├── CommPort.h ├── res ├── head.bmp ├── spm.bmp ├── Port2File.ico ├── Port2File.rc2 └── Port2File.manifest ├── stdafx.cpp ├── Port2File.h ├── consts.h ├── Port2File.sln ├── RedirectPort.h ├── stdafx.h ├── Port2File.cpp ├── README.md ├── resource.h ├── Port2FileDlg.h ├── Port2File.vcxproj.filters ├── Label.h ├── Port2File.vcproj ├── RedirectPort.cpp ├── Port2File.vcxproj ├── Port2File.rc ├── Port2FileDlg.cpp ├── LICENSE ├── CommPort.cpp └── Label.cpp /CommPort.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eltima-software/RS232-Data-Logger/HEAD/CommPort.h -------------------------------------------------------------------------------- /res/head.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eltima-software/RS232-Data-Logger/HEAD/res/head.bmp -------------------------------------------------------------------------------- /res/spm.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eltima-software/RS232-Data-Logger/HEAD/res/spm.bmp -------------------------------------------------------------------------------- /res/Port2File.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eltima-software/RS232-Data-Logger/HEAD/res/Port2File.ico -------------------------------------------------------------------------------- /stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // Port2File.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | 8 | -------------------------------------------------------------------------------- /res/Port2File.rc2: -------------------------------------------------------------------------------- 1 | // 2 | // Port2File.RC2 - resources Microsoft Visual C++ does not edit directly 3 | // 4 | 5 | #ifdef APSTUDIO_INVOKED 6 | #error this file is not editable by Microsoft Visual C++ 7 | #endif //APSTUDIO_INVOKED 8 | 9 | 10 | ///////////////////////////////////////////////////////////////////////////// 11 | // Add manually edited resources here... 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | -------------------------------------------------------------------------------- /Port2File.h: -------------------------------------------------------------------------------- 1 | // Port2File.h : main header file for the PROJECT_NAME application 2 | // 3 | 4 | #pragma once 5 | 6 | #ifndef __AFXWIN_H__ 7 | #error include 'stdafx.h' before including this file for PCH 8 | #endif 9 | 10 | #include "resource.h" // main symbols 11 | 12 | 13 | // CMainApp: 14 | // See Port2File.cpp for the implementation of this class 15 | // 16 | 17 | class CMainApp : public CWinApp 18 | { 19 | public: 20 | CMainApp(); 21 | 22 | // Overrides 23 | public: 24 | virtual BOOL InitInstance(); 25 | 26 | // Implementation 27 | 28 | DECLARE_MESSAGE_MAP() 29 | }; 30 | 31 | extern CMainApp theApp; -------------------------------------------------------------------------------- /res/Port2File.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your app description here 10 | 11 | 12 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /consts.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | const TCHAR VAL_BAUDRATE [][7] = { 5 | _T("100"), 6 | _T("300"), 7 | _T("600"), 8 | _T("1200"), 9 | _T("2400"), 10 | _T("4800"), 11 | _T("9600"), 12 | _T("14400"), 13 | _T("19200"), 14 | _T("38400"), 15 | _T("56000"), 16 | _T("57600"), 17 | _T("115200"), 18 | _T("128000"), 19 | _T("256000") }; 20 | const int NUM_BAUDRATE = 15; 21 | 22 | const TCHAR VAL_DATABITS [][2] = { 23 | _T("5"), 24 | _T("6"), 25 | _T("7"), 26 | _T("8") }; 27 | const int NUM_DATABITS = 4; 28 | 29 | const TCHAR VAL_PARITY [][6] = { 30 | _T("None"), 31 | _T("Odd"), 32 | _T("Even"), 33 | _T("Mark"), 34 | _T("Space") }; 35 | const int NUM_PARITY = 5; 36 | 37 | const TCHAR VAL_STOPBIT [3][4] = { _T("1"), _T("1,5"), _T("2") }; 38 | const int NUM_STOPBIT = 3; 39 | 40 | 41 | const TCHAR VAL_FC [][10] = { _T("None"), _T("Xon\\Xoff"), _T("Hardware") }; 42 | const int NUM_FC = 3; -------------------------------------------------------------------------------- /Port2File.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2010 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Port2File", "Port2File.vcxproj", "{5892FB7D-278E-45FE-A820-B2A323A30711}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Release|Win32 = Release|Win32 9 | Template|Win32 = Template|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5892FB7D-278E-45FE-A820-B2A323A30711}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {5892FB7D-278E-45FE-A820-B2A323A30711}.Debug|Win32.Build.0 = Debug|Win32 14 | {5892FB7D-278E-45FE-A820-B2A323A30711}.Release|Win32.ActiveCfg = Release|Win32 15 | {5892FB7D-278E-45FE-A820-B2A323A30711}.Release|Win32.Build.0 = Release|Win32 16 | {5892FB7D-278E-45FE-A820-B2A323A30711}.Template|Win32.ActiveCfg = Template|Win32 17 | {5892FB7D-278E-45FE-A820-B2A323A30711}.Template|Win32.Build.0 = Template|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /RedirectPort.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "commport.h" 3 | 4 | 5 | #define WM_USER_UPDATE_WND WM_USER + 5587 6 | #define WM_USER_CHANGE_STATUS WM_USER + 5588 7 | 8 | const TCHAR PREFERENCES_KEY[] = _T("Software\\Eltima\\Port2File"); 9 | // status codes 10 | enum 11 | { 12 | SC_NO_ERROR = 0, 13 | SC_OPEN_SUCCESS = 1, 14 | SC_OPEN_FILE_ERROR = 2, 15 | SC_OPEN_PORT_ERROR = 3, 16 | SC_FILE_EXCEPTION = 10 17 | }; 18 | 19 | class CRedirectPort : 20 | public CCommPort 21 | { 22 | private: 23 | CWnd* m_pParentWnd; 24 | CFile m_File; 25 | void OnRxChar( DWORD dwCount ); 26 | 27 | size_t m_stBytesInFile; 28 | size_t m_stBytesWritten; 29 | CString m_sPortName; 30 | int m_nIndex; 31 | 32 | public: 33 | bool m_bIsActive; 34 | BOOL m_bLogStarted; 35 | BOOL m_bAppend; 36 | CString m_sLogFile; 37 | CString m_sStatusMessage; 38 | 39 | DWORD m_dwBaudRate; 40 | int m_iIndexDataBits; 41 | int m_iIndexParity; 42 | int m_iIndexStopBits; 43 | int m_iIndexFlowCtrl; 44 | int m_iStatus; 45 | 46 | public: 47 | BOOL Open(); 48 | BOOL Open ( DWORD dwBaudrate, BYTE bDataBits, BYTE bParity, BYTE bStopBits, BYTE bFC ); 49 | void Close(); 50 | 51 | size_t GetFileTotalBytes() const { return m_stBytesInFile; } 52 | size_t GetFileWrittenBytes() const { return m_stBytesWritten; } 53 | 54 | BOOL SaveSettings (); 55 | BOOL LoadSettings (); 56 | 57 | CRedirectPort(const CString& sPortName, bool IsActive, CWnd* pWnd, int nIndex ); 58 | virtual ~CRedirectPort(void); 59 | }; 60 | -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, 3 | // but are changed infrequently 4 | 5 | #pragma once 6 | 7 | #ifndef VC_EXTRALEAN 8 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 9 | #endif 10 | 11 | // Modify the following defines if you have to target a platform prior to the ones specified below. 12 | // Refer to MSDN for the latest info on corresponding values for different platforms. 13 | #ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. 14 | #define WINVER 0x0500 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. 15 | #endif 16 | 17 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. 18 | #define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. 19 | #endif 20 | 21 | #ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. 22 | #define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later. 23 | #endif 24 | 25 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 26 | 27 | // turns off MFC's hiding of some common and often safely ignored warning messages 28 | #define _AFX_ALL_WARNINGS 29 | 30 | #include // MFC core and standard components 31 | #include // MFC extensions 32 | 33 | #include // MFC support for Internet Explorer 4 Common Controls 34 | #ifndef _AFX_NO_AFXCMN_SUPPORT 35 | #include // MFC support for Windows Common Controls 36 | #endif // _AFX_NO_AFXCMN_SUPPORT 37 | 38 | -------------------------------------------------------------------------------- /Port2File.cpp: -------------------------------------------------------------------------------- 1 | // Port2File.cpp : Defines the class behaviors for the application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "Port2File.h" 6 | #include "Port2FileDlg.h" 7 | 8 | #ifdef _DEBUG 9 | #define new DEBUG_NEW 10 | #endif 11 | 12 | 13 | // CMainApp 14 | 15 | BEGIN_MESSAGE_MAP(CMainApp, CWinApp) 16 | ON_COMMAND(ID_HELP, CWinApp::OnHelp) 17 | END_MESSAGE_MAP() 18 | 19 | 20 | // CMainApp construction 21 | 22 | CMainApp::CMainApp() 23 | { 24 | // TODO: add construction code here, 25 | // Place all significant initialization in InitInstance 26 | } 27 | 28 | 29 | // The one and only CMainApp object 30 | 31 | CMainApp theApp; 32 | 33 | 34 | // CMainApp initialization 35 | 36 | BOOL CMainApp::InitInstance() 37 | { 38 | // InitCommonControls() is required on Windows XP if an application 39 | // manifest specifies use of ComCtl32.dll version 6 or later to enable 40 | // visual styles. Otherwise, any window creation will fail. 41 | InitCommonControls(); 42 | 43 | CWinApp::InitInstance(); 44 | 45 | // Standard initialization 46 | // If you are not using these features and wish to reduce the size 47 | // of your final executable, you should remove from the following 48 | // the specific initialization routines you do not need 49 | // Change the registry key under which our settings are stored 50 | // TODO: You should modify this string to be something appropriate 51 | // such as the name of your company or organization 52 | SetRegistryKey(_T("Local AppWizard-Generated Applications")); 53 | 54 | CRedirectDlg dlg; 55 | m_pMainWnd = &dlg; 56 | INT_PTR nResponse = dlg.DoModal(); 57 | if (nResponse == IDOK) 58 | { 59 | // TODO: Place code here to handle when the dialog is 60 | // dismissed with OK 61 | } 62 | else if (nResponse == IDCANCEL) 63 | { 64 | // TODO: Place code here to handle when the dialog is 65 | // dismissed with Cancel 66 | } 67 | 68 | // Since the dialog has been closed, return FALSE so that we exit the 69 | // application, rather than start the application's message pump. 70 | return FALSE; 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RS232 Data Logger 2 | 3 | ## How Serial Port Logger solves it 4 | 5 | RS232 Data Logger is quite easy to use. It is a one-window application where you can choose the COM ports for monitoring, specify the file to save logged info to, and define serial port settings (baud rate, stop bits, number of bits to transmit, parity checking, and flow control types). All collected data is saved in a text file that you can later read and fully analyze all data you need. 6 | 7 | ## Log serial port communication, view and analyze logged data 8 | 9 | With [free serial port monitor](https://www.com-port-monitoring.com/) you can connect to real or virtual serial port and monitor the transmitted data. Specify the text document to save all intercepted data to for your analysis. RS232 Logger will display how many bytes are stored in the log file and all data logged from the serial port in a comprehensive way. 10 | 11 | ## Test serial communication 12 | 13 | RS232 Data Logger is a handy tool for testing serial port communication. As all data is saved into the log file, it can be analyzed later for any errors in commands or data. RS232 Data Logger can capture data streams of up to 256 COM ports. 14 | 15 | ## Supported operating systems 16 | 17 | * Windows 10 (32-bit and 64-bit) 18 | * Windows server 2012 19 | * Windows 8 (32-bit and 64-bit) 20 | * Windows 7 (32-bit and 64-bit) 21 | * Windows 2008 (32-bit and 64-bit) 22 | * Windows 2003 (32-bit and 64-bit) 23 | * Windows Vista (32-bit and 64-bit) 24 | * Windows XP (32-bit and 64-bit) 25 | * Windows 2000 26 | * Windows NT 4.x 27 | * Windows Me 28 | * Windows 98 29 | 30 | Note, that this is an open source software and you can only use it for non proprietary purposes. If you want to distribute it as a part of your own non-Open Source software product, it's required to obtain appropriate license from Eltima Software (sales@eltima.com) 31 | 32 | If you are looking for more powerful tool, Serial Port Logger is an advanced edition of a free serial port monitor with extra features. https://www.eltima.com/products/rs232-data-logger/ 33 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Port2File.rc 4 | // 5 | #define IDM_ABOUTBOX 16 6 | #define IDD_ABOUTBOX 100 7 | #define IDS_ABOUTBOX 101 8 | #define IDD_PORT2FILE_DIALOG 102 9 | #define IDR_MAINFRAME 128 10 | #define IDB_BMP_HEAD 132 11 | #define IDB_SPM 134 12 | #define IDC_CB_BAUDRATE 1005 13 | #define IDC_CB_DATABITS 1006 14 | #define IDC_CB_PARITY 1007 15 | #define IDC_CB_STOPBITS 1008 16 | #define IDC_CB_FC 1009 17 | #define IDC_EDIT2 1010 18 | #define IDC_ED_LOGFILE 1010 19 | #define IDC_BT_VIEW 1011 20 | #define IDC_CHECK_APPEND 1015 21 | #define IDC_LIST_PORTS 1018 22 | #define IDC_BT_STARTLOG 1019 23 | #define IDC_STATIC_2 1025 24 | #define IDC_STATIC_3 1026 25 | #define IDC_STATIC_4 1027 26 | #define IDC_STATIC_5 1028 27 | #define IDC_STATIC_6 1029 28 | #define IDC_STATIC_9 1031 29 | #define IDC_STATIC_A 1032 30 | #define IDC_BT_HELP 1033 31 | #define IDC_STATIC_HOME 1034 32 | #define IDC_STATIC_STATUS 1037 33 | #define IDC_STATIC_RECV 1038 34 | #define IDC_STATIC_TOTAL 1039 35 | #define IDC_BT_HIDE 1040 36 | #define IDC_STATIC_CAPTION 1041 37 | #define IDC_STATIC_TEXT 1042 38 | #define IDC_STATIC_HYPERLINK 1043 39 | 40 | // Next default values for new objects 41 | // 42 | #ifdef APSTUDIO_INVOKED 43 | #ifndef APSTUDIO_READONLY_SYMBOLS 44 | #define _APS_NEXT_RESOURCE_VALUE 135 45 | #define _APS_NEXT_COMMAND_VALUE 32771 46 | #define _APS_NEXT_CONTROL_VALUE 1044 47 | #define _APS_NEXT_SYMED_VALUE 102 48 | #endif 49 | #endif 50 | -------------------------------------------------------------------------------- /Port2FileDlg.h: -------------------------------------------------------------------------------- 1 | // Port2FileDlg.h : header file 2 | // 3 | 4 | #pragma once 5 | #include "afxcmn.h" 6 | #include "afxwin.h" 7 | #include "RedirectPort.h" 8 | #include 9 | #include "label.h" 10 | 11 | // CRedirectDlg dialog 12 | class CRedirectDlg : public CDialog 13 | { 14 | // Construction 15 | public: 16 | CRedirectDlg(CWnd* pParent = NULL); // standard constructor 17 | 18 | // Dialog Data 19 | enum { IDD = IDD_PORT2FILE_DIALOG }; 20 | 21 | protected: 22 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 23 | 24 | private: 25 | CListCtrl m_ListPorts; 26 | CImageList m_IconList; 27 | CLabel m_HomeHlink; 28 | 29 | CString m_sErrorStatus; 30 | CString m_sLogFile; 31 | CString m_sRecvBytes; 32 | CString m_sTotalFileSize; 33 | 34 | CComboBox m_cbBaudrate; 35 | CComboBox m_cbDataBits; 36 | CComboBox m_cbParity; 37 | CComboBox m_cbStopBits; 38 | CComboBox m_cbFC; 39 | 40 | BOOL m_bFileAppend; 41 | int m_iCurItemSel; 42 | 43 | 44 | std::vector m_Ports; 45 | 46 | void GetAvailablePorts(); 47 | void UpdateSettings (); 48 | //void StartLogging ( int iPort ); 49 | 50 | LRESULT OnWriteUpdate ( WPARAM, LPARAM ); 51 | LRESULT OnWriteStatus ( WPARAM, LPARAM ); 52 | 53 | // Implementation 54 | protected: 55 | HICON m_hIcon; 56 | 57 | // Generated message map functions 58 | virtual BOOL OnInitDialog(); 59 | afx_msg void OnPaint(); 60 | afx_msg HCURSOR OnQueryDragIcon(); 61 | DECLARE_MESSAGE_MAP() 62 | public: 63 | 64 | afx_msg void OnBnClickedBtView(); 65 | afx_msg void OnBnClickedBtStartlog(); 66 | afx_msg void OnBnClickedCheckLog(); 67 | afx_msg void OnBnClickedBtHelp(); 68 | 69 | protected: 70 | virtual void OnOK(); 71 | virtual void OnCancel(); 72 | 73 | protected: 74 | virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); 75 | void OnCustomdrawList ( NMHDR* pNMHDR, LRESULT* pResult ); 76 | public: 77 | afx_msg void OnHdnGetdispinfoListPorts (NMHDR *pNMHDR, LRESULT *pResult); 78 | afx_msg void OnLvnItemActivateListPorts(NMHDR *pNMHDR, LRESULT *pResult); 79 | afx_msg void OnLvnItemchangedListPorts (NMHDR *pNMHDR, LRESULT *pResult); 80 | afx_msg void OnLvnItemchangingListPorts(NMHDR *pNMHDR, LRESULT *pResult); 81 | afx_msg void OnCbnSelchangeCbBaudrate (); 82 | afx_msg void OnCbnSelchangeCbDatabits (); 83 | afx_msg void OnCbnSelchangeCbParity (); 84 | afx_msg void OnCbnSelchangeCbStopbits (); 85 | afx_msg void OnCbnSelchangeCbFc (); 86 | afx_msg void OnBnClickedCheckAppend (); 87 | afx_msg void OnEnChangeEdLogfile (); 88 | }; 89 | -------------------------------------------------------------------------------- /Port2File.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | 64 | 65 | Resource Files 66 | 67 | 68 | Resource Files 69 | 70 | 71 | Resource Files 72 | 73 | 74 | Resource Files 75 | 76 | 77 | 78 | 79 | 80 | Resource Files 81 | 82 | 83 | -------------------------------------------------------------------------------- /Label.h: -------------------------------------------------------------------------------- 1 | #if !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_) 2 | #define AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_ 3 | 4 | #if _MSC_VER >= 1000 5 | #pragma once 6 | #endif // _MSC_VER >= 1000 7 | // Label.h : header file 8 | // 9 | 10 | #define NM_LINKCLICK WM_APP + 0x200 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | // CLabel window 14 | 15 | class CLabel : public CStatic 16 | { 17 | // Construction 18 | public: 19 | 20 | 21 | static enum LinkStyle { LinkNone, HyperLink, MailLink }; 22 | static enum FlashType {None, Text, Background }; 23 | static enum Type3D { Raised, Sunken}; 24 | static enum BackFillMode { Normal, Gradient }; 25 | 26 | CLabel(); 27 | virtual CLabel& SetBkColor(COLORREF crBkgnd, COLORREF crBkgndHigh = 0, BackFillMode mode = Normal); 28 | virtual CLabel& SetTextColor(COLORREF crText); 29 | virtual CLabel& SetText(const CString& strText); 30 | virtual CLabel& SetFontBold(BOOL bBold); 31 | virtual CLabel& SetFontName(const CString& strFont, BYTE byCharSet = ANSI_CHARSET); 32 | virtual CLabel& SetFontUnderline(BOOL bSet); 33 | virtual CLabel& SetFontItalic(BOOL bSet); 34 | virtual CLabel& SetFontSize(int nSize); 35 | virtual CLabel& SetSunken(BOOL bSet); 36 | virtual CLabel& SetBorder(BOOL bSet); 37 | virtual CLabel& SetTransparent(BOOL bSet); 38 | virtual CLabel& FlashText(BOOL bActivate); 39 | virtual CLabel& FlashBackground(BOOL bActivate); 40 | virtual CLabel& SetLink(BOOL bLink,BOOL bNotifyParent); 41 | virtual CLabel& SetLinkCursor(HCURSOR hCursor); 42 | virtual CLabel& SetFont3D(BOOL bSet,Type3D type=Raised); 43 | virtual CLabel& SetRotationAngle(UINT nAngle,BOOL bRotation); 44 | virtual CLabel& SetText3DHiliteColor(COLORREF cr3DHiliteColor); 45 | virtual CLabel& SetFont(LOGFONT lf); 46 | virtual CLabel& SetMailLink(BOOL bEnable, BOOL bNotifyParent); 47 | virtual CLabel& SetHyperLink(const CString& sLink); 48 | 49 | // Attributes 50 | public: 51 | protected: 52 | void UpdateSurface(); 53 | void ReconstructFont(); 54 | void DrawGradientFill(CDC* pDC, CRect* pRect, COLORREF crStart, COLORREF crEnd, int nSegments); 55 | COLORREF m_crText; 56 | COLORREF m_cr3DHiliteColor; 57 | HBRUSH m_hwndBrush; 58 | HBRUSH m_hBackBrush; 59 | LOGFONT m_lf; 60 | CFont m_font; 61 | BOOL m_bState; 62 | BOOL m_bTimer; 63 | LinkStyle m_Link; 64 | BOOL m_bTransparent; 65 | BOOL m_bFont3d; 66 | BOOL m_bToolTips; 67 | BOOL m_bNotifyParent; 68 | BOOL m_bRotation; 69 | FlashType m_Type; 70 | HCURSOR m_hCursor; 71 | Type3D m_3dType; 72 | BackFillMode m_fillmode; 73 | COLORREF m_crHiColor; 74 | COLORREF m_crLoColor; 75 | CString m_sLink; 76 | 77 | // Operations 78 | public: 79 | 80 | // Overrides 81 | // ClassWizard generated virtual function overrides 82 | //{{AFX_VIRTUAL(CLabel) 83 | protected: 84 | virtual void PreSubclassWindow(); 85 | virtual BOOL PreCreateWindow(CREATESTRUCT& cs); 86 | //}}AFX_VIRTUAL 87 | 88 | // Implementation 89 | public: 90 | virtual ~CLabel(); 91 | 92 | // Generated message map functions 93 | protected: 94 | //{{AFX_MSG(CLabel) 95 | afx_msg void OnTimer(UINT nIDEvent); 96 | afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 97 | afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); 98 | afx_msg void OnSysColorChange(); 99 | afx_msg void OnPaint(); 100 | afx_msg BOOL OnEraseBkgnd(CDC* pDC); 101 | //}}AFX_MSG 102 | 103 | DECLARE_MESSAGE_MAP() 104 | }; 105 | 106 | ///////////////////////////////////////////////////////////////////////////// 107 | 108 | //{{AFX_INSERT_LOCATION}} 109 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 110 | 111 | #endif // !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_) 112 | -------------------------------------------------------------------------------- /Port2File.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 13 | 20 | 32 | 34 | 40 | 44 | 46 | 48 | 50 | 55 | 57 | 59 | 61 | 63 | 65 | 66 | 73 | 83 | 85 | 94 | 98 | 100 | 102 | 104 | 109 | 111 | 113 | 115 | 117 | 119 | 120 | 121 | 122 | 123 | 124 | 128 | 130 | 131 | 133 | 134 | 136 | 137 | 139 | 140 | 142 | 143 | 145 | 147 | 150 | 151 | 153 | 156 | 157 | 158 | 159 | 163 | 165 | 166 | 168 | 169 | 171 | 172 | 174 | 175 | 177 | 178 | 180 | 181 | 183 | 184 | 186 | 187 | 188 | 192 | 194 | 195 | 197 | 198 | 200 | 201 | 203 | 204 | 206 | 207 | 208 | 210 | 211 | 213 | 214 | 215 | 216 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /RedirectPort.cpp: -------------------------------------------------------------------------------- 1 | #include "StdAfx.h" 2 | #include ".\redirectport.h" 3 | 4 | CRedirectPort::CRedirectPort(const CString& sPortName, bool IsActive, CWnd* pWnd, int nIndex ): 5 | CCommPort() 6 | { 7 | m_bIsActive = IsActive; 8 | m_pParentWnd = pWnd; 9 | ASSERT( m_pParentWnd ); 10 | 11 | m_sPortName = sPortName; 12 | m_sLogFile = _T(""); 13 | m_sStatusMessage = _T("Ready to start"); 14 | 15 | m_bLogStarted = FALSE; 16 | m_bAppend = FALSE; 17 | 18 | m_nIndex = nIndex; 19 | // this is indexes 20 | m_dwBaudRate = 9600; 21 | m_iIndexDataBits = 3; 22 | m_iIndexParity = 0; 23 | m_iIndexStopBits = 0; 24 | m_iIndexFlowCtrl = 2; 25 | 26 | m_stBytesInFile = 0; 27 | m_stBytesWritten = 0; 28 | } 29 | 30 | CRedirectPort::~CRedirectPort(void) 31 | { 32 | if ( IsOpen() ) 33 | Close(); 34 | } 35 | 36 | void CRedirectPort::OnRxChar( DWORD dwCount ) 37 | { 38 | BYTE buffer[4096]; 39 | DWORD dwSymbolsRead = Read( (VOID*)buffer, 4096 ); 40 | 41 | try 42 | { 43 | m_File.Write( buffer, dwSymbolsRead ); 44 | 45 | m_stBytesWritten += dwSymbolsRead; 46 | m_stBytesInFile += dwSymbolsRead; 47 | if ( m_bIsActive ) 48 | { 49 | m_pParentWnd ->PostMessage( WM_USER_UPDATE_WND, 0, 0 ); 50 | } 51 | } 52 | catch( CFileException *e ) 53 | { 54 | 55 | 56 | TCHAR *lpszCause = m_sStatusMessage.GetBufferSetLength( 255 ); 57 | 58 | if ( !e ->GetErrorMessage( lpszCause, 255 ) ) 59 | m_sStatusMessage = _T("File error"); 60 | 61 | m_pParentWnd ->PostMessage( WM_USER_UPDATE_WND, m_nIndex, SC_FILE_EXCEPTION ); 62 | 63 | e->Delete(); 64 | } 65 | } 66 | 67 | BOOL CRedirectPort::Open() 68 | { 69 | return Open( m_dwBaudRate, m_iIndexDataBits + 5, m_iIndexParity, m_iIndexStopBits, m_iIndexFlowCtrl ); 70 | } 71 | 72 | BOOL CRedirectPort::Open( DWORD dwBaudrate, BYTE bDataBits, BYTE bParity, BYTE bStopBits, BYTE bFC ) 73 | { 74 | UINT nOpenFlags = CFile::modeWrite | CFile::shareDenyNone | CFile::modeCreate; 75 | if( m_bAppend ) 76 | { 77 | nOpenFlags |= CFile::modeNoTruncate; 78 | } 79 | 80 | if ( m_File.Open( m_sLogFile, nOpenFlags ) ) 81 | { 82 | if ( m_bAppend ) 83 | { 84 | m_File.SeekToEnd(); 85 | CFileStatus fsStatus; 86 | m_File.GetStatus( fsStatus ); 87 | m_stBytesInFile = (size_t)fsStatus.m_size; 88 | } 89 | 90 | if( CCommPort::Open( m_sPortName, dwBaudrate, bDataBits, bStopBits, bParity, bFC ) ) 91 | { 92 | COMMTIMEOUTS Timeouts; 93 | memset( (LPVOID)&Timeouts, 0, sizeof(Timeouts)); 94 | 95 | Timeouts.ReadTotalTimeoutConstant = 300; 96 | Timeouts.WriteTotalTimeoutConstant = 300; 97 | SetTimeouts( &Timeouts ); 98 | m_pParentWnd ->PostMessage( WM_USER_CHANGE_STATUS, m_nIndex, SC_OPEN_SUCCESS ); 99 | 100 | m_sStatusMessage = _T("Logging started"); 101 | 102 | return TRUE; 103 | } 104 | else 105 | { 106 | m_iStatus = SC_OPEN_PORT_ERROR; 107 | m_sStatusMessage = _T("Unable open port"); 108 | m_pParentWnd ->PostMessage( WM_USER_CHANGE_STATUS, m_nIndex, SC_OPEN_PORT_ERROR ); 109 | 110 | m_File.Close(); 111 | return FALSE; 112 | } 113 | } 114 | else 115 | { 116 | m_sStatusMessage = _T("Unable open file"); 117 | m_pParentWnd ->PostMessage( WM_USER_CHANGE_STATUS, m_nIndex, SC_OPEN_FILE_ERROR ); 118 | return FALSE; 119 | } 120 | } 121 | 122 | void CRedirectPort::Close() 123 | { 124 | m_File.Close(); 125 | CCommPort::Close(); 126 | 127 | m_sStatusMessage = _T("Logging stopped"); 128 | } 129 | 130 | BOOL CRedirectPort::SaveSettings() 131 | { 132 | HKEY hKey = NULL; 133 | 134 | CString sPreferenceKey( PREFERENCES_KEY ); 135 | 136 | sPreferenceKey += _T("\\"); 137 | sPreferenceKey += m_sPortName; 138 | 139 | DWORD dwDisposition; 140 | if ( RegCreateKeyEx( HKEY_CURRENT_USER, sPreferenceKey, 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 141 | NULL, &hKey, &dwDisposition ) != ERROR_SUCCESS ) 142 | { 143 | return FALSE; 144 | } 145 | 146 | // start logging 147 | DWORD dwStarted = (DWORD)m_bLogStarted; 148 | RegSetValueEx( hKey, _T("logging"), 0, REG_DWORD, (BYTE*)&dwStarted, 4 ); 149 | 150 | // redirect file 151 | RegSetValueEx( hKey, _T("file"), 0, REG_SZ, (BYTE*)(LPCTSTR)m_sLogFile, m_sLogFile.GetLength() * sizeof (TCHAR) ); 152 | 153 | 154 | // check append 155 | RegSetValueEx( hKey, _T("append"), 0, REG_DWORD,(BYTE*)&m_bAppend, 4 ); 156 | // port options 157 | RegSetValueEx( hKey, _T("baudrate"), 0, REG_DWORD,(BYTE*)&m_dwBaudRate, 4 ); 158 | 159 | RegSetValueEx( hKey, _T("databits"), 0, REG_DWORD,(BYTE*)&m_iIndexDataBits, 4 ); 160 | 161 | RegSetValueEx( hKey, _T("parity"), 0, REG_DWORD,(BYTE*)&m_iIndexParity, 4 ); 162 | 163 | RegSetValueEx( hKey, _T("stopbits"), 0, REG_DWORD,(BYTE*)&m_iIndexStopBits, 4 ); 164 | 165 | RegSetValueEx( hKey, _T("flowctrl"), 0, REG_DWORD,(BYTE*)&m_iIndexFlowCtrl, 4 ); 166 | 167 | return TRUE; 168 | } 169 | 170 | BOOL CRedirectPort::LoadSettings ( ) 171 | { 172 | HKEY hKey = NULL; 173 | 174 | CString sPreferenceKey( PREFERENCES_KEY ); 175 | sPreferenceKey += _T("\\"); 176 | sPreferenceKey += m_sPortName; 177 | 178 | if ( RegOpenKeyEx( HKEY_CURRENT_USER, sPreferenceKey, 0, KEY_ALL_ACCESS, &hKey ) != ERROR_SUCCESS ) 179 | { 180 | return FALSE; 181 | } 182 | 183 | DWORD cValues; // number of values for key 184 | DWORD cchMaxValue; // longest value name 185 | DWORD cbMaxValueData; // longest value data 186 | BYTE bData [1024]; 187 | DWORD dwDataLen = 1024; 188 | 189 | DWORD retCode; 190 | TCHAR achValue[254]; 191 | DWORD cchValue = 255; //16383; 192 | 193 | // Get the class name and the value count. 194 | retCode = RegQueryInfoKey( hKey, NULL, NULL, NULL, NULL, NULL, NULL, 195 | &cValues, &cchMaxValue, &cbMaxValueData, NULL, NULL); 196 | // search values of keys 197 | if (cValues) 198 | { 199 | for (DWORD i=0, retCode=ERROR_SUCCESS; i 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Template 14 | Win32 15 | 16 | 17 | 18 | {5892FB7D-278E-45FE-A820-B2A323A30711} 19 | MFCProj 20 | 21 | 22 | 23 | Application 24 | Static 25 | MultiByte 26 | 27 | 28 | Application 29 | Static 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | <_ProjectFileVersion>10.0.40219.1 44 | Debug\ 45 | Debug\ 46 | true 47 | Release\ 48 | Release\ 49 | false 50 | AllRules.ruleset 51 | 52 | 53 | AllRules.ruleset 54 | 55 | 56 | AllRules.ruleset 57 | 58 | 59 | 60 | 61 | 62 | Disabled 63 | WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) 64 | true 65 | EnableFastChecks 66 | MultiThreadedDebug 67 | true 68 | Use 69 | Level3 70 | EditAndContinue 71 | 72 | 73 | true 74 | Windows 75 | MachineX86 76 | 77 | 78 | _DEBUG;%(PreprocessorDefinitions) 79 | false 80 | 81 | 82 | _DEBUG;%(PreprocessorDefinitions) 83 | 0x0409 84 | $(IntDir);%(AdditionalIncludeDirectories) 85 | 86 | 87 | 88 | 89 | WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) 90 | false 91 | MultiThreaded 92 | true 93 | Use 94 | Level3 95 | ProgramDatabase 96 | 97 | 98 | $(OutDir)DataLogger.exe 99 | true 100 | Windows 101 | true 102 | true 103 | MachineX86 104 | 105 | 106 | NDEBUG;%(PreprocessorDefinitions) 107 | false 108 | 109 | 110 | NDEBUG;%(PreprocessorDefinitions) 111 | 0x0409 112 | $(IntDir);%(AdditionalIncludeDirectories) 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | Create 123 | Create 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /Port2File.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "afxres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // Russian (Russia) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) 19 | LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT 20 | #pragma code_page(1251) 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""afxres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "#define _AFX_NO_SPLITTER_RESOURCES\r\n" 42 | "#define _AFX_NO_OLE_RESOURCES\r\n" 43 | "#define _AFX_NO_TRACKER_RESOURCES\r\n" 44 | "#define _AFX_NO_PROPERTY_RESOURCES\r\n" 45 | "\r\n" 46 | "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" 47 | "LANGUAGE 9, 1\r\n" 48 | "#pragma code_page(1252)\r\n" 49 | "#include ""res\\Port2File.rc2"" // non-Microsoft Visual C++ edited resources\r\n" 50 | "#include ""afxres.rc"" // Standard components\r\n" 51 | "#endif\r\n" 52 | "\0" 53 | END 54 | 55 | #endif // APSTUDIO_INVOKED 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Accelerator 61 | // 62 | 63 | IDR_ACCELERATOR1 ACCELERATORS 64 | BEGIN 65 | VK_F1, ID_HELP, VIRTKEY, NOINVERT 66 | END 67 | 68 | #endif // Russian (Russia) resources 69 | ///////////////////////////////////////////////////////////////////////////// 70 | 71 | 72 | ///////////////////////////////////////////////////////////////////////////// 73 | // English (United States) resources 74 | 75 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 76 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 77 | #pragma code_page(1252) 78 | 79 | ///////////////////////////////////////////////////////////////////////////// 80 | // 81 | // Icon 82 | // 83 | 84 | // Icon with lowest ID value placed first to ensure application icon 85 | // remains consistent on all systems. 86 | IDR_MAINFRAME ICON "res\\Port2File.ico" 87 | 88 | ///////////////////////////////////////////////////////////////////////////// 89 | // 90 | // Dialog 91 | // 92 | 93 | IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55 94 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU 95 | CAPTION "About Port2File" 96 | FONT 8, "MS Shell Dlg", 0, 0, 0x1 97 | BEGIN 98 | ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 99 | LTEXT "Port2File Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX 100 | LTEXT "Copyright (C) 2006",IDC_STATIC,40,25,119,8 101 | DEFPUSHBUTTON "OK",IDOK,178,7,50,16,WS_GROUP 102 | END 103 | 104 | IDD_PORT2FILE_DIALOG DIALOGEX 0, 0, 304, 286 105 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU 106 | EXSTYLE WS_EX_APPWINDOW 107 | CAPTION "RS232 DataLogger by Eltima Software 2.7 freeware" 108 | FONT 8, "MS Shell Dlg", 0, 0, 0x1 109 | BEGIN 110 | CONTROL "",IDC_LIST_PORTS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,7,80,115,186 111 | EDITTEXT IDC_ED_LOGFILE,129,80,150,12,ES_AUTOHSCROLL 112 | PUSHBUTTON " ...",IDC_BT_VIEW,281,80,16,12 113 | PUSHBUTTON "Start logging",IDC_BT_STARTLOG,128,252,111,14,WS_DISABLED 114 | COMBOBOX IDC_CB_BAUDRATE,174,121,120,126,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP 115 | COMBOBOX IDC_CB_DATABITS,174,136,120,109,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP 116 | COMBOBOX IDC_CB_PARITY,174,151,120,107,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP 117 | COMBOBOX IDC_CB_STOPBITS,174,166,120,91,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP 118 | COMBOBOX IDC_CB_FC,174,181,120,92,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP 119 | LTEXT "Baudrate",IDC_STATIC_2,132,125,30,8 120 | LTEXT "Data bits",IDC_STATIC_3,132,139,30,8 121 | LTEXT "Parity",IDC_STATIC_4,132,154,20,8 122 | LTEXT "Stop bits",IDC_STATIC_5,132,169,29,8 123 | LTEXT "Flow control",IDC_STATIC_6,132,184,40,8 124 | CONTROL "Append to file",IDC_CHECK_APPEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,129,96,61,10 125 | LTEXT "Total bytes in file",IDC_STATIC_A,133,224,56,8 126 | LTEXT "Bytes received from port",IDC_STATIC_9,133,212,80,8 127 | CONTROL 132,IDC_STATIC,"Static",SS_BITMAP,0,0,304,62 128 | LTEXT "Available ports",IDC_STATIC,8,67,48,8 129 | PUSHBUTTON "Help",IDC_BT_HELP,242,252,55,14 130 | LTEXT "Eltima Software GmbH - click for other products",IDC_STATIC_HOME,63,271,196,8 131 | LTEXT "Status",IDC_STATIC,134,235,22,8 132 | LTEXT "Static",IDC_STATIC_STATUS,177,235,116,8 133 | LTEXT "Static",IDC_STATIC_RECV,218,212,75,8 134 | LTEXT "Static",IDC_STATIC_TOTAL,218,224,75,8 135 | GROUPBOX "Serial port options",IDC_STATIC,128,110,170,90 136 | GROUPBOX "Statistics",IDC_STATIC,128,201,169,48 137 | END 138 | 139 | 140 | ///////////////////////////////////////////////////////////////////////////// 141 | // 142 | // Version 143 | // 144 | 145 | VS_VERSION_INFO VERSIONINFO 146 | FILEVERSION 2,7,0,117 147 | PRODUCTVERSION 2,7,0,117 148 | FILEFLAGSMASK 0x3fL 149 | #ifdef _DEBUG 150 | FILEFLAGS 0x1L 151 | #else 152 | FILEFLAGS 0x0L 153 | #endif 154 | FILEOS 0x4L 155 | FILETYPE 0x1L 156 | FILESUBTYPE 0x0L 157 | BEGIN 158 | BLOCK "StringFileInfo" 159 | BEGIN 160 | BLOCK "040904e4" 161 | BEGIN 162 | VALUE "CompanyName", "Eltima Software" 163 | VALUE "FileDescription", "RS232 Data Logger" 164 | VALUE "FileVersion", "2.7.0.117" 165 | VALUE "InternalName", "DataLogger.exe" 166 | VALUE "LegalCopyright", " (c) Eltima Software. All rights reserved." 167 | VALUE "OriginalFilename", "DataLogger.exe" 168 | VALUE "ProductName", "RS232 Data Logger" 169 | VALUE "ProductVersion", "2.7.0.117" 170 | END 171 | END 172 | BLOCK "VarFileInfo" 173 | BEGIN 174 | VALUE "Translation", 0x409, 1252 175 | END 176 | END 177 | 178 | 179 | ///////////////////////////////////////////////////////////////////////////// 180 | // 181 | // DESIGNINFO 182 | // 183 | 184 | #ifdef APSTUDIO_INVOKED 185 | GUIDELINES DESIGNINFO 186 | BEGIN 187 | IDD_ABOUTBOX, DIALOG 188 | BEGIN 189 | LEFTMARGIN, 7 190 | RIGHTMARGIN, 228 191 | TOPMARGIN, 7 192 | BOTTOMMARGIN, 48 193 | END 194 | 195 | IDD_PORT2FILE_DIALOG, DIALOG 196 | BEGIN 197 | VERTGUIDE, 7 198 | VERTGUIDE, 128 199 | VERTGUIDE, 174 200 | VERTGUIDE, 297 201 | BOTTOMMARGIN, 280 202 | HORZGUIDE, 58 203 | HORZGUIDE, 80 204 | HORZGUIDE, 91 205 | HORZGUIDE, 266 206 | END 207 | END 208 | #endif // APSTUDIO_INVOKED 209 | 210 | 211 | ///////////////////////////////////////////////////////////////////////////// 212 | // 213 | // Bitmap 214 | // 215 | 216 | IDB_BMP_HEAD BITMAP "res\\head.bmp" 217 | IDB_SPM BITMAP "res\\spm.bmp" 218 | 219 | ///////////////////////////////////////////////////////////////////////////// 220 | // 221 | // String Table 222 | // 223 | 224 | STRINGTABLE 225 | BEGIN 226 | IDS_ABOUTBOX "&About Port2File..." 227 | END 228 | 229 | #endif // English (United States) resources 230 | ///////////////////////////////////////////////////////////////////////////// 231 | 232 | 233 | 234 | #ifndef APSTUDIO_INVOKED 235 | ///////////////////////////////////////////////////////////////////////////// 236 | // 237 | // Generated from the TEXTINCLUDE 3 resource. 238 | // 239 | #define _AFX_NO_SPLITTER_RESOURCES 240 | #define _AFX_NO_OLE_RESOURCES 241 | #define _AFX_NO_TRACKER_RESOURCES 242 | #define _AFX_NO_PROPERTY_RESOURCES 243 | 244 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 245 | LANGUAGE 9, 1 246 | #pragma code_page(1252) 247 | #include "res\Port2File.rc2" // non-Microsoft Visual C++ edited resources 248 | #include "afxres.rc" // Standard components 249 | #endif 250 | 251 | ///////////////////////////////////////////////////////////////////////////// 252 | #endif // not APSTUDIO_INVOKED 253 | 254 | -------------------------------------------------------------------------------- /Port2FileDlg.cpp: -------------------------------------------------------------------------------- 1 | // Port2FileDlg.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "Port2File.h" 6 | #include "Port2FileDlg.h" 7 | #include ".\port2filedlg.h" 8 | #include "consts.h" 9 | 10 | #ifdef _DEBUG 11 | #define new DEBUG_NEW 12 | #endif 13 | 14 | const TCHAR STRING_DISABLE [] = _T("[Stopped]"); 15 | const TCHAR STRING_ENABLE [] = _T("[Started]"); 16 | const TCHAR STRING_ERROR [] = _T("[Error]"); 17 | 18 | 19 | ///////////////////////////////////////////////////////////// 20 | // 21 | // CRedirectDlg dialog 22 | // 23 | ///////////////////////////////////////////////////////////// 24 | 25 | CRedirectDlg::CRedirectDlg(CWnd* pParent /*=NULL*/) 26 | : CDialog(CRedirectDlg::IDD, pParent) 27 | , m_bFileAppend(FALSE) 28 | , m_sLogFile(_T("")) 29 | , m_iCurItemSel(0) 30 | , m_sRecvBytes(_T("0 bytes")) 31 | , m_sTotalFileSize(_T("0 bytes")) 32 | , m_sErrorStatus(_T("")) 33 | { 34 | m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 35 | } 36 | 37 | void CRedirectDlg::DoDataExchange(CDataExchange* pDX) 38 | { 39 | CDialog::DoDataExchange(pDX); 40 | DDX_Control(pDX, IDC_LIST_PORTS, m_ListPorts); 41 | DDX_Check(pDX, IDC_CHECK_APPEND, m_bFileAppend); 42 | DDX_Control(pDX, IDC_CB_BAUDRATE, m_cbBaudrate); 43 | DDX_Control(pDX, IDC_CB_DATABITS, m_cbDataBits); 44 | DDX_Control(pDX, IDC_CB_PARITY, m_cbParity); 45 | DDX_Control(pDX, IDC_CB_STOPBITS, m_cbStopBits); 46 | DDX_Control(pDX, IDC_CB_FC, m_cbFC); 47 | DDX_Text(pDX, IDC_ED_LOGFILE, m_sLogFile); 48 | DDX_Text(pDX, IDC_STATIC_RECV, m_sRecvBytes); 49 | DDX_Text(pDX, IDC_STATIC_TOTAL, m_sTotalFileSize); 50 | DDX_Control(pDX, IDC_STATIC_HOME, m_HomeHlink); 51 | DDX_Text(pDX, IDC_STATIC_STATUS, m_sErrorStatus); 52 | } 53 | 54 | BEGIN_MESSAGE_MAP(CRedirectDlg, CDialog) 55 | ON_WM_PAINT() 56 | ON_WM_QUERYDRAGICON() 57 | //}}AFX_MSG_MAP 58 | ON_BN_CLICKED(IDC_BT_VIEW, OnBnClickedBtView) 59 | ON_BN_CLICKED(IDC_BT_STARTLOG, OnBnClickedBtStartlog) 60 | ON_BN_CLICKED(IDC_BT_HELP, OnBnClickedBtHelp) 61 | ON_BN_CLICKED(IDC_CHECK_APPEND, OnBnClickedCheckAppend) 62 | ON_CBN_SELCHANGE(IDC_CB_BAUDRATE, OnCbnSelchangeCbBaudrate) 63 | ON_CBN_SELCHANGE(IDC_CB_DATABITS, OnCbnSelchangeCbDatabits) 64 | ON_CBN_SELCHANGE(IDC_CB_PARITY, OnCbnSelchangeCbParity) 65 | ON_CBN_SELCHANGE(IDC_CB_STOPBITS, OnCbnSelchangeCbStopbits) 66 | ON_CBN_SELCHANGE(IDC_CB_FC, OnCbnSelchangeCbFc) 67 | ON_EN_CHANGE(IDC_ED_LOGFILE, OnEnChangeEdLogfile) 68 | ON_MESSAGE (WM_USER_UPDATE_WND, OnWriteUpdate ) 69 | ON_MESSAGE (WM_USER_CHANGE_STATUS, OnWriteStatus ) 70 | ON_NOTIFY (NM_CUSTOMDRAW, IDC_LIST_PORTS, OnCustomdrawList) 71 | ON_COMMAND(ID_HELP, OnBnClickedBtHelp) 72 | END_MESSAGE_MAP() 73 | 74 | 75 | // CRedirectDlg message handlers 76 | 77 | BOOL CRedirectDlg::OnInitDialog() 78 | { 79 | CDialog::OnInitDialog(); 80 | 81 | SetIcon(m_hIcon, TRUE); // Set big icon 82 | SetIcon(m_hIcon, FALSE); // Set small icon 83 | 84 | // comm initialization 85 | m_IconList.Create( 16, 16, ILC_MASK | ILC_COLOR24, 1, 1 ); 86 | m_IconList.Add( AfxGetApp() ->LoadIcon( MAKEINTRESOURCE( IDR_MAINFRAME ) ) ); 87 | m_ListPorts.SetExtendedStyle( LVS_EX_FULLROWSELECT ); 88 | m_ListPorts.SetImageList( &m_IconList, LVSIL_SMALL ); 89 | 90 | m_HomeHlink.SetLink( true, false ); 91 | m_HomeHlink.SetLinkCursor( LoadCursor(NULL, MAKEINTRESOURCE(32649) ) ); 92 | m_HomeHlink.SetHyperLink( CString( _T("http:\\\\www.eltima.com\\products") ) ); 93 | m_HomeHlink.SetFontBold( true ); 94 | m_HomeHlink.SetTextColor( RGB( 0, 0, 255 ) ); 95 | 96 | 97 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_LIST_PORTS ); 98 | CRect rect; 99 | pWnd ->GetClientRect( &rect ); 100 | m_ListPorts.InsertColumn( 0, _T(""), LVCFMT_LEFT, int(rect.Width() / 2 - 0.05 * rect.Width()) ); 101 | m_ListPorts.InsertColumn( 1, _T(""), LVCFMT_LEFT, int(rect.Width() / 2 - 0.05 * rect.Width()) ); 102 | 103 | GetAvailablePorts(); 104 | 105 | // fill controls 106 | for ( int i=0; i(dc.GetSafeHdc()), 0); 146 | 147 | // Center icon in client rectangle 148 | int cxIcon = GetSystemMetrics(SM_CXICON); 149 | int cyIcon = GetSystemMetrics(SM_CYICON); 150 | CRect rect; 151 | GetClientRect(&rect); 152 | int x = (rect.Width() - cxIcon + 1) / 2; 153 | int y = (rect.Height() - cyIcon + 1) / 2; 154 | 155 | // Draw the icon 156 | dc.DrawIcon(x, y, m_hIcon); 157 | } 158 | else 159 | { 160 | CDialog::OnPaint(); 161 | } 162 | } 163 | 164 | HCURSOR CRedirectDlg::OnQueryDragIcon() 165 | { 166 | return static_cast(m_hIcon); 167 | } 168 | 169 | 170 | 171 | //////////////////////////////////////////////////////////////////////////////////// 172 | // 173 | // control handling 174 | // 175 | ///////////////////////////////////////////////////////////////////////////////////// 176 | void CRedirectDlg::OnEnChangeEdLogfile() 177 | { 178 | UpdateData(); 179 | if ( m_sLogFile.GetLength() ) 180 | { 181 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_BT_STARTLOG ); 182 | pWnd ->EnableWindow( TRUE ); 183 | } 184 | else 185 | { 186 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_BT_STARTLOG ); 187 | pWnd ->EnableWindow( FALSE ); 188 | } 189 | 190 | m_Ports[ m_iCurItemSel ] ->m_sLogFile = m_sLogFile; 191 | } 192 | 193 | void CRedirectDlg::OnBnClickedBtView() 194 | { 195 | static TCHAR BASED_CODE szFilter[] = _T("Text Files (*.txt)|*.txt|All Files (*.*)|*.*||"); 196 | 197 | CFileDialog dlg( FALSE, _T("*.txt"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter ); 198 | if ( dlg.DoModal() == IDOK ) 199 | { 200 | m_sLogFile = dlg.GetPathName(); 201 | 202 | if ( m_sLogFile.GetLength() ) 203 | { 204 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_BT_STARTLOG ); 205 | pWnd ->EnableWindow( TRUE ); 206 | } 207 | 208 | m_Ports[ m_iCurItemSel ] ->m_sLogFile = m_sLogFile; 209 | } 210 | 211 | CEdit* pEdit = (CEdit*)GetDlgItem( IDC_ED_LOGFILE ); 212 | pEdit ->SetWindowText( m_sLogFile ); 213 | pEdit ->SetSel( m_sLogFile.GetLength(), m_sLogFile.GetLength() ); 214 | 215 | UpdateData( FALSE ); 216 | } 217 | 218 | void CRedirectDlg::OnBnClickedBtStartlog() 219 | { 220 | if ( m_Ports[ m_iCurItemSel ] ->m_bLogStarted ) 221 | { 222 | // stop logging 223 | m_Ports[ m_iCurItemSel ] ->Close(); 224 | 225 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_BT_STARTLOG ); 226 | pWnd ->SetWindowText( _T("Start logging") ); 227 | 228 | pWnd = (CWnd*)GetDlgItem( IDC_ED_LOGFILE ); 229 | pWnd ->EnableWindow( TRUE ); 230 | 231 | pWnd = (CWnd*)GetDlgItem( IDC_BT_VIEW ); 232 | pWnd ->EnableWindow( TRUE ); 233 | 234 | pWnd = (CWnd*)GetDlgItem( IDC_CHECK_APPEND ); 235 | pWnd ->EnableWindow( TRUE ); 236 | 237 | m_ListPorts.SetItemText( m_iCurItemSel, 1, STRING_DISABLE ); 238 | 239 | m_Ports[ m_iCurItemSel ] ->m_bLogStarted = FALSE; 240 | 241 | m_sErrorStatus = m_Ports[m_iCurItemSel] ->m_sStatusMessage; 242 | UpdateData( FALSE ); 243 | } 244 | else 245 | { 246 | ////////////////////////////////////////////// 247 | CString sBaudrate; 248 | m_cbBaudrate.GetLBText( m_cbBaudrate.GetCurSel(), sBaudrate ); 249 | DWORD dwBaudrate = _ttoi( sBaudrate ); 250 | int iBits = m_cbDataBits.GetCurSel() + 5; 251 | int iParity = m_cbParity.GetCurSel(); 252 | int iStopbits = m_cbStopBits.GetCurSel(); 253 | int iFC = m_cbFC.GetCurSel(); 254 | 255 | UpdateData(); 256 | m_Ports[ m_iCurItemSel ] ->m_sLogFile = m_sLogFile; 257 | 258 | // run logging 259 | if ( (iBits != -1 && iParity != -1 && iStopbits != -1) && 260 | m_Ports[ m_iCurItemSel ] ->Open( dwBaudrate, iBits, iParity, iStopbits, iFC ) ) 261 | { 262 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_BT_STARTLOG ); 263 | pWnd ->SetWindowText( _T("Stop logging") ); 264 | 265 | pWnd = (CWnd*)GetDlgItem( IDC_ED_LOGFILE ); 266 | pWnd ->EnableWindow( FALSE ); 267 | 268 | pWnd = (CWnd*)GetDlgItem( IDC_BT_VIEW ); 269 | pWnd ->EnableWindow( FALSE ); 270 | 271 | pWnd = (CWnd*)GetDlgItem( IDC_CHECK_APPEND ); 272 | pWnd ->EnableWindow( FALSE ); 273 | 274 | m_ListPorts.SetItemText( m_iCurItemSel, 1, STRING_ENABLE ); 275 | 276 | m_Ports[ m_iCurItemSel ] ->m_bLogStarted = TRUE; 277 | } 278 | else 279 | { 280 | m_ListPorts.SetItemText( m_iCurItemSel, 1, STRING_ERROR ); 281 | } 282 | } 283 | 284 | m_ListPorts.RedrawItems( m_iCurItemSel, m_iCurItemSel ); 285 | m_ListPorts.Invalidate( TRUE ); 286 | m_ListPorts.UpdateWindow(); 287 | } 288 | 289 | void CRedirectDlg::OnBnClickedBtHelp() 290 | { 291 | CString str; 292 | TCHAR *Buf = str.GetBufferSetLength (1024); 293 | GetModuleFileName (NULL, Buf, 1024); 294 | *(_tcsrchr (Buf, _T('\\'))) = 0; 295 | str.ReleaseBuffer (); 296 | str += _T("\\"); 297 | str += _T("data_logger.chm"); 298 | ShellExecute(NULL, _T("open"), str, NULL, NULL, SW_SHOWNORMAL ); 299 | } 300 | 301 | // enable logging 302 | void CRedirectDlg::OnCbnSelchangeCbBaudrate() 303 | { 304 | CString sBaudrate; 305 | m_cbBaudrate.GetLBText( m_cbBaudrate.GetCurSel(), sBaudrate ); 306 | m_Ports[ m_iCurItemSel ] ->m_dwBaudRate = _ttoi( sBaudrate ); 307 | 308 | m_Ports[ m_iCurItemSel ] ->SetBaudrate( m_Ports[ m_iCurItemSel ] ->m_dwBaudRate ); 309 | } 310 | 311 | void CRedirectDlg::OnCbnSelchangeCbDatabits() 312 | { 313 | m_Ports[ m_iCurItemSel ] ->m_iIndexDataBits = m_cbDataBits.GetCurSel(); 314 | m_Ports[ m_iCurItemSel ] ->SetDataBits( m_cbDataBits.GetCurSel() + 4 ); 315 | } 316 | 317 | void CRedirectDlg::OnCbnSelchangeCbParity() 318 | { 319 | m_Ports[ m_iCurItemSel ] ->m_iIndexParity = m_cbParity.GetCurSel(); 320 | m_Ports[ m_iCurItemSel ] ->SetParity( m_cbParity.GetCurSel() ); 321 | } 322 | 323 | void CRedirectDlg::OnCbnSelchangeCbStopbits() 324 | { 325 | m_Ports[ m_iCurItemSel ] ->m_iIndexStopBits = m_cbStopBits.GetCurSel(); 326 | m_Ports[ m_iCurItemSel ] ->SetStopBits( m_cbStopBits.GetCurSel() ); 327 | } 328 | 329 | void CRedirectDlg::OnCbnSelchangeCbFc() 330 | { 331 | m_Ports[ m_iCurItemSel ] ->m_iIndexFlowCtrl = m_cbFC.GetCurSel(); 332 | m_Ports[ m_iCurItemSel ] ->SetFlowControl( m_cbFC.GetCurSel() ); 333 | } 334 | 335 | void CRedirectDlg::OnBnClickedCheckAppend() 336 | { 337 | UpdateData(); 338 | m_Ports[m_iCurItemSel] ->m_bAppend = m_bFileAppend; 339 | } 340 | 341 | //////////////////////////////////////////////////////////////////////////////////// 342 | // 343 | // control handling 344 | // 345 | ///////////////////////////////////////////////////////////////////////////////////// 346 | void CRedirectDlg::OnOK() 347 | { 348 | OnBnClickedBtStartlog(); 349 | } 350 | 351 | void CRedirectDlg::OnCancel() 352 | { 353 | if( MessageBox( _T("Do you really want to quit? All logging tasks will be halted."), _T("Data Logger"), 354 | MB_ICONQUESTION | MB_YESNO ) == IDYES ) 355 | { 356 | for ( UINT i=0; iSaveSettings(); 360 | delete pPort; 361 | } 362 | 363 | CDialog::OnCancel(); 364 | } 365 | } 366 | 367 | BOOL CRedirectDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 368 | { 369 | NMHDR *nmhdr = (NMHDR*)lParam; 370 | 371 | if ( nmhdr ->hwndFrom == m_ListPorts.m_hWnd ) 372 | { 373 | if ( nmhdr->code == LVN_ITEMCHANGED ) 374 | { 375 | 376 | LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam; 377 | 378 | if ( pnmv ->iItem != m_iCurItemSel ) 379 | { 380 | m_Ports[m_iCurItemSel] ->m_bIsActive = false; 381 | m_iCurItemSel = pnmv ->iItem; 382 | m_Ports[m_iCurItemSel] ->m_bIsActive = true; 383 | UpdateSettings(); 384 | } 385 | } 386 | } 387 | 388 | return CDialog::OnNotify(wParam, lParam, pResult); 389 | } 390 | 391 | LRESULT CRedirectDlg::OnWriteUpdate ( WPARAM, LPARAM ) 392 | { 393 | m_sTotalFileSize.Format( _T("%d bytes"), m_Ports[m_iCurItemSel] ->GetFileTotalBytes () ); 394 | m_sRecvBytes.Format ( _T("%d bytes"), m_Ports[m_iCurItemSel] ->GetFileWrittenBytes() ); 395 | 396 | UpdateData( FALSE ); 397 | 398 | return 0; 399 | } 400 | 401 | LRESULT CRedirectDlg::OnWriteStatus ( WPARAM wp, LPARAM lp ) 402 | { 403 | // lp - status code 404 | if ( wp == m_iCurItemSel ) 405 | { 406 | m_sErrorStatus = m_Ports[m_iCurItemSel] ->m_sStatusMessage; 407 | } 408 | 409 | if ( lp != SC_OPEN_SUCCESS && lp != SC_NO_ERROR ) 410 | { 411 | m_ListPorts.SetItemText( (int)wp, 1, STRING_ERROR ); 412 | } 413 | 414 | UpdateData( FALSE ); 415 | return 0; 416 | } 417 | 418 | //////////////////////////////////////////////////////////////////////////////// 419 | // 420 | // user functions utilites 421 | // 422 | /////////////////////////////////////////////////////////////////////////////// 423 | 424 | void CRedirectDlg::GetAvailablePorts() 425 | { 426 | CStringList portNameList; 427 | 428 | if ( CCommPort::GetAvailablePorts( &portNameList ) ) 429 | { 430 | m_Ports.reserve( portNameList.GetCount() ); 431 | 432 | CString sDefaultPath; 433 | TCHAR *Buf = sDefaultPath.GetBufferSetLength (1024); 434 | GetModuleFileName (NULL, Buf, 1024); 435 | *(_tcsrchr (Buf, _T('\\'))) = 0; 436 | sDefaultPath.ReleaseBuffer (); 437 | sDefaultPath += _T("\\"); 438 | sDefaultPath += _T("Logs"); 439 | CreateDirectory( sDefaultPath, NULL ); 440 | 441 | POSITION pos = portNameList.GetHeadPosition(); 442 | for ( int i=0; i< portNameList.GetCount(); i++ ) 443 | { 444 | LV_ITEM item; 445 | item.mask = LVIF_IMAGE | LVIF_TEXT; 446 | item.iItem = m_ListPorts.GetItemCount(); 447 | 448 | CString sPortName = portNameList.GetNext( pos ); 449 | TCHAR buffer[255]; 450 | _tcsncpy( buffer, sPortName, 255 ); 451 | item.pszText = buffer; 452 | item.iImage = 0; 453 | item.iSubItem = 0; 454 | 455 | m_Ports.push_back( new CRedirectPort( sPortName, (i==0)?true:false, this, i ) ); 456 | 457 | m_Ports[i] ->LoadSettings(); 458 | 459 | if ( m_Ports[i] ->m_sLogFile.IsEmpty() ) 460 | { 461 | CString sCommDefaultPath = sDefaultPath; 462 | sCommDefaultPath += _T("\\"); 463 | sCommDefaultPath += sPortName; 464 | sCommDefaultPath += _T("port"); 465 | sCommDefaultPath += _T(".txt"); 466 | m_Ports[i] ->m_sLogFile = sCommDefaultPath; 467 | } 468 | 469 | m_ListPorts.InsertItem( &item ); 470 | 471 | if ( m_Ports[i] ->m_bLogStarted && m_Ports[ i ] ->Open() ) 472 | { 473 | m_ListPorts.SetItemText( item.iItem, 1, STRING_ENABLE ); 474 | } 475 | else 476 | { 477 | m_ListPorts.SetItemText( item.iItem, 1, STRING_DISABLE ); 478 | } 479 | } 480 | 481 | UpdateSettings(); 482 | } 483 | } 484 | 485 | // set active port settings 486 | void CRedirectDlg::UpdateSettings() 487 | { 488 | m_sLogFile = m_Ports[m_iCurItemSel] ->m_sLogFile; 489 | 490 | if ( m_Ports[ m_iCurItemSel ] ->m_bLogStarted ) 491 | { 492 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_BT_STARTLOG ); 493 | pWnd ->SetWindowText( _T("Stop logging") ); 494 | 495 | pWnd = (CWnd*)GetDlgItem( IDC_ED_LOGFILE ); 496 | pWnd ->EnableWindow( FALSE ); 497 | 498 | pWnd = (CWnd*)GetDlgItem( IDC_BT_VIEW ); 499 | pWnd ->EnableWindow( FALSE ); 500 | 501 | pWnd = (CWnd*)GetDlgItem( IDC_CHECK_APPEND ); 502 | pWnd ->EnableWindow( FALSE ); 503 | } 504 | else 505 | { 506 | CWnd* pWnd = (CWnd*)GetDlgItem( IDC_BT_STARTLOG ); 507 | pWnd ->SetWindowText( _T("Start logging") ); 508 | 509 | if ( m_sLogFile.GetLength() ) 510 | { 511 | pWnd ->EnableWindow( TRUE ); 512 | } 513 | else 514 | { 515 | pWnd ->EnableWindow( FALSE ); 516 | } 517 | 518 | pWnd = (CWnd*)GetDlgItem( IDC_ED_LOGFILE ); 519 | pWnd ->EnableWindow( TRUE ); 520 | 521 | pWnd = (CWnd*)GetDlgItem( IDC_BT_VIEW ); 522 | pWnd ->EnableWindow( TRUE ); 523 | 524 | pWnd = (CWnd*)GetDlgItem( IDC_CHECK_APPEND ); 525 | pWnd ->EnableWindow( TRUE ); 526 | } 527 | 528 | m_bFileAppend = m_Ports[m_iCurItemSel] ->m_bAppend; 529 | 530 | CString sBaudrate; 531 | sBaudrate.Format( _T("%d"), m_Ports[m_iCurItemSel] ->m_dwBaudRate ); 532 | m_cbBaudrate.SetWindowText( sBaudrate ); 533 | 534 | m_cbDataBits.SetCurSel( m_Ports[m_iCurItemSel] ->m_iIndexDataBits ); 535 | m_cbParity.SetCurSel ( m_Ports[m_iCurItemSel] ->m_iIndexParity ); 536 | m_cbStopBits.SetCurSel( m_Ports[m_iCurItemSel] ->m_iIndexStopBits ); 537 | m_cbFC.SetCurSel ( m_Ports[m_iCurItemSel] ->m_iIndexFlowCtrl ); 538 | 539 | m_sErrorStatus = m_Ports[m_iCurItemSel] ->m_sStatusMessage; 540 | 541 | CString sWrittenBytes, sTotalBytes; 542 | sTotalBytes.Format ( _T("%d bytes"), m_Ports[m_iCurItemSel] ->GetFileTotalBytes() ); 543 | sWrittenBytes.Format( _T("%d bytes"), m_Ports[m_iCurItemSel] ->GetFileWrittenBytes() ); 544 | 545 | UpdateData( FALSE ); 546 | 547 | CEdit* pEdit = (CEdit*)GetDlgItem( IDC_ED_LOGFILE ); 548 | pEdit ->SetWindowText( m_sLogFile ); 549 | pEdit ->SetSel( m_sLogFile.GetLength() - 1, m_sLogFile.GetLength() ); 550 | } 551 | 552 | void CRedirectDlg::OnCustomdrawList ( NMHDR* pNMHDR, LRESULT* pResult ) 553 | { 554 | NMLVCUSTOMDRAW* pLVCD = reinterpret_cast( pNMHDR ); 555 | 556 | *pResult = 0; 557 | 558 | if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage ) 559 | { 560 | *pResult = CDRF_NOTIFYITEMDRAW; 561 | } 562 | else 563 | { 564 | if ( CDDS_ITEM == pLVCD->nmcd.dwDrawStage ) 565 | { 566 | TRACE( "dfssdafas" ); 567 | } 568 | 569 | 570 | if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage ) 571 | { 572 | if ( !m_Ports[ pLVCD->nmcd.dwItemSpec ] ->m_bLogStarted ) 573 | { 574 | pLVCD->clrText = RGB( 128, 128, 128 ); 575 | } 576 | 577 | *pResult = CDRF_DODEFAULT; 578 | } 579 | } 580 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | 2. You may modify your copy or copies of the Program or any portion 88 | of it, thus forming a work based on the Program, and copy and 89 | distribute such modifications or work under the terms of Section 1 90 | above, provided that you also meet all of these conditions: 91 | 92 | a) You must cause the modified files to carry prominent notices 93 | stating that you changed the files and the date of any change. 94 | 95 | b) You must cause any work that you distribute or publish, that in 96 | whole or in part contains or is derived from the Program or any 97 | part thereof, to be licensed as a whole at no charge to all third 98 | parties under the terms of this License. 99 | 100 | c) If the modified program normally reads commands interactively 101 | when run, you must cause it, when started running for such 102 | interactive use in the most ordinary way, to print or display an 103 | announcement including an appropriate copyright notice and a 104 | notice that there is no warranty (or else, saying that you provide 105 | a warranty) and that users may redistribute the program under 106 | these conditions, and telling the user how to view a copy of this 107 | License. (Exception: if the Program itself is interactive but 108 | does not normally print such an announcement, your work based on 109 | the Program is not required to print an announcement.) 110 | 111 | These requirements apply to the modified work as a whole. If 112 | identifiable sections of that work are not derived from the Program, 113 | and can be reasonably considered independent and separate works in 114 | themselves, then this License, and its terms, do not apply to those 115 | sections when you distribute them as separate works. But when you 116 | distribute the same sections as part of a whole which is a work based 117 | on the Program, the distribution of the whole must be on the terms of 118 | this License, whose permissions for other licensees extend to the 119 | entire whole, and thus to each and every part regardless of who wrote it. 120 | 121 | Thus, it is not the intent of this section to claim rights or contest 122 | your rights to work written entirely by you; rather, the intent is to 123 | exercise the right to control the distribution of derivative or 124 | collective works based on the Program. 125 | 126 | In addition, mere aggregation of another work not based on the Program 127 | with the Program (or with a work based on the Program) on a volume of 128 | a storage or distribution medium does not bring the other work under 129 | the scope of this License. 130 | 131 | 3. You may copy and distribute the Program (or a work based on it, 132 | under Section 2) in object code or executable form under the terms of 133 | Sections 1 and 2 above provided that you also do one of the following: 134 | 135 | a) Accompany it with the complete corresponding machine-readable 136 | source code, which must be distributed under the terms of Sections 137 | 1 and 2 above on a medium customarily used for software interchange; or, 138 | 139 | b) Accompany it with a written offer, valid for at least three 140 | years, to give any third party, for a charge no more than your 141 | cost of physically performing source distribution, a complete 142 | machine-readable copy of the corresponding source code, to be 143 | distributed under the terms of Sections 1 and 2 above on a medium 144 | customarily used for software interchange; or, 145 | 146 | c) Accompany it with the information you received as to the offer 147 | to distribute corresponding source code. (This alternative is 148 | allowed only for noncommercial distribution and only if you 149 | received the program in object code or executable form with such 150 | an offer, in accord with Subsection b above.) 151 | 152 | The source code for a work means the preferred form of the work for 153 | making modifications to it. For an executable work, complete source 154 | code means all the source code for all modules it contains, plus any 155 | associated interface definition files, plus the scripts used to 156 | control compilation and installation of the executable. However, as a 157 | special exception, the source code distributed need not include 158 | anything that is normally distributed (in either source or binary 159 | form) with the major components (compiler, kernel, and so on) of the 160 | operating system on which the executable runs, unless that component 161 | itself accompanies the executable. 162 | 163 | If distribution of executable or object code is made by offering 164 | access to copy from a designated place, then offering equivalent 165 | access to copy the source code from the same place counts as 166 | distribution of the source code, even though third parties are not 167 | compelled to copy the source along with the object code. 168 | 169 | 4. You may not copy, modify, sublicense, or distribute the Program 170 | except as expressly provided under this License. Any attempt 171 | otherwise to copy, modify, sublicense or distribute the Program is 172 | void, and will automatically terminate your rights under this License. 173 | However, parties who have received copies, or rights, from you under 174 | this License will not have their licenses terminated so long as such 175 | parties remain in full compliance. 176 | 177 | 5. You are not required to accept this License, since you have not 178 | signed it. However, nothing else grants you permission to modify or 179 | distribute the Program or its derivative works. These actions are 180 | prohibited by law if you do not accept this License. Therefore, by 181 | modifying or distributing the Program (or any work based on the 182 | Program), you indicate your acceptance of this License to do so, and 183 | all its terms and conditions for copying, distributing or modifying 184 | the Program or works based on it. 185 | 186 | 6. Each time you redistribute the Program (or any work based on the 187 | Program), the recipient automatically receives a license from the 188 | original licensor to copy, distribute or modify the Program subject to 189 | these terms and conditions. You may not impose any further 190 | restrictions on the recipients' exercise of the rights granted herein. 191 | You are not responsible for enforcing compliance by third parties to 192 | this License. 193 | 194 | 7. If, as a consequence of a court judgment or allegation of patent 195 | infringement or for any other reason (not limited to patent issues), 196 | conditions are imposed on you (whether by court order, agreement or 197 | otherwise) that contradict the conditions of this License, they do not 198 | excuse you from the conditions of this License. If you cannot 199 | distribute so as to satisfy simultaneously your obligations under this 200 | License and any other pertinent obligations, then as a consequence you 201 | may not distribute the Program at all. For example, if a patent 202 | license would not permit royalty-free redistribution of the Program by 203 | all those who receive copies directly or indirectly through you, then 204 | the only way you could satisfy both it and this License would be to 205 | refrain entirely from distribution of the Program. 206 | 207 | If any portion of this section is held invalid or unenforceable under 208 | any particular circumstance, the balance of the section is intended to 209 | apply and the section as a whole is intended to apply in other 210 | circumstances. 211 | 212 | It is not the purpose of this section to induce you to infringe any 213 | patents or other property right claims or to contest validity of any 214 | such claims; this section has the sole purpose of protecting the 215 | integrity of the free software distribution system, which is 216 | implemented by public license practices. Many people have made 217 | generous contributions to the wide range of software distributed 218 | through that system in reliance on consistent application of that 219 | system; it is up to the author/donor to decide if he or she is willing 220 | to distribute software through any other system and a licensee cannot 221 | impose that choice. 222 | 223 | This section is intended to make thoroughly clear what is believed to 224 | be a consequence of the rest of this License. 225 | 226 | 8. If the distribution and/or use of the Program is restricted in 227 | certain countries either by patents or by copyrighted interfaces, the 228 | original copyright holder who places the Program under this License 229 | may add an explicit geographical distribution limitation excluding 230 | those countries, so that distribution is permitted only in or among 231 | countries not thus excluded. In such case, this License incorporates 232 | the limitation as if written in the body of this License. 233 | 234 | 9. The Free Software Foundation may publish revised and/or new versions 235 | of the General Public License from time to time. Such new versions will 236 | be similar in spirit to the present version, but may differ in detail to 237 | address new problems or concerns. 238 | 239 | Each version is given a distinguishing version number. If the Program 240 | specifies a version number of this License which applies to it and "any 241 | later version", you have the option of following the terms and conditions 242 | either of that version or of any later version published by the Free 243 | Software Foundation. If the Program does not specify a version number of 244 | this License, you may choose any version ever published by the Free Software 245 | Foundation. 246 | 247 | 10. If you wish to incorporate parts of the Program into other free 248 | programs whose distribution conditions are different, write to the author 249 | to ask for permission. For software which is copyrighted by the Free 250 | Software Foundation, write to the Free Software Foundation; we sometimes 251 | make exceptions for this. Our decision will be guided by the two goals 252 | of preserving the free status of all derivatives of our free software and 253 | of promoting the sharing and reuse of software generally. 254 | 255 | NO WARRANTY 256 | 257 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 258 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 259 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 260 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 261 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 262 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 263 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 264 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 265 | REPAIR OR CORRECTION. 266 | 267 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 268 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 269 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 270 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 271 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 272 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 273 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 274 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 275 | POSSIBILITY OF SUCH DAMAGES. 276 | 277 | END OF TERMS AND CONDITIONS 278 | 279 | How to Apply These Terms to Your New Programs 280 | 281 | If you develop a new program, and you want it to be of the greatest 282 | possible use to the public, the best way to achieve this is to make it 283 | free software which everyone can redistribute and change under these terms. 284 | 285 | To do so, attach the following notices to the program. It is safest 286 | to attach them to the start of each source file to most effectively 287 | convey the exclusion of warranty; and each file should have at least 288 | the "copyright" line and a pointer to where the full notice is found. 289 | 290 | 291 | Copyright (C) 292 | 293 | This program is free software; you can redistribute it and/or modify 294 | it under the terms of the GNU General Public License as published by 295 | the Free Software Foundation; either version 2 of the License, or 296 | (at your option) any later version. 297 | 298 | This program is distributed in the hope that it will be useful, 299 | but WITHOUT ANY WARRANTY; without even the implied warranty of 300 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 301 | GNU General Public License for more details. 302 | 303 | You should have received a copy of the GNU General Public License along 304 | with this program; if not, write to the Free Software Foundation, Inc., 305 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 306 | 307 | Also add information on how to contact you by electronic and paper mail. 308 | 309 | If the program is interactive, make it output a short notice like this 310 | when it starts in an interactive mode: 311 | 312 | Gnomovision version 69, Copyright (C) year name of author 313 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 314 | This is free software, and you are welcome to redistribute it 315 | under certain conditions; type `show c' for details. 316 | 317 | The hypothetical commands `show w' and `show c' should show the appropriate 318 | parts of the General Public License. Of course, the commands you use may 319 | be called something other than `show w' and `show c'; they could even be 320 | mouse-clicks or menu items--whatever suits your program. 321 | 322 | You should also get your employer (if you work as a programmer) or your 323 | school, if any, to sign a "copyright disclaimer" for the program, if 324 | necessary. Here is a sample; alter the names: 325 | 326 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 327 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 328 | 329 | , 1 April 1989 330 | Ty Coon, President of Vice 331 | 332 | This General Public License does not permit incorporating your program into 333 | proprietary programs. If your program is a subroutine library, you may 334 | consider it more useful to permit linking proprietary applications with the 335 | library. If this is what you want to do, use the GNU Lesser General 336 | Public License instead of this License. 337 | -------------------------------------------------------------------------------- /CommPort.cpp: -------------------------------------------------------------------------------- 1 | // CommPort.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "CommPort.h" 6 | 7 | 8 | // CCommPort 9 | 10 | // =========================================================== 11 | // constructor & destructor 12 | // =========================================================== 13 | CCommPort::CCommPort() 14 | { 15 | m_hComm = INVALID_HANDLE_VALUE; 16 | m_hThread = NULL; 17 | lReqTerminate = 0; 18 | } 19 | 20 | CCommPort::~CCommPort() 21 | { 22 | if ( IsOpen() ) 23 | Close(); 24 | } 25 | 26 | // =========================================================== 27 | // opening and closing ports 28 | // =========================================================== 29 | BOOL CCommPort::Open ( CString sPortName, 30 | DWORD dwBaudRate, 31 | BYTE bDataBits, 32 | BYTE stopbit, 33 | BYTE parity, 34 | BYTE fc ) 35 | { 36 | if ( IsOpen() ) return FALSE; 37 | 38 | CString sPort = _T("\\\\.\\"); 39 | sPort += sPortName; 40 | m_hComm = CreateFile( sPort, 41 | GENERIC_READ | GENERIC_WRITE, 42 | 0, // must be opened with exclusive-access 43 | NULL, // no security attributes 44 | OPEN_EXISTING, // must use OPEN_EXISTING 45 | FILE_FLAG_OVERLAPPED, 46 | NULL // hTemplate must be NULL for comm devices 47 | ); 48 | 49 | TRACE ( _T("Error: %d\n"), GetLastError() ); 50 | 51 | if (m_hComm == INVALID_HANDLE_VALUE) 52 | { 53 | TRACE (_T("CreateFile failed with error %d.\n"), GetLastError()); 54 | 55 | CloseHandle( m_hComm ); 56 | m_hComm = INVALID_HANDLE_VALUE; 57 | return FALSE; 58 | } 59 | 60 | // reconfigure port 61 | DCB dcb; 62 | BOOL fSuccess = GetCommState(m_hComm, &dcb); 63 | 64 | if (!fSuccess) 65 | { 66 | TRACE (_T("GetCommState failed with error %d.\n"), GetLastError()); 67 | 68 | CloseHandle( m_hComm ); 69 | m_hComm = INVALID_HANDLE_VALUE; 70 | return FALSE; 71 | } 72 | 73 | dcb.BaudRate = dwBaudRate; 74 | dcb.ByteSize = bDataBits; 75 | dcb.Parity = parity; 76 | 77 | switch ( stopbit ) 78 | { 79 | case OneStopBit: dcb.StopBits = ONESTOPBIT; break; 80 | case OneFiveStopBits: dcb.StopBits = ONE5STOPBITS; break; 81 | case TwoStopBits: dcb.StopBits = TWOSTOPBITS; break; 82 | } 83 | 84 | switch ( fc ) 85 | { 86 | case NoFlowControl: 87 | { 88 | dcb.fInX = FALSE; 89 | dcb.fOutX = FALSE; 90 | dcb.fOutxDsrFlow = FALSE; 91 | dcb.fOutxCtsFlow = FALSE; 92 | dcb.fDtrControl = DTR_CONTROL_ENABLE; 93 | dcb.fRtsControl = RTS_CONTROL_ENABLE; 94 | } break; 95 | 96 | case XonXoffFlowControl: 97 | { 98 | dcb.fInX = TRUE; 99 | dcb.fOutX = TRUE; 100 | dcb.fOutxDsrFlow = FALSE; 101 | dcb.fOutxCtsFlow = FALSE; 102 | dcb.fDtrControl = DTR_CONTROL_ENABLE; 103 | dcb.fRtsControl = RTS_CONTROL_ENABLE; 104 | } break; 105 | 106 | case Hardware: 107 | { 108 | dcb.fInX = FALSE; 109 | dcb.fOutX = FALSE; 110 | dcb.fOutxDsrFlow = TRUE; 111 | dcb.fOutxCtsFlow = TRUE; 112 | dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; 113 | dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; 114 | } break; 115 | } 116 | 117 | // Install new adjustment 118 | fSuccess = SetCommState(m_hComm, &dcb); 119 | if (!fSuccess) 120 | { 121 | TRACE (_T("SetCommState failed with error %d.\n"), GetLastError()); 122 | 123 | CloseHandle( m_hComm ); 124 | m_hComm = INVALID_HANDLE_VALUE; 125 | return FALSE; 126 | } 127 | 128 | // launch comm event handler 129 | DWORD dwId; 130 | m_hThread = CreateThread( NULL, 0, EventHandler, (LPVOID)this, CREATE_SUSPENDED, &dwId ); 131 | 132 | if ( m_hThread != NULL ) 133 | { 134 | m_hEventTerminate = CreateEvent( NULL, FALSE, FALSE, _T("OnStopThread") ); 135 | lReqTerminate = 1; 136 | ResumeThread( m_hThread ); 137 | } 138 | else 139 | { 140 | CloseHandle( m_hComm ); 141 | m_hComm = INVALID_HANDLE_VALUE; 142 | return FALSE; 143 | } 144 | 145 | return TRUE; 146 | } 147 | 148 | BOOL CCommPort::Open ( CString sPortName, CString sConfig ) 149 | { 150 | if ( IsOpen() ) return FALSE; 151 | 152 | CString sPort = _T("\\\\.\\"); 153 | sPort += sPortName; 154 | 155 | m_hComm = CreateFile( sPort, 156 | GENERIC_READ | GENERIC_WRITE, 157 | 0, // must be opened with exclusive-access 158 | NULL, // no security attributes 159 | OPEN_EXISTING, // must use OPEN_EXISTING 160 | FILE_FLAG_OVERLAPPED, 161 | NULL // hTemplate must be NULL for comm devices 162 | ); 163 | 164 | if (m_hComm == INVALID_HANDLE_VALUE) 165 | { 166 | TRACE (_T("CreateFile failed with error %d.\n"), GetLastError()); 167 | 168 | return FALSE; 169 | } 170 | 171 | // execute rearranging the port 172 | DCB dcb; 173 | 174 | if ( !GetCommState( m_hComm, &dcb) ) 175 | { 176 | TRACE ( _T("GetCommState failed with error %d.\n"), GetLastError()); 177 | 178 | CloseHandle ( m_hComm ); 179 | m_hComm = INVALID_HANDLE_VALUE; 180 | return FALSE; 181 | } 182 | 183 | if ( !BuildCommDCB ( sConfig, &dcb ) ) 184 | { 185 | TRACE( _T("BuildCommDCB failed with error %d.\n"), GetLastError()); 186 | 187 | CloseHandle ( m_hComm ); 188 | m_hComm = INVALID_HANDLE_VALUE; 189 | return FALSE; 190 | } 191 | 192 | // set new settings 193 | if ( !SetCommState(m_hComm, &dcb) ) 194 | { 195 | TRACE ( _T("SetCommState failed with error %d.\n"), GetLastError()); 196 | 197 | CloseHandle ( m_hComm ); 198 | m_hComm = INVALID_HANDLE_VALUE; 199 | return FALSE; 200 | } 201 | 202 | // launch comm event handler 203 | DWORD dwId; 204 | m_hThread = CreateThread( NULL, 0, EventHandler, (LPVOID)this, CREATE_SUSPENDED, &dwId ); 205 | 206 | if ( m_hThread != NULL ) 207 | { 208 | m_hEventTerminate = CreateEvent( NULL, FALSE, FALSE, _T("OnStopThread") ); 209 | lReqTerminate = 1; 210 | ResumeThread( m_hThread ); 211 | } 212 | else 213 | { 214 | TRACE( _T( "Thread is fault! Error is %d"), GetLastError() ); 215 | 216 | CloseHandle ( m_hComm ); 217 | m_hComm = INVALID_HANDLE_VALUE; 218 | return FALSE; 219 | } 220 | 221 | return TRUE; 222 | } 223 | 224 | 225 | // ============================================================== 226 | // can open 227 | // ============================================================== 228 | BOOL CCommPort::TestOpen( CString sTestingPort ) 229 | { 230 | CString sPort = _T("\\\\.\\"); 231 | sPort += sTestingPort; 232 | HANDLE hComm = CreateFile( sPort, GENERIC_READ | GENERIC_WRITE, 233 | 0, NULL, OPEN_EXISTING, 0, NULL ); 234 | 235 | BOOL fResult = FALSE; 236 | if ( hComm != INVALID_HANDLE_VALUE ) 237 | { 238 | CloseHandle( hComm ); 239 | return TRUE; 240 | } 241 | else 242 | return FALSE; 243 | } 244 | 245 | // ============================================================== 246 | // close port 247 | // ============================================================== 248 | void CCommPort::Close() 249 | { 250 | PurgeComm( m_hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); 251 | CancelIo( m_hComm ); 252 | SetCommMask (m_hComm, 0); 253 | 254 | if ( m_hThread != NULL ) 255 | { 256 | InterlockedDecrement( &lReqTerminate ); 257 | Sleep( 0 ); 258 | 259 | OSVERSIONINFO info; 260 | info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); 261 | 262 | GetVersionEx ( &info ); 263 | 264 | if ( info.dwPlatformId == VER_PLATFORM_WIN32_NT ) 265 | { 266 | // windows NT family 267 | while( WaitForSingleObject( m_hEventTerminate, 100 ) != WAIT_OBJECT_0 ) 268 | { 269 | MSG msg; 270 | GetMessage(&msg, NULL, 0, 0); 271 | if ( !TranslateAccelerator(msg.hwnd, NULL, &msg) ) 272 | { 273 | TranslateMessage(&msg); 274 | DispatchMessage(&msg); 275 | } 276 | } 277 | } 278 | else 279 | { 280 | // other windows 281 | TerminateThread( m_hThread, 0 ); 282 | } 283 | 284 | CloseHandle( m_hComm ); 285 | m_hComm = INVALID_HANDLE_VALUE; 286 | 287 | CloseHandle( m_hThread ); 288 | CloseHandle( m_hEventTerminate ); 289 | 290 | m_hThread = NULL; 291 | m_hEventTerminate = NULL; 292 | lReqTerminate = 0; 293 | } 294 | } 295 | 296 | // ============================================================== 297 | // enumerate available ports 298 | // ============================================================== 299 | DWORD CCommPort::GetAvailablePorts ( CStringList* portList ) 300 | { 301 | //HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM 302 | HKEY hKey = NULL; 303 | 304 | if ( RegOpenKey( HKEY_LOCAL_MACHINE, _T("Hardware\\DeviceMap\\SerialComm"), &hKey ) != ERROR_SUCCESS ) 305 | { 306 | return 0; 307 | } 308 | 309 | DWORD cValues; // number of values for key 310 | DWORD cchMaxValue; // longest value name 311 | DWORD cbMaxValueData; // longest value data 312 | 313 | BYTE bData [100]; 314 | DWORD dwDataLen = 100; 315 | 316 | DWORD i, retCode, iFindedPorts=0; 317 | 318 | TCHAR achValue[255]; 319 | DWORD cchValue = 255; //16300; //16383 320 | 321 | // Get the class name and the value count. 322 | retCode = RegQueryInfoKey( hKey, NULL, NULL, NULL, NULL, NULL, NULL, 323 | &cValues, &cchMaxValue, &cbMaxValueData, NULL, NULL); 324 | 325 | // enumerate all keys. 326 | if (cValues) 327 | { 328 | DWORD dwType; 329 | for (i=0, retCode=ERROR_SUCCESS; iAddTail( (LPCTSTR)bData ); 340 | iFindedPorts++; 341 | } 342 | } 343 | } 344 | 345 | return iFindedPorts; 346 | } 347 | 348 | // =========================================================== 349 | // read & write 350 | // =========================================================== 351 | 352 | DWORD CCommPort::Read ( LPVOID lpBuf, DWORD dwCount ) 353 | { 354 | if ( !IsOpen() ) return 0; 355 | 356 | OVERLAPPED o; 357 | memset ( &o, 0, sizeof (OVERLAPPED) ); 358 | o.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL); 359 | 360 | DWORD dwBytesRead=0; 361 | 362 | BOOL bResult = ReadFile(m_hComm, lpBuf, dwCount, &dwBytesRead, &o); 363 | if ( !bResult ) 364 | { 365 | if ( GetLastError() == ERROR_IO_PENDING ) 366 | { 367 | bResult = GetOverlappedResult( m_hComm, &o, &dwBytesRead, TRUE); 368 | return dwBytesRead; 369 | } 370 | else 371 | return 0; 372 | } 373 | 374 | CloseHandle( o.hEvent ); 375 | return dwBytesRead; 376 | } 377 | 378 | DWORD CCommPort::Write( LPCVOID lpBuf, DWORD dwCount ) 379 | { 380 | if ( !IsOpen() ) return 0; 381 | 382 | OVERLAPPED o; 383 | memset ( &o, 0, sizeof (OVERLAPPED) ); 384 | o.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL); 385 | 386 | DWORD dwBytesWritten = 0; 387 | BOOL bResult = WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, &o ) ; 388 | 389 | if ( !bResult ) 390 | { 391 | if ( GetLastError() == ERROR_IO_PENDING ) 392 | { 393 | bResult = GetOverlappedResult( m_hComm, &o, &dwBytesWritten, TRUE ); 394 | if ( !bResult ) 395 | { 396 | //CloseHandle( o.hEvent ); 397 | return 0; 398 | } 399 | } 400 | else 401 | { 402 | CloseHandle( o.hEvent ); 403 | return 0; 404 | } 405 | } 406 | 407 | CloseHandle( o.hEvent ); 408 | return dwBytesWritten; 409 | } 410 | 411 | // =========================================================== 412 | // port configuration 413 | // =========================================================== 414 | BOOL CCommPort::GetConfig(COMMCONFIG& config) 415 | { 416 | ASSERT( IsOpen() ); 417 | 418 | DWORD dwSize = sizeof(COMMCONFIG); 419 | 420 | return GetCommConfig( m_hComm, &config, &dwSize ); 421 | } 422 | 423 | BOOL CCommPort::SetConfig(COMMCONFIG& config) 424 | { 425 | ASSERT( IsOpen() ); 426 | 427 | return SetCommConfig( m_hComm, &config, sizeof(COMMCONFIG)); 428 | } 429 | 430 | BOOL CCommPort::GetState(LPDCB dcb) 431 | { 432 | ASSERT ( IsOpen() ); 433 | 434 | return GetCommState( m_hComm, dcb ); 435 | } 436 | 437 | BOOL CCommPort::SetState(LPDCB dcb) 438 | { 439 | ASSERT( IsOpen() ); 440 | 441 | return SetCommState( m_hComm, dcb ); 442 | } 443 | 444 | // =========================================================== 445 | // timeouts 446 | // =========================================================== 447 | BOOL CCommPort::SetTimeouts( LPCOMMTIMEOUTS lpCommTimeouts ) 448 | { 449 | return SetCommTimeouts( m_hComm, lpCommTimeouts ); 450 | } 451 | 452 | BOOL CCommPort::GetTimeouts( LPCOMMTIMEOUTS lpCommTimeouts ) 453 | { 454 | return GetCommTimeouts( m_hComm, lpCommTimeouts ); 455 | } 456 | 457 | // =========================================================== 458 | // buffer cleaning 459 | // =========================================================== 460 | BOOL CCommPort::Purge ( DWORD dwFlags ) 461 | { 462 | ASSERT( IsOpen() ); 463 | 464 | return PurgeComm ( m_hComm, dwFlags ); 465 | } 466 | 467 | BOOL CCommPort::ClearWriteQueue() 468 | { 469 | return Purge ( PURGE_TXCLEAR ); 470 | } 471 | 472 | BOOL CCommPort::ClearReadQueue () 473 | { 474 | return Purge ( PURGE_RXCLEAR ); 475 | } 476 | 477 | BOOL CCommPort::AbortAllRead () 478 | { 479 | return Purge ( PURGE_RXABORT ); 480 | } 481 | 482 | BOOL CCommPort::AbortAllWrite () 483 | { 484 | return Purge ( PURGE_TXABORT ); 485 | } 486 | 487 | BOOL CCommPort::Flush() 488 | { 489 | ASSERT( IsOpen() ); 490 | 491 | return ::FlushFileBuffers( m_hComm ); 492 | } 493 | 494 | // =========================================================== 495 | // transmition control 496 | // =========================================================== 497 | BOOL CCommPort::TransmitChar( char cChar ) 498 | { 499 | ASSERT( IsOpen() ); 500 | 501 | return TransmitCommChar( m_hComm, cChar ); 502 | } 503 | 504 | BOOL CCommPort::SetBreak() 505 | { 506 | ASSERT( IsOpen() ); 507 | 508 | return SetCommBreak( m_hComm ); 509 | } 510 | 511 | BOOL CCommPort::ClearBreak() 512 | { 513 | ASSERT( IsOpen() ); 514 | 515 | return ClearCommBreak( m_hComm ); 516 | } 517 | 518 | BOOL CCommPort::EscapeFunction( DWORD dwFunc ) 519 | { 520 | ASSERT( IsOpen() ); 521 | 522 | return EscapeCommFunction( m_hComm, dwFunc ); 523 | } 524 | 525 | BOOL CCommPort::ClearError( LPDWORD lpErrors, LPCOMSTAT lpStat) 526 | { 527 | return ClearCommError( m_hComm, lpErrors, lpStat); 528 | } 529 | 530 | BOOL CCommPort::GetModemStatus( LPDWORD lpModemStat ) 531 | { 532 | return GetCommModemStatus( m_hComm, lpModemStat ); 533 | } 534 | 535 | BOOL CCommPort::GetProperties( LPCOMMPROP lpCommProp ) 536 | { 537 | return GetCommProperties( m_hComm, lpCommProp ); 538 | } 539 | 540 | 541 | // =========================================================== 542 | // events 543 | // =========================================================== 544 | BOOL CCommPort::SetMask ( DWORD dwMask ) 545 | { 546 | ASSERT( IsOpen() ); 547 | 548 | return SetCommMask( m_hComm, dwMask); 549 | } 550 | 551 | BOOL CCommPort::GetMask ( DWORD& dwMask ) 552 | { 553 | ASSERT( IsOpen() ); 554 | 555 | return GetCommMask( m_hComm, &dwMask ); 556 | } 557 | 558 | DWORD CCommPort::EventHandler ( LPVOID lpParam ) 559 | { 560 | CCommPort *pPort = (CCommPort*)lpParam; 561 | DWORD dwMask = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | 562 | EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY; 563 | 564 | if ( !pPort->SetMask( dwMask ) ) 565 | { 566 | pPort ->OnEventError( COMM_SET_EVNT_MASK_ERROR ); 567 | TRACE ( _T("Thread event handling exiting with error Can't set Mask!\r\n") ); 568 | return 1; 569 | } 570 | 571 | OVERLAPPED o; 572 | DWORD dwResMask=0; 573 | 574 | o.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); 575 | o.Internal = 0; 576 | o.InternalHigh = 0; 577 | o.Offset = 0; 578 | o.OffsetHigh = 0; 579 | 580 | while (1) 581 | { 582 | // exit from thread 583 | if ( pPort->lReqTerminate == 0) 584 | { 585 | CloseHandle( o.hEvent ); 586 | SetEvent( pPort->m_hEventTerminate ); 587 | TRACE ( _T("Thread event handling exiting with 0!\r\n") ); 588 | return 0; 589 | } 590 | 591 | // handling comm events 592 | if ( !WaitCommEvent( pPort->m_hComm, &dwResMask, &o ) ) 593 | { 594 | DWORD dwError = GetLastError(); 595 | if ( dwError != ERROR_IO_PENDING ) 596 | { 597 | pPort ->OnEventError( COMM_WAIT_FOR_EVENT_ERROR ); 598 | CloseHandle( o.hEvent ); 599 | SetEvent( pPort->m_hEventTerminate ); 600 | TRACE ( _T("Thread event handling exiting with 1!\r\n") ); 601 | return 1; 602 | } 603 | else 604 | { 605 | DWORD dwBytesTransfer; 606 | GetOverlappedResult( pPort->m_hComm, &o, &dwBytesTransfer, TRUE ); 607 | } 608 | } 609 | 610 | if ( dwResMask & EV_BREAK ) 611 | { 612 | pPort ->OnBreak(); 613 | } 614 | 615 | if ( dwResMask & EV_CTS ) 616 | { 617 | DWORD dwStatus; 618 | pPort ->GetModemStatus( &dwStatus ); 619 | if ( dwStatus & MS_CTS_ON ) 620 | pPort ->OnCTS( TRUE ); 621 | else 622 | pPort ->OnCTS( FALSE ); 623 | } 624 | 625 | if ( dwResMask & EV_DSR ) 626 | { 627 | DWORD dwStatus; 628 | pPort ->GetModemStatus( &dwStatus ); 629 | if ( dwStatus & MS_DSR_ON ) 630 | pPort ->OnDSR( TRUE ); 631 | else 632 | pPort ->OnDSR( FALSE ); 633 | } 634 | 635 | if ( dwResMask & EV_ERR ) 636 | { 637 | DWORD dwError; 638 | COMSTAT comStat; 639 | pPort ->ClearError( &dwError, &comStat ); 640 | pPort ->OnERR( dwError ); 641 | } 642 | 643 | if ( dwResMask & EV_RING ) 644 | { 645 | DWORD dwStatus; 646 | pPort ->GetModemStatus( &dwStatus ); 647 | if ( dwStatus & MS_DSR_ON ) 648 | pPort ->OnRing( TRUE ); 649 | else 650 | pPort ->OnRing( FALSE ); 651 | } 652 | 653 | if ( dwResMask & EV_RLSD ) 654 | { 655 | DWORD dwStatus; 656 | pPort ->GetModemStatus( &dwStatus ); 657 | if ( dwStatus & MS_RLSD_ON ) 658 | pPort ->OnRlsd( TRUE ); 659 | else 660 | pPort ->OnRlsd( FALSE ); 661 | } 662 | 663 | if ( dwResMask & EV_RXCHAR ) 664 | { 665 | DWORD dwError; 666 | COMSTAT comStat; 667 | pPort ->ClearError( &dwError, &comStat ); 668 | pPort ->OnRxChar( comStat.cbInQue ); 669 | } 670 | 671 | if ( dwResMask & EV_RXFLAG ) 672 | { 673 | pPort ->OnRxFlag(); 674 | } 675 | 676 | if ( dwResMask & EV_TXEMPTY ) 677 | { 678 | pPort ->OnTxEmpty(); 679 | } 680 | } // while 681 | 682 | CloseHandle( o.hEvent ); 683 | 684 | return 0; 685 | } 686 | 687 | void CCommPort::OnBreak() {} 688 | void CCommPort::OnCTS( BOOL fCTS ) {} 689 | void CCommPort::OnDSR( BOOL fDSR ) {} 690 | void CCommPort::OnERR( DWORD dwError ) {} 691 | void CCommPort::OnRing( BOOL fRing ) {} 692 | void CCommPort::OnRlsd( BOOL fLSD ) {} 693 | void CCommPort::OnRxChar( DWORD dwCount ) {} 694 | void CCommPort::OnRxFlag() {} 695 | void CCommPort::OnTxEmpty(){} 696 | void CCommPort::OnEventError ( DWORD dwErrCode ) {} 697 | 698 | 699 | // baudrate manipulation 700 | BOOL CCommPort::SetBaudrate ( DWORD dwBaudRate ) 701 | { 702 | if ( !IsOpen() ) 703 | { 704 | return FALSE; 705 | } 706 | 707 | DCB dcb; 708 | BOOL result = GetCommState( m_hComm, &dcb ); 709 | 710 | if ( result ) 711 | { 712 | dcb.BaudRate = dwBaudRate; 713 | 714 | result = SetCommState( m_hComm, &dcb ); 715 | } 716 | else 717 | { 718 | return FALSE; 719 | } 720 | 721 | return result; 722 | } 723 | 724 | DWORD CCommPort::GetBaudrate ( ) 725 | { 726 | if ( !IsOpen() ) 727 | { 728 | return 0; 729 | } 730 | 731 | DCB dcb; 732 | if ( GetCommState( m_hComm, &dcb ) ) 733 | return dcb.BaudRate; 734 | else 735 | return 0; 736 | } 737 | 738 | // databits manipulation 739 | BOOL CCommPort::SetDataBits ( BYTE bDataBits ) 740 | { 741 | if ( !IsOpen() ) 742 | { 743 | return FALSE; 744 | } 745 | 746 | DCB dcb; 747 | BOOL result = GetCommState( m_hComm, &dcb ); 748 | 749 | if ( result ) 750 | { 751 | dcb.ByteSize = bDataBits; 752 | 753 | result = SetCommState( m_hComm, &dcb ); 754 | } 755 | else 756 | { 757 | return FALSE; 758 | } 759 | 760 | return result; 761 | } 762 | 763 | BYTE CCommPort::GetDataBits ( ) 764 | { 765 | if ( !IsOpen() ) 766 | { 767 | return 0; 768 | } 769 | 770 | DCB dcb; 771 | if( GetCommState( m_hComm, &dcb ) ) 772 | { 773 | return dcb.ByteSize; 774 | } 775 | else 776 | { 777 | return 0; 778 | } 779 | } 780 | // parity manipulation 781 | BOOL CCommPort::SetParity ( BYTE bParity ) 782 | { 783 | if ( !IsOpen() ) 784 | { 785 | return FALSE; 786 | } 787 | 788 | DCB dcb; 789 | BOOL result = GetCommState( m_hComm, &dcb ); 790 | 791 | if ( result ) 792 | { 793 | dcb.Parity = bParity; 794 | 795 | result = SetCommState( m_hComm, &dcb ); 796 | } 797 | else 798 | { 799 | return FALSE; 800 | } 801 | 802 | return result; 803 | } 804 | 805 | BOOL CCommPort::GetParity ( BYTE& Parity ) 806 | { 807 | if ( !IsOpen() ) 808 | { 809 | return FALSE; 810 | } 811 | 812 | DCB dcb; 813 | if( GetCommState( m_hComm, &dcb ) ) 814 | { 815 | Parity = dcb.Parity; 816 | return TRUE; 817 | } 818 | else 819 | { 820 | return TRUE; 821 | } 822 | } 823 | 824 | BOOL CCommPort::SetStopBits ( BYTE bStopBits ) 825 | { 826 | if ( !IsOpen() ) 827 | { 828 | return FALSE; 829 | } 830 | 831 | DCB dcb; 832 | BOOL result = GetCommState( m_hComm, &dcb ); 833 | 834 | if ( result ) 835 | { 836 | dcb.StopBits = bStopBits; 837 | 838 | result = SetCommState( m_hComm, &dcb ); 839 | } 840 | else 841 | { 842 | return FALSE; 843 | } 844 | 845 | return result; 846 | } 847 | 848 | BOOL CCommPort::GetStopBits ( BYTE &StopBits ) 849 | { 850 | if ( !IsOpen() ) 851 | { 852 | return FALSE; 853 | } 854 | 855 | DCB dcb; 856 | if( GetCommState( m_hComm, &dcb ) ) 857 | { 858 | StopBits = dcb.StopBits; 859 | return TRUE; 860 | } 861 | else 862 | { 863 | return FALSE; 864 | } 865 | } 866 | 867 | BOOL CCommPort::SetFlowControl( BYTE fc ) 868 | { 869 | if ( !IsOpen() ) 870 | { 871 | return FALSE; 872 | } 873 | 874 | DCB dcb; 875 | if( GetCommState( m_hComm, &dcb ) ) 876 | { 877 | switch ( fc ) 878 | { 879 | case NoFlowControl: 880 | { 881 | dcb.fInX = FALSE; 882 | dcb.fOutX = FALSE; 883 | dcb.fOutxDsrFlow = FALSE; 884 | dcb.fOutxCtsFlow = FALSE; 885 | dcb.fDtrControl = DTR_CONTROL_ENABLE; 886 | dcb.fRtsControl = RTS_CONTROL_ENABLE; 887 | } break; 888 | 889 | case XonXoffFlowControl: 890 | { 891 | dcb.fInX = TRUE; 892 | dcb.fOutX = TRUE; 893 | dcb.fOutxDsrFlow = FALSE; 894 | dcb.fOutxCtsFlow = FALSE; 895 | dcb.fDtrControl = DTR_CONTROL_ENABLE; 896 | dcb.fRtsControl = RTS_CONTROL_ENABLE; 897 | } break; 898 | 899 | case Hardware: 900 | { 901 | dcb.fInX = FALSE; 902 | dcb.fOutX = FALSE; 903 | dcb.fOutxDsrFlow = TRUE; 904 | dcb.fOutxCtsFlow = TRUE; 905 | dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; 906 | dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; 907 | } break; 908 | } 909 | return SetCommState( m_hComm, &dcb ); 910 | } 911 | else 912 | { 913 | return FALSE; 914 | } 915 | } -------------------------------------------------------------------------------- /Label.cpp: -------------------------------------------------------------------------------- 1 | // Label.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "Label.h" 6 | 7 | #ifdef _DEBUG 8 | #define new DEBUG_NEW 9 | #undef THIS_FILE 10 | static char THIS_FILE[] = __FILE__; 11 | #endif 12 | 13 | BEGIN_MESSAGE_MAP(CLabel, CStatic) 14 | //{{AFX_MSG_MAP(CLabel) 15 | ON_WM_TIMER() 16 | ON_WM_LBUTTONDOWN() 17 | ON_WM_SETCURSOR() 18 | ON_WM_SYSCOLORCHANGE() 19 | ON_WM_PAINT() 20 | ON_WM_ERASEBKGND() 21 | //}}AFX_MSG_MAP 22 | END_MESSAGE_MAP() 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | // CLabel Version 1.2 26 | // 27 | // From now on I'll try to keep a log of fixes and enhancements... 28 | // 29 | // The new feature were added due to the response of people. 30 | // All I ask is to all you programmers out there, is if you add, fix or 31 | // enhance this code, sent me a copy and I'll send the copy on to www.codeproject.com 32 | // 33 | // Happy Software Engineer :) 34 | // 35 | // New features include: 36 | // 37 | // A. Support for 3D Fonts 38 | // B. Support for background transparency 39 | // C. More comments provided 40 | // D. If alignment is 'centered' and the window text is seperated by '\r\n' 41 | // the will be centered accordingly - requested by someone @ nasa ;) 42 | // E. Support for font rotation. 43 | // F. Respond to System Color Change 44 | // G. OnPaint improved performance - using Double Buffering Technique 45 | // 46 | // Thanks to: 47 | // Mark McDowell - For suggestion on 'Increasing the flexibility of "hypertext" setting...' 48 | // Erich Ruth - For suggestion on 'Font Rotation' 49 | // 50 | 51 | ///////////////////////////////////////////////////////////////////////////// 52 | // CLabel Version 1.3 53 | // 54 | // A. Added SS_LEFTNOWORDWRAP to include wordwrap 55 | // B. Fix repainting problem 56 | // C. Fix SetBkColor 57 | // D. Added SS_CENTER 58 | 59 | // Thanks to: 60 | // Marius - Added styling problem. 61 | // Azing Vondeling & Broker - Spotting painting Problem. 62 | // Mel Stober - Back Color & SS_CENTER 63 | // 64 | ///////////////////////////////////////////////////////////////////////////// 65 | // CLabel Version 1.4 66 | // 67 | // A. Fix to transparency mode 68 | // B. Added new SetText3DHiliteColor to change the 3D Font face color - default is white. 69 | // 70 | // Thanks to: 71 | // michael.groeger - Spotting Transparency with other controls bug. 72 | // 73 | // 74 | ///////////////////////////////////////////////////////////////////////////// 75 | // CLabel Version 1.5 76 | // 77 | // A. Sanity handle check 78 | // B. Support Interface Charset 79 | // C. Check compilition with _UNICODE 80 | // D. Fix hyperlink feature 81 | // E. Support default Dialog Font 82 | // F. Inclusion of SS_OWNERDRAW via control creation and subclassing 83 | // G. Modification to Text aligmnent code 84 | // H. New background gradient fill function 85 | // 86 | // Thanks to: 87 | // Steve Kowald - Using null handles 88 | // Alan Chan - Supporting International Windows 89 | // Dieter Fauth - Request for default Dialog font 90 | // Herb Illfelder - Text Alignment code 91 | // 92 | ///////////////////////////////////////////////////////////////////////////// 93 | // CLabel Version 1.6 94 | // Jeroen Roosendaal - SetFont suggestion 95 | // Laurent - Spotting SelectObject bugs 96 | // Bernie - Fix PreCreateWindow bug 97 | // Jignesh I. Patel - Added expanded tabs feature 98 | // Jim Farmelant - Fix SetText crash 99 | 100 | 101 | ////////////////////////////////////////////////////////////////////////// 102 | // 103 | // Function: CLabel::CLabel 104 | // 105 | // Description: Default contructor 106 | // 107 | // INPUTS: 108 | // 109 | // RETURNS: 110 | // 111 | // NOTES: 112 | // 113 | // MODIFICATIONS: 114 | // 115 | // Name Date Version Comments 116 | // NT ALMOND 26/08/98 1.0 Origin 117 | // 118 | ////////////////////////////////////////////////////////////////////////// 119 | CLabel::CLabel() 120 | { 121 | m_crText = GetSysColor(COLOR_WINDOWTEXT); 122 | 123 | // 1.1 124 | m_hBackBrush = NULL; 125 | 126 | 127 | m_crHiColor = 0; 128 | m_crLoColor = 0; 129 | 130 | m_bTimer = FALSE; 131 | m_bState = FALSE; 132 | m_bTransparent = FALSE; 133 | m_Link = LinkNone; 134 | m_hCursor = NULL; 135 | m_Type = None; 136 | m_bFont3d = FALSE; 137 | m_bNotifyParent = FALSE; 138 | m_bToolTips = FALSE; 139 | m_bRotation = FALSE; 140 | m_fillmode = Normal; 141 | m_cr3DHiliteColor = RGB(255,255,255); 142 | 143 | m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE)); 144 | } 145 | 146 | ////////////////////////////////////////////////////////////////////////// 147 | // 148 | // Function: CLabel::~CLabel 149 | // 150 | // Description: 151 | // 152 | // INPUTS: 153 | // 154 | // RETURNS: 155 | // 156 | // NOTES: 157 | // 158 | // MODIFICATIONS: 159 | // 160 | // Name Date Version Comments 161 | // NT ALMOND 26/08/98 1.0 Origin 162 | // NT ALMOND 15092000 1.5 Handle Check 163 | ////////////////////////////////////////////////////////////////////////// 164 | CLabel::~CLabel() 165 | { 166 | // Clean up 167 | m_font.DeleteObject(); 168 | ::DeleteObject(m_hwndBrush); 169 | 170 | // Stop Checking complaining 171 | if (m_hBackBrush) 172 | ::DeleteObject(m_hBackBrush); 173 | 174 | } 175 | 176 | void CLabel::UpdateSurface() 177 | { 178 | CRect (rc); 179 | GetWindowRect(rc); 180 | RedrawWindow(); 181 | 182 | GetParent()->ScreenToClient(rc); 183 | GetParent()->InvalidateRect(rc,TRUE); 184 | GetParent()->UpdateWindow(); 185 | } 186 | 187 | ////////////////////////////////////////////////////////////////////////// 188 | // 189 | // Function: CLabel::ReconstructFont 190 | // 191 | // Description: Helper function to build font after it was changed 192 | // 193 | // INPUTS: 194 | // 195 | // RETURNS: 196 | // 197 | // NOTES: PROTECTED 198 | // 199 | // MODIFICATIONS: 200 | // 201 | // Name Date Version Comments 202 | // NT ALMOND 26/08/98 1.0 Origin 203 | // 204 | ////////////////////////////////////////////////////////////////////////// 205 | void CLabel::ReconstructFont() 206 | { 207 | m_font.DeleteObject(); 208 | BOOL bCreated = m_font.CreateFontIndirect(&m_lf); 209 | 210 | ASSERT(bCreated); 211 | } 212 | 213 | ////////////////////////////////////////////////////////////////////////// 214 | // 215 | // Function: CLabel::OnPaint 216 | // 217 | // Description: Handles all the drawing code for the label 218 | // 219 | // INPUTS: 220 | // 221 | // RETURNS: 222 | // 223 | // NOTES: Called by Windows... not by USER 224 | // Probably needs tiding up a some point. 225 | // Different states will require this code to be reworked. 226 | // 227 | // 228 | // MODIFICATIONS: 229 | // 230 | // Name Date Version Comments 231 | // NT ALMOND 22/10/98 1.0 Origin 232 | // NT ALMOND 15092000 1.5 Handle Check 233 | // NT ALMOND 15092000 1.5 Alignment mods 234 | // NT ALMOND 15092000 1.5 Gradient Fill Mode 235 | // NT ALMOND 02072002 1.6 Fill SelectObject bugs 236 | // NT ALMOND 02072002 1.6 Added to expand tabs 237 | ////////////////////////////////////////////////////////////////////////// 238 | 239 | void CLabel::OnPaint() 240 | { 241 | CPaintDC dc(this); // device context for painting 242 | 243 | DWORD dwFlags = 0; 244 | 245 | CRect rc; 246 | GetClientRect(rc); 247 | CString strText; 248 | GetWindowText(strText); 249 | CBitmap bmp; 250 | 251 | 252 | /////////////////////////////////////////////////////// 253 | // 254 | // Set up for double buffering... 255 | // 256 | CDC* pDCMem; 257 | CBitmap* pOldBitmap = NULL; 258 | 259 | if (!m_bTransparent) 260 | { 261 | pDCMem = new CDC; 262 | pDCMem->CreateCompatibleDC(&dc); 263 | bmp.CreateCompatibleBitmap(&dc,rc.Width(),rc.Height()); 264 | pOldBitmap = pDCMem->SelectObject(&bmp); 265 | } 266 | else 267 | { 268 | pDCMem = &dc; 269 | } 270 | 271 | UINT nMode = pDCMem->SetBkMode(TRANSPARENT); 272 | 273 | 274 | COLORREF crText = pDCMem->SetTextColor(m_crText); 275 | CFont *pOldFont = pDCMem->SelectObject(&m_font); 276 | 277 | 278 | // Fill in backgound if not transparent 279 | if (!m_bTransparent) 280 | { 281 | if (m_fillmode == Normal) 282 | { 283 | CBrush br; 284 | 285 | if (m_hBackBrush != NULL) 286 | br.Attach(m_hBackBrush); 287 | else 288 | br.Attach(m_hwndBrush); 289 | 290 | pDCMem->FillRect(rc,&br); 291 | 292 | br.Detach(); 293 | } 294 | else // Gradient Fill 295 | { 296 | DrawGradientFill(pDCMem, &rc, m_crLoColor, m_crHiColor, 100); 297 | } 298 | 299 | } 300 | 301 | 302 | // If the text is flashing turn the text color on 303 | // then to the color of the window background. 304 | 305 | LOGBRUSH lb; 306 | ZeroMemory(&lb,sizeof(lb)); 307 | 308 | // Stop Checking complaining 309 | if (m_hBackBrush) 310 | ::GetObject(m_hBackBrush,sizeof(lb),&lb); 311 | 312 | 313 | // Something to do with flashing 314 | if (!m_bState && m_Type == Text) 315 | pDCMem->SetTextColor(lb.lbColor); 316 | 317 | DWORD style = GetStyle(); 318 | 319 | switch (style & SS_TYPEMASK) 320 | { 321 | case SS_RIGHT: 322 | dwFlags = DT_RIGHT | DT_WORDBREAK; 323 | break; 324 | 325 | case SS_CENTER: 326 | dwFlags = SS_CENTER | DT_WORDBREAK; 327 | break; 328 | 329 | case SS_LEFTNOWORDWRAP: 330 | dwFlags = DT_LEFT; 331 | break; 332 | 333 | default: // treat other types as left 334 | case SS_LEFT: 335 | dwFlags = DT_LEFT | DT_WORDBREAK; 336 | break; 337 | } 338 | 339 | 340 | // Added to expand tabs... 341 | if(strText.Find(_T('\t')) != -1) 342 | dwFlags |= DT_EXPANDTABS; 343 | 344 | // If the text centered make an assumtion that 345 | // the will want to center verticly as well 346 | if (style & SS_CENTERIMAGE) 347 | { 348 | dwFlags = DT_CENTER; 349 | 350 | // Apply 351 | if (strText.Find(_T("\r\n")) == -1) 352 | { 353 | dwFlags |= DT_VCENTER; 354 | 355 | // And because DT_VCENTER only works with single lines 356 | dwFlags |= DT_SINGLELINE; 357 | } 358 | 359 | } 360 | 361 | // 362 | // 3333 DDDDD 363 | // 3 D D 364 | // 33 D D E F X 365 | // 3 D D 366 | // 3333 DDDDD 367 | // 368 | // 369 | if (m_bRotation) 370 | { 371 | int nAlign = pDCMem->SetTextAlign (TA_BASELINE); 372 | 373 | CPoint pt; 374 | GetViewportOrgEx (pDCMem->m_hDC,&pt) ; 375 | SetViewportOrgEx (pDCMem->m_hDC,rc.Width() / 2, rc.Height() / 2, NULL) ; 376 | pDCMem->TextOut (0, 0, strText) ; 377 | SetViewportOrgEx (pDCMem->m_hDC,pt.x / 2, pt.y / 2, NULL) ; 378 | pDCMem->SetTextAlign (nAlign); 379 | } 380 | else 381 | { 382 | pDCMem->DrawText(strText,rc,dwFlags); 383 | if (m_bFont3d) 384 | { 385 | pDCMem->SetTextColor(m_cr3DHiliteColor); 386 | 387 | if (m_3dType == Raised) 388 | rc.OffsetRect(-1,-1); 389 | else 390 | rc.OffsetRect(1,1); 391 | 392 | pDCMem->DrawText(strText,rc,dwFlags); 393 | m_3dType; 394 | 395 | } 396 | } 397 | 398 | // Restore DC's State 399 | pDCMem->SetBkMode(nMode); 400 | pDCMem->SelectObject(pOldFont); 401 | pDCMem->SetTextColor(crText); 402 | 403 | if (!m_bTransparent) 404 | { 405 | dc.BitBlt(0,0,rc.Width(),rc.Height(),pDCMem,0,0,SRCCOPY); 406 | // continue DC restore 407 | pDCMem->SelectObject ( pOldBitmap ) ; 408 | delete pDCMem; 409 | } 410 | } 411 | 412 | 413 | ////////////////////////////////////////////////////////////////////////// 414 | // 415 | // Function: CLabel::OnTimer 416 | // 417 | // Description: Used in conjunction with 'FLASH' functions 418 | // 419 | // INPUTS: Windows API 420 | // 421 | // RETURNS: Windows API 422 | // 423 | // NOTES: 424 | // 425 | // MODIFICATIONS: 426 | // 427 | // Name Date Version Comments 428 | // NT ALMOND 26/08/98 1.0 Origin 429 | // 430 | ////////////////////////////////////////////////////////////////////////// 431 | void CLabel::OnTimer(UINT nIDEvent) 432 | { 433 | 434 | m_bState = !m_bState; 435 | 436 | UpdateSurface(); 437 | 438 | CStatic::OnTimer(nIDEvent); 439 | } 440 | 441 | ////////////////////////////////////////////////////////////////////////// 442 | // 443 | // Function: CLabel::OnSetCursor 444 | // 445 | // Description: Used in conjunction with 'LINK' function 446 | // 447 | // INPUTS: Windows API 448 | // 449 | // RETURNS: Windows API 450 | // 451 | // NOTES: 452 | // 453 | // MODIFICATIONS: 454 | // 455 | // Name Date Version Comments 456 | // NT ALMOND 26/08/98 1.0 Origin 457 | // 458 | ////////////////////////////////////////////////////////////////////////// 459 | BOOL CLabel::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 460 | { 461 | 462 | if (m_hCursor) 463 | { 464 | ::SetCursor(m_hCursor); 465 | return TRUE; 466 | } 467 | 468 | return CStatic::OnSetCursor(pWnd, nHitTest, message); 469 | } 470 | 471 | ////////////////////////////////////////////////////////////////////////// 472 | // 473 | // Function: CLabel::OnLButtonDown 474 | // 475 | // Description: Called when a link is click on 476 | // 477 | // INPUTS: Windows API 478 | // 479 | // RETURNS: Windows API 480 | // 481 | // NOTES: 482 | // 483 | // MODIFICATIONS: 484 | // 485 | // Name Date Version Comments 486 | // NT ALMOND 26/08/98 1.0 Origin 487 | // NT ALMOND 02072002 1.6 Added Mail support 488 | ////////////////////////////////////////////////////////////////////////// 489 | void CLabel::OnLButtonDown(UINT nFlags, CPoint point) 490 | { 491 | 492 | if (!m_bNotifyParent) // Fix 493 | { 494 | CString strLink; 495 | 496 | GetWindowText(strLink); 497 | if (m_Link == HyperLink) 498 | { 499 | ShellExecute(NULL,_T("open"),m_sLink.IsEmpty() ? strLink : m_sLink,NULL,NULL,SW_SHOWNORMAL); 500 | } 501 | if (m_Link == MailLink) 502 | { 503 | strLink = _T("mailto:") + strLink; 504 | ShellExecute( NULL, NULL, strLink, NULL, NULL, SW_SHOWNORMAL ); 505 | } 506 | } 507 | else 508 | { 509 | // To use notification in parent window 510 | // Respond to a OnNotify in parent and disassemble the message 511 | // 512 | NMHDR nm; 513 | 514 | nm.hwndFrom = GetSafeHwnd(); 515 | nm.idFrom = GetDlgCtrlID(); 516 | nm.code = NM_LINKCLICK; 517 | GetParent()->SendMessage(WM_NOTIFY,nm.idFrom,(LPARAM) &nm); 518 | } 519 | 520 | CStatic::OnLButtonDown(nFlags, point); 521 | } 522 | 523 | ////////////////////////////////////////////////////////////////////////// 524 | ////////////////////////////////////////////////////////////////////////// 525 | // THE FUNCTIONS START HERE :---- 526 | ////////////////////////////////////////////////////////////////////////// 527 | ////////////////////////////////////////////////////////////////////////// 528 | 529 | ////////////////////////////////////////////////////////////////////////// 530 | // 531 | // Function: CLabel::SetText 532 | // 533 | // Description: Short cut to set window text - caption - label 534 | // 535 | // INPUTS: Text to use 536 | // 537 | // RETURNS: Reference to this 538 | // 539 | // NOTES: 540 | // 541 | // MODIFICATIONS: 542 | // 543 | // Name Date Version Comments 544 | // NT ALMOND 26081998 1.0 Origin 545 | // NT ALMOND 02072002 1.6 Crash Fix 546 | ////////////////////////////////////////////////////////////////////////// 547 | CLabel& CLabel::SetText(const CString& strText) 548 | { 549 | if(IsWindow(this->GetSafeHwnd())) 550 | { 551 | SetWindowText(strText); 552 | UpdateSurface(); 553 | } 554 | 555 | return *this; 556 | } 557 | 558 | ////////////////////////////////////////////////////////////////////////// 559 | // 560 | // Function: CLabel::SetTextColor 561 | // 562 | // Description: Sets the text color 563 | // 564 | // INPUTS: True or false 565 | // 566 | // RETURNS: Reference to 'this' object 567 | // 568 | // NOTES: 569 | // 570 | // MODIFICATIONS: 571 | // 572 | // Name Date Version Comments 573 | // NT ALMOND 22/10/98 1.0 Origin 574 | // 575 | ////////////////////////////////////////////////////////////////////////// 576 | CLabel& CLabel::SetTextColor(COLORREF crText) 577 | { 578 | 579 | m_crText = crText; 580 | 581 | UpdateSurface(); 582 | return *this; 583 | } 584 | 585 | ////////////////////////////////////////////////////////////////////////// 586 | // 587 | // Function: CLabel::SetFontBold 588 | // 589 | // Description: Sets the font ot bold 590 | // 591 | // INPUTS: True or false 592 | // 593 | // RETURNS: Reference to 'this' object 594 | // 595 | // NOTES: 596 | // 597 | // MODIFICATIONS: 598 | // 599 | // Name Date Version Comments 600 | // NT ALMOND 22/10/98 1.0 Origin 601 | // 602 | ////////////////////////////////////////////////////////////////////////// 603 | CLabel& CLabel::SetFontBold(BOOL bBold) 604 | { 605 | 606 | m_lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL; 607 | ReconstructFont(); 608 | UpdateSurface(); 609 | return *this; 610 | } 611 | 612 | 613 | 614 | ////////////////////////////////////////////////////////////////////////// 615 | // 616 | // Function: CLabel::SetFontUnderline 617 | // 618 | // Description: Sets font underline attribue 619 | // 620 | // INPUTS: True of false 621 | // 622 | // RETURNS: Reference to 'this' object 623 | // 624 | // NOTES: 625 | // 626 | // MODIFICATIONS: 627 | // 628 | // Name Date Version Comments 629 | // NT ALMOND 26/08/98 1.0 Origin 630 | // 631 | ////////////////////////////////////////////////////////////////////////// 632 | CLabel& CLabel::SetFontUnderline(BOOL bSet) 633 | { 634 | m_lf.lfUnderline = bSet; 635 | ReconstructFont(); 636 | UpdateSurface(); 637 | 638 | return *this; 639 | } 640 | 641 | ////////////////////////////////////////////////////////////////////////// 642 | // 643 | // Function: CLabel::SetFontItalic 644 | // 645 | // Description: Sets font italic attribute 646 | // 647 | // INPUTS: True of false 648 | // 649 | // RETURNS: Reference to 'this' object 650 | // 651 | // NOTES: 652 | // 653 | // MODIFICATIONS: 654 | // 655 | // Name Date Version Comments 656 | // NT ALMOND 26/08/98 1.0 Origin 657 | // 658 | ////////////////////////////////////////////////////////////////////////// 659 | CLabel& CLabel::SetFontItalic(BOOL bSet) 660 | { 661 | 662 | m_lf.lfItalic = bSet; 663 | ReconstructFont(); 664 | UpdateSurface(); 665 | 666 | return *this; 667 | } 668 | 669 | ////////////////////////////////////////////////////////////////////////// 670 | // 671 | // Function: CLabel::SetSunken 672 | // 673 | // Description: Sets sunken effect on border 674 | // 675 | // INPUTS: True of false 676 | // 677 | // RETURNS: Reference to 'this' object 678 | // 679 | // NOTES: 680 | // 681 | // MODIFICATIONS: 682 | // 683 | // Name Date Version Comments 684 | // NT ALMOND 26/08/98 1.0 Origin 685 | // 686 | ////////////////////////////////////////////////////////////////////////// 687 | CLabel& CLabel::SetSunken(BOOL bSet) 688 | { 689 | 690 | if (!bSet) 691 | ModifyStyleEx(WS_EX_STATICEDGE,0,SWP_DRAWFRAME); 692 | else 693 | ModifyStyleEx(0,WS_EX_STATICEDGE,SWP_DRAWFRAME); 694 | 695 | return *this; 696 | } 697 | 698 | ////////////////////////////////////////////////////////////////////////// 699 | // 700 | // Function: CLabel::SetBorder 701 | // 702 | // Description: Toggles the border on/off 703 | // 704 | // INPUTS: True of false 705 | // 706 | // RETURNS: Reference to 'this' object 707 | // 708 | // NOTES: 709 | // 710 | // MODIFICATIONS: 711 | // 712 | // Name Date Version Comments 713 | // NT ALMOND 26/08/98 1.0 Origin 714 | // 715 | ////////////////////////////////////////////////////////////////////////// 716 | CLabel& CLabel::SetBorder(BOOL bSet) 717 | { 718 | 719 | if (!bSet) 720 | ModifyStyle(WS_BORDER,0,SWP_DRAWFRAME); 721 | else 722 | ModifyStyle(0,WS_BORDER,SWP_DRAWFRAME); 723 | 724 | return *this; 725 | } 726 | 727 | ////////////////////////////////////////////////////////////////////////// 728 | // 729 | // Function: CLabel::SetFontSize 730 | // 731 | // Description: Sets the font size 732 | // 733 | // INPUTS: True of false 734 | // 735 | // RETURNS: Reference to 'this' object 736 | // 737 | // NOTES: 738 | // 739 | // MODIFICATIONS: 740 | // 741 | // Name Date Version Comments 742 | // NT ALMOND 26/08/98 1.0 Origin 743 | // 744 | ////////////////////////////////////////////////////////////////////////// 745 | CLabel& CLabel::SetFontSize(int nSize) 746 | { 747 | 748 | CFont cf; 749 | LOGFONT lf; 750 | 751 | cf.CreatePointFont(nSize * 10, m_lf.lfFaceName); 752 | cf.GetLogFont(&lf); 753 | 754 | m_lf.lfHeight = lf.lfHeight; 755 | m_lf.lfWidth = lf.lfWidth; 756 | 757 | // nSize*=-1; 758 | // m_lf.lfHeight = nSize; 759 | ReconstructFont(); 760 | UpdateSurface(); 761 | 762 | return *this; 763 | } 764 | 765 | 766 | ////////////////////////////////////////////////////////////////////////// 767 | // 768 | // Function: CLabel::SetBkColor 769 | // 770 | // Description: Sets background color 771 | // 772 | // INPUTS: Colorref of background color 773 | // 774 | // RETURNS: Reference to 'this' object 775 | // 776 | // NOTES: 777 | // 778 | // MODIFICATIONS: 779 | // 780 | // Name Date Version Comments 781 | // NT ALMOND 26/08/98 1.0 Origin 782 | // 783 | ////////////////////////////////////////////////////////////////////////// 784 | CLabel& CLabel::SetBkColor(COLORREF crBkgnd, COLORREF crBkgndHigh , BackFillMode mode) 785 | { 786 | 787 | m_crLoColor = crBkgnd; 788 | m_crHiColor = crBkgndHigh; 789 | 790 | m_fillmode = mode; 791 | 792 | if (m_hBackBrush) 793 | ::DeleteObject(m_hBackBrush); 794 | 795 | 796 | if (m_fillmode == Normal) 797 | m_hBackBrush = ::CreateSolidBrush(crBkgnd); 798 | 799 | UpdateSurface(); 800 | 801 | return *this; 802 | } 803 | 804 | ////////////////////////////////////////////////////////////////////////// 805 | // 806 | // Function: CLabel::SetFontName 807 | // 808 | // Description: Sets the fonts face name 809 | // 810 | // INPUTS: String containing font name 811 | // 812 | // RETURNS: Reference to 'this' object 813 | // 814 | // NOTES: 815 | // 816 | // MODIFICATIONS: 817 | // 818 | // Name Date Version Comments 819 | // NT ALMOND 26/08/98 1.0 Origin 820 | // NT ALMOND 15092000 1.5 Support internation windows 821 | ////////////////////////////////////////////////////////////////////////// 822 | CLabel& CLabel::SetFontName(const CString& strFont, BYTE byCharSet /* Default = ANSI_CHARSET */) 823 | { 824 | 825 | m_lf.lfCharSet = byCharSet; 826 | 827 | _tcscpy(m_lf.lfFaceName,strFont); 828 | ReconstructFont(); 829 | UpdateSurface(); 830 | 831 | return *this; 832 | } 833 | 834 | ////////////////////////////////////////////////////////////////////////// 835 | // 836 | // Function: CLabel::FlashText 837 | // 838 | // Description: As the function states 839 | // 840 | // INPUTS: True or false 841 | // 842 | // RETURNS: Reference to 'this' object 843 | // 844 | // NOTES: 845 | // 846 | // MODIFICATIONS: 847 | // 848 | // Name Date Version Comments 849 | // NT ALMOND 26/08/98 1.0 Origin 850 | // 851 | ////////////////////////////////////////////////////////////////////////// 852 | CLabel& CLabel::FlashText(BOOL bActivate) 853 | { 854 | 855 | if (m_bTimer) 856 | KillTimer(1); 857 | 858 | if (bActivate) 859 | { 860 | m_bState = FALSE; 861 | 862 | m_bTimer = TRUE; 863 | 864 | SetTimer(1,500,NULL); 865 | 866 | m_Type = Text; 867 | } 868 | else 869 | m_Type = None; // Fix 870 | 871 | return *this; 872 | } 873 | 874 | ////////////////////////////////////////////////////////////////////////// 875 | // 876 | // Function: CLabel::FlashBackground 877 | // 878 | // Description: As the function states 879 | // 880 | // INPUTS: True or false 881 | // 882 | // RETURNS: Reference to 'this' object 883 | // 884 | // NOTES: 885 | // 886 | // MODIFICATIONS: 887 | // 888 | // Name Date Version Comments 889 | // NT ALMOND 26/08/98 1.0 Origin 890 | // 891 | ////////////////////////////////////////////////////////////////////////// 892 | CLabel& CLabel::FlashBackground(BOOL bActivate) 893 | { 894 | 895 | if (m_bTimer) 896 | KillTimer(1); 897 | 898 | if (bActivate) 899 | { 900 | m_bState = FALSE; 901 | 902 | m_bTimer = TRUE; 903 | SetTimer(1,500,NULL); 904 | 905 | m_Type = Background; 906 | } 907 | 908 | return *this; 909 | } 910 | 911 | 912 | ////////////////////////////////////////////////////////////////////////// 913 | // 914 | // Function: CLabel::SetLink 915 | // 916 | // Description: Indicates the string is a link 917 | // 918 | // INPUTS: True or false 919 | // 920 | // RETURNS: Reference to 'this' object 921 | // 922 | // NOTES: 923 | // 924 | // MODIFICATIONS: 925 | // 926 | // Name Date Version Comments 927 | // NT ALMOND 26/08/98 1.0 Origin 928 | // NT ALMOND 26/08/99 1.2 Added flexbility of 929 | // Sending Click meessage to parent 930 | // 931 | ////////////////////////////////////////////////////////////////////////// 932 | CLabel& CLabel::SetLink(BOOL bLink,BOOL bNotifyParent) 933 | { 934 | 935 | if (bLink) 936 | m_Link = HyperLink; 937 | else 938 | m_Link = LinkNone; 939 | 940 | m_bNotifyParent = bNotifyParent; 941 | 942 | if (m_Link != LinkNone) 943 | ModifyStyle(0,SS_NOTIFY); 944 | else 945 | ModifyStyle(SS_NOTIFY,0); 946 | 947 | 948 | 949 | return *this; 950 | } 951 | 952 | ////////////////////////////////////////////////////////////////////////// 953 | // 954 | // Function: CLabel::SetLinkCursor 955 | // 956 | // Description: Sets the internet browers link 957 | // 958 | // INPUTS: Handle of cursor 959 | // 960 | // RETURNS: Reference to 'this' object 961 | // 962 | // NOTES: 963 | // 964 | // MODIFICATIONS: 965 | // 966 | // Name Date Version Comments 967 | // NT ALMOND 26/08/98 1.0 Origin 968 | // 969 | ////////////////////////////////////////////////////////////////////////// 970 | CLabel& CLabel::SetLinkCursor(HCURSOR hCursor) 971 | { 972 | 973 | m_hCursor = hCursor; 974 | return *this; 975 | } 976 | 977 | ////////////////////////////////////////////////////////////////////////// 978 | // 979 | // Function: CLabel::SetTransparent 980 | // 981 | // Description: Sets the Label window to be transpaent 982 | // 983 | // INPUTS: True or false 984 | // 985 | // RETURNS: Reference to 'this' object 986 | // 987 | // NOTES: 988 | // 989 | // MODIFICATIONS: 990 | // 991 | // Name Date Version Comments 992 | // NT ALMOND 22/10/98 1.0 Origin 993 | // 994 | ////////////////////////////////////////////////////////////////////////// 995 | CLabel& CLabel::SetTransparent(BOOL bSet) 996 | { 997 | 998 | m_bTransparent = bSet; 999 | ModifyStyleEx(0,WS_EX_TRANSPARENT); // Fix for transparency 1000 | UpdateSurface(); 1001 | 1002 | return *this; 1003 | } 1004 | 1005 | ////////////////////////////////////////////////////////////////////////// 1006 | // 1007 | // Function: CLabel::SetFont3D 1008 | // 1009 | // Description: Sets the 3D attribute of the font. 1010 | // 1011 | // INPUTS: True or false, Raised or Sunken 1012 | // 1013 | // RETURNS: Reference to 'this' object 1014 | // 1015 | // NOTES: 1016 | // 1017 | // MODIFICATIONS: 1018 | // 1019 | // Name Date Version Comments 1020 | // NT ALMOND 22/10/98 1.0 Origin 1021 | // 1022 | ////////////////////////////////////////////////////////////////////////// 1023 | CLabel& CLabel::SetFont3D(BOOL bSet,Type3D type) 1024 | { 1025 | 1026 | m_bFont3d = bSet; 1027 | m_3dType = type; 1028 | UpdateSurface(); 1029 | 1030 | 1031 | return *this; 1032 | } 1033 | 1034 | void CLabel::OnSysColorChange() 1035 | { 1036 | 1037 | if (m_hwndBrush) 1038 | ::DeleteObject(m_hwndBrush); 1039 | 1040 | m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE)); 1041 | 1042 | UpdateSurface(); 1043 | 1044 | 1045 | } 1046 | 1047 | 1048 | 1049 | ////////////////////////////////////////////////////////////////////////// 1050 | // 1051 | // Function: CLabel::SetRotationAngle 1052 | // 1053 | // Description: Sets the rotation angle for the current font. 1054 | // 1055 | // INPUTS: Angle in Degress 1056 | // 1057 | // RETURNS: Reference to 'this' object 1058 | // 1059 | // NOTES: 1060 | // 1061 | // MODIFICATIONS: 1062 | // 1063 | // Name Date Version Comments 1064 | // NT ALMOND 22/10/98 1.0 Origin 1065 | // 1066 | ////////////////////////////////////////////////////////////////////////// 1067 | CLabel& CLabel::SetRotationAngle(UINT nAngle,BOOL bRotation) 1068 | { 1069 | // Arrrrh... 1070 | // Your looking in here why the font is rotating, aren't you? 1071 | // Well try setting the font name to 'Arial' or 'Times New Roman' 1072 | // Make the Angle 180 and set bRotation to true. 1073 | // 1074 | // Font rotation _ONLY_ works with TrueType fonts... 1075 | // 1076 | // 1077 | m_lf.lfEscapement = m_lf.lfOrientation = (nAngle * 10); 1078 | m_bRotation = bRotation; 1079 | 1080 | ReconstructFont(); 1081 | 1082 | UpdateSurface(); 1083 | 1084 | 1085 | return *this; 1086 | } 1087 | 1088 | ////////////////////////////////////////////////////////////////////////// 1089 | // 1090 | // Function: CLabel::SetText3DHiliteColor 1091 | // 1092 | // Description: Sets the 3D font hilite color 1093 | // 1094 | // INPUTS: Color 1095 | // 1096 | // RETURNS: Reference to 'this' object 1097 | // 1098 | // NOTES: 1099 | // 1100 | // MODIFICATIONS: 1101 | // 1102 | // Name Date Version Comments 1103 | // NT ALMOND 17/07/00 1.0 Origin 1104 | // 1105 | ////////////////////////////////////////////////////////////////////////// 1106 | CLabel& CLabel::SetText3DHiliteColor(COLORREF cr3DHiliteColor) 1107 | { 1108 | m_cr3DHiliteColor = cr3DHiliteColor; 1109 | UpdateSurface(); 1110 | 1111 | 1112 | return *this; 1113 | } 1114 | 1115 | 1116 | ////////////////////////////////////////////////////////////////////////// 1117 | // 1118 | // Function: CLabel::PreSubclassWindow 1119 | // 1120 | // Description: Assigns default dialog font 1121 | // 1122 | // INPUTS: 1123 | // 1124 | // RETURNS: 1125 | // 1126 | // NOTES: 1127 | // 1128 | // MODIFICATIONS: 1129 | // 1130 | // Name Date Version Comments 1131 | // NT ALMOND 15092000 1.5 Origin 1132 | // NT ALMOND 02072002 1.6 Fix crash when GetFont returns NULL 1133 | ////////////////////////////////////////////////////////////////////////// 1134 | void CLabel::PreSubclassWindow() 1135 | { 1136 | 1137 | CStatic::PreSubclassWindow(); 1138 | 1139 | CFont* cf = GetFont(); 1140 | if(cf !=NULL) 1141 | { 1142 | cf->GetObject(sizeof(m_lf),&m_lf); 1143 | } 1144 | else 1145 | { 1146 | GetObject(GetStockObject(SYSTEM_FONT),sizeof(m_lf),&m_lf); 1147 | } 1148 | 1149 | ReconstructFont(); 1150 | 1151 | } 1152 | 1153 | ////////////////////////////////////////////////////////////////////////// 1154 | // 1155 | // Function: CLabel::PreCreateWindow 1156 | // 1157 | // Description: 1158 | // 1159 | // INPUTS: 1160 | // 1161 | // RETURNS: 1162 | // 1163 | // NOTES: 1164 | // 1165 | // MODIFICATIONS: 1166 | // 1167 | // Name Date Version Comments 1168 | // NT ALMOND 15092000 1.5 Origin 1169 | ////////////////////////////////////////////////////////////////////////// 1170 | BOOL CLabel::PreCreateWindow(CREATESTRUCT& cs) 1171 | { 1172 | return CStatic::PreCreateWindow(cs); 1173 | } 1174 | 1175 | ////////////////////////////////////////////////////////////////////////// 1176 | // 1177 | // Function: CLabel::DrawGradientFill 1178 | // 1179 | // Description: Internal help function to gradient fill background 1180 | // 1181 | // INPUTS: 1182 | // 1183 | // RETURNS: 1184 | // 1185 | // NOTES: 1186 | // 1187 | // MODIFICATIONS: 1188 | // 1189 | // Name Date Version Comments 1190 | // NT ALMOND 15092000 1.5 Origin 1191 | ////////////////////////////////////////////////////////////////////////// 1192 | void CLabel::DrawGradientFill(CDC* pDC, CRect* pRect, COLORREF crStart, COLORREF crEnd, int nSegments) 1193 | { 1194 | // Get the starting RGB values and calculate the incremental 1195 | // changes to be applied. 1196 | 1197 | COLORREF cr; 1198 | int nR = GetRValue(crStart); 1199 | int nG = GetGValue(crStart); 1200 | int nB = GetBValue(crStart); 1201 | 1202 | int neB = GetBValue(crEnd); 1203 | int neG = GetGValue(crEnd); 1204 | int neR = GetRValue(crEnd); 1205 | 1206 | if(nSegments > pRect->Width()) 1207 | nSegments = pRect->Width(); 1208 | 1209 | int nDiffR = (neR - nR); 1210 | int nDiffG = (neG - nG); 1211 | int nDiffB = (neB - nB); 1212 | 1213 | int ndR = 256 * (nDiffR) / (max(nSegments,1)); 1214 | int ndG = 256 * (nDiffG) / (max(nSegments,1)); 1215 | int ndB = 256 * (nDiffB) / (max(nSegments,1)); 1216 | 1217 | nR *= 256; 1218 | nG *= 256; 1219 | nB *= 256; 1220 | 1221 | neR *= 256; 1222 | neG *= 256; 1223 | neB *= 256; 1224 | 1225 | int nCX = pRect->Width() / max(nSegments,1), nLeft = pRect->left, nRight; 1226 | pDC->SelectStockObject(NULL_PEN); 1227 | 1228 | for (int i = 0; i < nSegments; i++, nR += ndR, nG += ndG, nB += ndB) 1229 | { 1230 | // Use special code for the last segment to avoid any problems 1231 | // with integer division. 1232 | 1233 | if (i == (nSegments - 1)) 1234 | nRight = pRect->right; 1235 | else 1236 | nRight = nLeft + nCX; 1237 | 1238 | cr = RGB(nR / 256, nG / 256, nB / 256); 1239 | 1240 | { 1241 | CBrush br(cr); 1242 | CBrush* pbrOld = pDC->SelectObject(&br); 1243 | pDC->Rectangle(nLeft, pRect->top, nRight + 1, pRect->bottom); 1244 | pDC->SelectObject(pbrOld); 1245 | } 1246 | 1247 | // Reset the left side of the drawing rectangle. 1248 | 1249 | nLeft = nRight; 1250 | } 1251 | } 1252 | 1253 | 1254 | ////////////////////////////////////////////////////////////////////////// 1255 | // 1256 | // Function: CLabel::SetFont 1257 | // 1258 | // Description: Sets font with LOGFONT structure 1259 | // 1260 | // INPUTS: 1261 | // 1262 | // RETURNS: 1263 | // 1264 | // NOTES: 1265 | // 1266 | // MODIFICATIONS: 1267 | // 1268 | // Name Date Version Comments 1269 | // NT ALMOND 02072002 1.6 Origin 1270 | ////////////////////////////////////////////////////////////////////////// 1271 | CLabel& CLabel::SetFont(LOGFONT lf) 1272 | { 1273 | CopyMemory(&m_lf, &lf, sizeof(m_lf)); 1274 | ReconstructFont(); 1275 | UpdateSurface(); 1276 | return *this; 1277 | 1278 | } 1279 | 1280 | BOOL CLabel::OnEraseBkgnd(CDC* pDC) 1281 | { 1282 | // TODO: Add your message handler code here and/or call default 1283 | 1284 | return TRUE; 1285 | } 1286 | 1287 | ////////////////////////////////////////////////////////////////////////// 1288 | // 1289 | // Function: CLabel::SetMailLink 1290 | // 1291 | // Description: Sets the label so it becomes Mail enabled 1292 | // 1293 | // INPUTS: 1294 | // 1295 | // RETURNS: 1296 | // 1297 | // NOTES: 1298 | // 1299 | // MODIFICATIONS: 1300 | // 1301 | // Name Date Version Comments 1302 | // NT ALMOND 02072002 1.6 Origin 1303 | ////////////////////////////////////////////////////////////////////////// 1304 | CLabel& CLabel::SetMailLink(BOOL bEnable, BOOL bNotifyParent) 1305 | { 1306 | if (bEnable) 1307 | m_Link = MailLink; 1308 | else 1309 | m_Link = LinkNone; 1310 | 1311 | 1312 | m_bNotifyParent = bNotifyParent; 1313 | 1314 | if (m_Link != LinkNone) 1315 | ModifyStyle(0,SS_NOTIFY); 1316 | else 1317 | ModifyStyle(SS_NOTIFY,0); 1318 | 1319 | return *this; 1320 | } 1321 | 1322 | ////////////////////////////////////////////////////////////////////////// 1323 | // 1324 | // Function: CLabel::SetHyperLink 1325 | // 1326 | // Description: Sets the label so it becomes hyperlink enabled 1327 | // 1328 | // INPUTS: 1329 | // 1330 | // RETURNS: 1331 | // 1332 | // NOTES: 1333 | // 1334 | // MODIFICATIONS: 1335 | // 1336 | // Name Date Version Comments 1337 | // NT ALMOND 02072002 1.6 Origin 1338 | ////////////////////////////////////////////////////////////////////////// 1339 | CLabel& CLabel::SetHyperLink(const CString& sLink) 1340 | { 1341 | m_sLink = sLink; 1342 | 1343 | return *this; 1344 | } 1345 | --------------------------------------------------------------------------------