├── CGridListCtrlEx ├── CGridColumnTrait.h ├── CGridColumnTraitCombo.cpp ├── CGridColumnTraitCombo.h ├── CGridColumnTraitDateTime.cpp ├── CGridColumnTraitDateTime.h ├── CGridColumnTraitEdit.cpp ├── CGridColumnTraitEdit.h ├── CGridColumnTraitHyperLink.cpp ├── CGridColumnTraitHyperLink.h ├── CGridColumnTraitImage.cpp ├── CGridColumnTraitImage.h ├── CGridColumnTraitMultilineEdit.cpp ├── CGridColumnTraitMultilineEdit.h ├── CGridColumnTraitText.cpp ├── CGridColumnTraitText.h ├── CGridColumnTraitVisitor.h ├── CGridListCtrlEx.cpp ├── CGridListCtrlEx.h ├── CGridListCtrlEx.ncb ├── CGridListCtrlEx.sln ├── CGridListCtrlEx.suo ├── CGridListCtrlEx.vcproj ├── CGridListCtrlGroups.cpp ├── CGridListCtrlGroups.h ├── CGridRowTrait.h ├── CGridRowTraitText.cpp ├── CGridRowTraitText.h ├── CGridRowTraitVisitor.h ├── CGridRowTraitXP.cpp ├── CGridRowTraitXP.h ├── Debug │ └── CGridListCtrlEx.lib ├── MAKEFILE ├── Release │ └── CGridListCtrlEx.lib ├── SOURCES ├── ViewConfigSection.cpp ├── ViewConfigSection.h └── stdafx.h ├── DIRS ├── Filter ├── Filter.vcproj ├── Filter.vcproj.vspscc ├── MAKEFILE ├── SOURCES ├── common.h ├── moure.c ├── moure.h └── moure.rc ├── Manager ├── CGridListCtrlEx.rc ├── CGridListCtrlExApp.cpp ├── CGridListCtrlExApp.h ├── CGridListCtrlExDlg.cpp ├── CGridListCtrlExDlg.h ├── CListCtrl_DataModel.h ├── MAKEFILE ├── Manager.vcproj ├── Moure.exe.manifest ├── SOURCES ├── res │ ├── CGridListCtrlEx.exe.manifest │ ├── CGridListCtrlEx.ico │ └── CGridListCtrlEx.rc2 ├── resource.h ├── stdafx.cpp └── stdafx.h ├── Moure.sln ├── README.md ├── Setup └── setup.iss ├── Snapshots ├── Moure-ss1.jpg └── Moure-ss2.jpg └── bin ├── Moure-1.0.exe ├── Moure-1.1.exe ├── Moure-1.2.exe └── Moure-1.3.exe /CGridListCtrlEx/CGridColumnTrait.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 10 | // Using MFC Extension DLL 11 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 12 | #undef AFX_DATA 13 | #define AFX_DATA AFX_EXT_DATA 14 | #else 15 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 16 | #endif 17 | 18 | class CGridColumnTraitVisitor; 19 | class CGridListCtrlEx; 20 | 21 | #pragma warning(push) 22 | #pragma warning(disable:4100) // unreferenced formal parameter 23 | 24 | //------------------------------------------------------------------------ 25 | //! CGridColumnTrait specifies the methods needed for custom cell handling 26 | //------------------------------------------------------------------------ 27 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTrait 28 | { 29 | public: 30 | //! Destructor 31 | virtual ~CGridColumnTrait() {} 32 | 33 | //! Override OnInsertColumn() to provide your own special styling of the column, 34 | //! after column has been added. 35 | //! 36 | //! @param owner The list control adding column 37 | //! @param nCol The index of the column just added 38 | virtual void OnInsertColumn(CGridListCtrlEx& owner, int nCol) {} 39 | 40 | //! Override OnCustomDraw() to provide your own special cell-drawing. 41 | //! - Must handle selection drawing 42 | //! - Must handle focus drawing 43 | //! - Must handle selection drawing when the CListCtrl doesn't have focus 44 | //! - Must query owner if special foreground/background-color or font should be used 45 | //! 46 | //! @param owner The list control drawing 47 | //! @param pLVCD Pointer to NMLVCUSTOMDRAW structure 48 | //! @param pResult Modification to the drawing stage (CDRF_NEWFONT, etc.) 49 | virtual void OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult) {} 50 | 51 | //! Override OnClickEditStart() to control whether cell edit should be started 52 | //! when clicked with the mouse. OnEditBegin() will be called when return value >= 1. 53 | //! Do NOT start the editor within this method, as it will cause havoc in the mouse click handler. 54 | //! 55 | //! @param owner The list control being clicked 56 | //! @param nRow The index of the row 57 | //! @param nCol The index of the column 58 | //! @param pt The position clicked, in client coordinates. 59 | //! @param bDblClick The position was double clicked 60 | //! @return How should the cell editor be started (0 = No editor, 1 = Start Editor, 2 = Start Editor and block click-event) 61 | virtual int OnClickEditStart(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt, bool bDblClick) { return 0; } 62 | 63 | //! Override OnEditBegin() to provide your own special cell-edit control. 64 | //! - The edit control must inherit from CWnd 65 | //! - The edit control must delete itself when it looses focus 66 | //! - The edit control must send a LVN_ENDLABELEDIT message when edit is complete 67 | //! 68 | //! @param owner The list control starting edit 69 | //! @param nRow The index of the row for the cell to edit 70 | //! @param nCol The index of the column for the cell to edit 71 | //! @return Pointer to the cell editor to use (NULL if cell edit is not possible) 72 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol) { return NULL; } 73 | 74 | //! Override OnEditBegin() to provide your own special cell-edit control. 75 | //! - The edit control must inherit from CWnd 76 | //! - The edit control must delete itself when it looses focus 77 | //! - The edit control must send a LVN_ENDLABELEDIT message when edit is complete 78 | //! 79 | //! @param owner The list control starting edit 80 | //! @param nRow The index of the row for the cell to edit 81 | //! @param nCol The index of the column for the cell to edit 82 | //! @param pt The position clicked, in client coordinates. 83 | //! @return Pointer to the cell editor to use (NULL if cell edit is not possible) 84 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) { return OnEditBegin(owner, nRow, nCol); } 85 | 86 | //! Override OnEditEnd() in case one need to change state after a cell-edit. 87 | virtual void OnEditEnd() {} 88 | 89 | //! Override OnSortRows() to provide your own special row sorting 90 | //! 91 | //! @param leftItem Left cell item 92 | //! @param rightItem Right cell item 93 | //! @param bAscending Perform sorting in ascending or descending order 94 | //! @return Is left value less than right value (-1) or equal (0) or larger (1) 95 | virtual int OnSortRows(const LVITEM& leftItem, const LVITEM& rightItem, bool bAscending) { return OnSortRows(leftItem.pszText, rightItem.pszText, bAscending); } 96 | 97 | //! Override OnSortRows() to provide your own special row sorting 98 | //! 99 | //! @param pszLeftValue Left cell value 100 | //! @param pszRightValue Right cell value 101 | //! @param bAscending Perform sorting in ascending or descending order 102 | //! @return Is left value less than right value (-1) or equal (0) or larger (1) 103 | virtual int OnSortRows(LPCTSTR pszLeftValue, LPCTSTR pszRightValue, bool bAscending) { return 0; } 104 | 105 | //! Override Accept() and update CGridColumnTraitVisitor for new column-trait classes. 106 | //! - Will enable the use of the visitor-pattern ex. for serialization of column-traits 107 | virtual void Accept(CGridColumnTraitVisitor& visitor) {} 108 | 109 | //! Override IsCellReadOnly() to provide custom control whether a cell can be edited 110 | //! 111 | //! @param owner The list control starting edit 112 | //! @param nRow The index of the row for the cell 113 | //! @param nCol The index of the column for the cell 114 | //! @param pt The position clicked, in client coordinates. 115 | //! @return Is cell read only ? (true / false) 116 | virtual bool IsCellReadOnly(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) const { return !m_ColumnState.m_Editable; } 117 | 118 | // Maintaining column visible state, etc. 119 | struct CGRIDLISTCTRLEX_AFX_EXT_CLASS ColumnState 120 | { 121 | ColumnState() 122 | : m_Visible(true) 123 | , m_OrgWidth(0) 124 | , m_OrgPosition(-1) 125 | , m_AlwaysHidden(false) 126 | , m_AlwaysVisible(false) 127 | , m_Sortable(true) 128 | , m_Editable(true) 129 | , m_Resizable(true) 130 | , m_MetaFlags(0) 131 | , m_MinWidth(-1) 132 | , m_MaxWidth(-1) 133 | {} 134 | bool m_Visible; //!< Column is visible or not 135 | int m_OrgWidth; //!< Width it had before being hidden 136 | int m_OrgPosition; //!< Position it had before being hidden 137 | bool m_AlwaysHidden;//!< Column can never be visible 138 | bool m_AlwaysVisible;//!< Column can never be hidden 139 | bool m_Sortable; //!< Rows can be sorted according to column 140 | bool m_Editable; //!< Cells in the column can be edited 141 | bool m_Resizable; //!< Column width is resizable 142 | int m_MinWidth; //!< Column width has a min size 143 | int m_MaxWidth; //!< Column width has a max size 144 | 145 | //! Meta-Flags (and data) can be used to store extra properties for a column 146 | //! when deriving from CGridListCtrlEx. 147 | DWORD m_MetaFlags; 148 | }; 149 | inline ColumnState& GetColumnState() { return m_ColumnState; } 150 | 151 | inline BOOL HasMetaFlag(DWORD flag) { return (m_ColumnState.m_MetaFlags & flag) ? TRUE : FALSE; } 152 | void SetMetaFlag(DWORD flag, bool enable) 153 | { 154 | if (enable) 155 | m_ColumnState.m_MetaFlags |= flag; 156 | else 157 | m_ColumnState.m_MetaFlags &= ~flag; 158 | } 159 | 160 | protected: 161 | ColumnState m_ColumnState; 162 | }; 163 | 164 | #pragma warning(pop) 165 | 166 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 167 | #undef AFX_DATA 168 | #define AFX_DATA 169 | #endif 170 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitCombo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridColumnTraitImage.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | template class CGRIDLISTCTRLEX_AFX_EXT_CLASS CSimpleMap; 17 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CEdit; 18 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CComboBox; 19 | #else 20 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 21 | #endif 22 | 23 | //------------------------------------------------------------------------ 24 | //! CGridColumnTraitCombo implements a CComboBox as cell-editor 25 | //------------------------------------------------------------------------ 26 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitCombo : public CGridColumnTraitImage 27 | { 28 | public: 29 | CGridColumnTraitCombo(); 30 | 31 | void SetMaxItems(UINT nMaxItems); 32 | UINT GetMaxItems() const; 33 | 34 | void SetStyle(DWORD dwStyle); 35 | DWORD GetStyle() const; 36 | 37 | void SetMaxWidth(UINT nMaxWidth); 38 | UINT GetMaxWidth() const; 39 | 40 | void SetShowDropDown(BOOL bShowIt); 41 | BOOL GetShowDropDown() const; 42 | 43 | void LoadList(const CSimpleMap& comboList, int nCurSel); 44 | void AddItem(DWORD_PTR nItemData, const CString& strItemText); 45 | void ClearFixedItems(); 46 | 47 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol); 48 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) { return CGridColumnTraitImage::OnEditBegin(owner, nRow, nCol, pt); } 49 | virtual void OnEditEnd(); 50 | 51 | protected: 52 | virtual void Accept(CGridColumnTraitVisitor& visitor); 53 | virtual CComboBox* CreateComboBox(CGridListCtrlEx& owner, int nRow, int nCol, DWORD dwStyle, const CRect& rect); 54 | 55 | CSimpleMap m_ComboList; //!< Fixed list of items in the combo-box 56 | CComboBox* m_pComboBox; //!< CComboBox currently open 57 | DWORD m_ComboBoxStyle; //!< Style to use when creating CComboBox 58 | UINT m_MaxItems; //!< Max height (in items) of the CComboBox when doing dropdown 59 | UINT m_MaxWidth; //!< Max width (in pixels) of the CComboBox when doing dropdown 60 | BOOL m_ShowDropDown; //!< Show drop down of the CComboBox at edit begin 61 | 62 | private: 63 | // Private because they doesn't handle CSimpleMap 64 | CGridColumnTraitCombo(const CGridColumnTraitCombo&); 65 | CGridColumnTraitCombo& operator=(const CGridColumnTraitCombo& other); 66 | }; 67 | 68 | //------------------------------------------------------------------------ 69 | //! CEdit inside CComboBox for inplace edit. For internal use by CGridColumnTraitCombo 70 | // 71 | // Taken from "MFC Grid control" credits Chris Maunder 72 | // http://www.codeproject.com/KB/miscctrl/gridctrl.aspx 73 | //------------------------------------------------------------------------ 74 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridEditorComboBoxEdit : public CEdit 75 | { 76 | DECLARE_DYNAMIC(CGridEditorComboBoxEdit) 77 | 78 | public: 79 | CGridEditorComboBoxEdit(); 80 | 81 | protected: 82 | afx_msg void OnKillFocus(CWnd* pNewWnd); 83 | 84 | DECLARE_MESSAGE_MAP(); 85 | 86 | private: 87 | CGridEditorComboBoxEdit(const CGridEditorComboBoxEdit&); 88 | CGridEditorComboBoxEdit& operator=(const CGridEditorComboBoxEdit&); 89 | }; 90 | 91 | //------------------------------------------------------------------------ 92 | //! CComboBox for inplace edit. For internal use by CGridColumnTraitCombo 93 | // 94 | // Taken from "MFC Grid control" credits Chris Maunder 95 | // http://www.codeproject.com/KB/miscctrl/gridctrl.aspx 96 | //------------------------------------------------------------------------ 97 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridEditorComboBox : public CComboBox 98 | { 99 | DECLARE_DYNAMIC(CGridEditorComboBox) 100 | 101 | public: 102 | CGridEditorComboBox(int nRow, int nCol, UINT nMaxWidthPixels, UINT nMaxHeightItems, BOOL bShowDropDown); 103 | 104 | virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID); 105 | virtual void EndEdit(bool bSuccess); 106 | 107 | protected: 108 | afx_msg void OnKillFocus(CWnd* pNewWnd); 109 | afx_msg void OnSetFocus(CWnd* pOldWnd); 110 | afx_msg void OnDestroy(); 111 | afx_msg void OnDropDown(); 112 | afx_msg void OnCloseUp(); 113 | afx_msg void OnChangeSelection(); 114 | afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); 115 | 116 | virtual void PostNcDestroy(); 117 | virtual BOOL PreTranslateMessage(MSG* pMsg); 118 | 119 | DECLARE_MESSAGE_MAP(); 120 | 121 | CGridEditorComboBoxEdit m_Edit; //!< Subclassed edit control inside the CComboBox 122 | bool m_Completed; //!< Ensure the editor only reacts to a single close event 123 | bool m_Modified; //!< Register if selection was modified while the editor was open 124 | int m_Row; //!< The index of the row being edited 125 | int m_Col; //!< The index of the column being edited 126 | UINT m_MaxWidthPixels; //!< Max width (in pixels) of the CComboBox when doing dropdown 127 | UINT m_MaxHeightItems; //!< Max height (in items) of the CComboBox when doing dropdown 128 | BOOL m_ShowDropDown; //!< Show drop down of the CComboBox at edit begin 129 | 130 | private: 131 | CGridEditorComboBox(); 132 | CGridEditorComboBox(const CGridEditorComboBox&); 133 | CGridEditorComboBox& operator=(const CGridEditorComboBox&); 134 | }; 135 | 136 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 137 | #undef AFX_DATA 138 | #define AFX_DATA 139 | #endif 140 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitDateTime.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // Author: Rolf Kristensen 3 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 4 | // License: Free to use for all (New BSD License) 5 | //------------------------------------------------------------------------ 6 | 7 | #include "stdafx.h" 8 | #pragma warning(disable:4100) // unreferenced formal parameter 9 | 10 | #include "CGridColumnTraitDateTime.h" 11 | 12 | #include "CGridColumnTraitVisitor.h" 13 | #include "CGridListCtrlEx.h" 14 | 15 | //------------------------------------------------------------------------ 16 | //! CGridColumnTraitDateTime - Constructor 17 | //------------------------------------------------------------------------ 18 | CGridColumnTraitDateTime::CGridColumnTraitDateTime() 19 | : m_ParseDateTimeFlags(0) 20 | , m_ParseDateTimeLCID(LOCALE_USER_DEFAULT) 21 | , m_DateTimeCtrlStyle(DTS_APPCANPARSE) 22 | {} 23 | 24 | //------------------------------------------------------------------------ 25 | //! Accept Visitor Pattern 26 | //------------------------------------------------------------------------ 27 | void CGridColumnTraitDateTime::Accept(CGridColumnTraitVisitor& visitor) 28 | { 29 | visitor.Visit(*this); 30 | } 31 | 32 | //------------------------------------------------------------------------ 33 | //! Set the DateTime format used to display the date in the editor 34 | //! 35 | //! @param strFormat Date Format string 36 | //------------------------------------------------------------------------ 37 | void CGridColumnTraitDateTime::SetFormat(const CString& strFormat) 38 | { 39 | m_Format = strFormat; 40 | } 41 | 42 | //------------------------------------------------------------------------ 43 | //! Get the DateTime format used to display the date in the editor 44 | //! 45 | //! @return Date Format string 46 | //------------------------------------------------------------------------ 47 | CString CGridColumnTraitDateTime::GetFormat() const 48 | { 49 | return m_Format; 50 | } 51 | 52 | //------------------------------------------------------------------------ 53 | //! Set the flags for converting the datetime in text format to actual date. 54 | //! 55 | //! @param dwFlags Flags for locale settings and parsing 56 | //! @param lcid Locale ID to use for the conversion 57 | //------------------------------------------------------------------------ 58 | void CGridColumnTraitDateTime::SetParseDateTime(DWORD dwFlags, LCID lcid) 59 | { 60 | m_ParseDateTimeFlags = dwFlags; 61 | m_ParseDateTimeLCID = lcid; 62 | } 63 | 64 | //------------------------------------------------------------------------ 65 | //! Set style used when creating CDataTimeCtrl for cell value editing 66 | //! 67 | //! @param dwStyle Style flags 68 | //------------------------------------------------------------------------ 69 | void CGridColumnTraitDateTime::SetStyle(DWORD dwStyle) 70 | { 71 | m_DateTimeCtrlStyle = dwStyle; 72 | } 73 | 74 | //------------------------------------------------------------------------ 75 | //! Get style used when creating CDataTimeCtrl for cell value editing 76 | //! 77 | //! @return Style Flags 78 | //------------------------------------------------------------------------ 79 | DWORD CGridColumnTraitDateTime::GetStyle() const 80 | { 81 | return m_DateTimeCtrlStyle; 82 | } 83 | 84 | //------------------------------------------------------------------------ 85 | //! Parse the input string into a datetime value 86 | //! 87 | //! @param lpszDate The input string 88 | //! @param dateTime The datetime value 89 | //! @return Could the input string be converted into a valid datetime value ? 90 | //------------------------------------------------------------------------ 91 | BOOL CGridColumnTraitDateTime::ParseDateTime(LPCTSTR lpszDate, COleDateTime& dateTime) 92 | { 93 | if (dateTime.ParseDateTime(lpszDate, m_ParseDateTimeFlags, m_ParseDateTimeLCID) == FALSE) 94 | { 95 | dateTime.SetDateTime(1970, 1, 1, 0, 0, 0); 96 | return FALSE; 97 | } 98 | else 99 | return TRUE; 100 | } 101 | 102 | //------------------------------------------------------------------------ 103 | //! Create a CDateTimeCtrl as cell value editor 104 | //! 105 | //! @param owner The list control starting a cell edit 106 | //! @param nRow The index of the row 107 | //! @param nCol The index of the column 108 | //! @param dwStyle The windows style to use when creating the CEdit 109 | //! @param rect The rectangle where the inplace cell value editor should be placed 110 | //! @return Pointer to the cell editor to use 111 | //------------------------------------------------------------------------ 112 | CDateTimeCtrl* CGridColumnTraitDateTime::CreateDateTimeCtrl(CGridListCtrlEx& owner, int nRow, int nCol, DWORD dwStyle, const CRect& rect) 113 | { 114 | // Create control to edit the cell 115 | CDateTimeCtrl* pDateTimeCtrl = new CGridEditorDateTimeCtrl(nRow, nCol, this); 116 | VERIFY(pDateTimeCtrl->Create(WS_CHILD | dwStyle, rect, &owner, 0)); 117 | if (!owner.UsingVisualStyle()) 118 | pDateTimeCtrl->ModifyStyleEx(WS_EX_CLIENTEDGE, WS_EX_STATICEDGE, SWP_FRAMECHANGED); // Remove sunken edge 119 | return pDateTimeCtrl; 120 | } 121 | 122 | //------------------------------------------------------------------------ 123 | //! Overrides OnEditBegin() to provide a CDateTimeCtrl cell value editor 124 | //! 125 | //! @param owner The list control starting edit 126 | //! @param nRow The index of the row for the cell to edit 127 | //! @param nCol The index of the column for the cell to edit 128 | //! @return Pointer to the cell editor to use (NULL if cell edit is not possible) 129 | //------------------------------------------------------------------------ 130 | CWnd* CGridColumnTraitDateTime::OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol) 131 | { 132 | // Convert cell-text to date/time format 133 | CString cellText = owner.GetItemText(nRow, nCol); 134 | COleDateTime dateTime; 135 | ParseDateTime(cellText, dateTime); 136 | 137 | // Get position of the cell to edit 138 | CRect rectCell = GetCellEditRect(owner, nRow, nCol); 139 | 140 | // Get the text-style of the cell to edit 141 | DWORD dwStyle = m_DateTimeCtrlStyle; 142 | HDITEM hd = { 0 }; 143 | hd.mask = HDI_FORMAT; 144 | VERIFY(owner.GetHeaderCtrl()->GetItem(nCol, &hd)); 145 | if (hd.fmt & HDF_RIGHT) 146 | dwStyle |= DTS_RIGHTALIGN; 147 | 148 | // Create control to edit the cell 149 | CDateTimeCtrl* pDateTimeCtrl = CreateDateTimeCtrl(owner, nRow, nCol, dwStyle, rectCell); 150 | VERIFY(pDateTimeCtrl != NULL); 151 | if (pDateTimeCtrl == NULL) 152 | return NULL; 153 | 154 | // Configure font 155 | pDateTimeCtrl->SetFont(owner.GetCellFont()); 156 | 157 | // Configure datetime format 158 | if (!m_Format.IsEmpty()) 159 | pDateTimeCtrl->SetFormat(m_Format); 160 | 161 | pDateTimeCtrl->SetTime(dateTime); 162 | 163 | // Check with the original string 164 | CString timeText; 165 | pDateTimeCtrl->GetWindowText(timeText); 166 | if (cellText != timeText) 167 | { 168 | dateTime.SetDateTime(1970, 1, 1, 0, 0, 0); 169 | pDateTimeCtrl->SetTime(dateTime); 170 | } 171 | 172 | return pDateTimeCtrl; 173 | } 174 | 175 | //------------------------------------------------------------------------ 176 | //! Compares two cell values according to specified sort order 177 | //! 178 | //! @param pszLeftValue Left cell value 179 | //! @param pszRightValue Right cell value 180 | //! @param bAscending Perform sorting in ascending or descending order 181 | //! @return Is left value less than right value (-1) or equal (0) or larger (1) 182 | //------------------------------------------------------------------------ 183 | int CGridColumnTraitDateTime::OnSortRows(LPCTSTR pszLeftValue, LPCTSTR pszRightValue, bool bAscending) 184 | { 185 | COleDateTime leftDateTime, rightDateTime; 186 | ParseDateTime(pszLeftValue, leftDateTime); 187 | ParseDateTime(pszRightValue, rightDateTime); 188 | 189 | if (leftDateTime > rightDateTime) 190 | return bAscending ? 1 : -1; 191 | else 192 | if (leftDateTime < rightDateTime) 193 | return bAscending ? -1 : 1; 194 | else 195 | return 0; 196 | } 197 | 198 | //------------------------------------------------------------------------ 199 | // CGridEditorDateTimeCtrl (For internal use) 200 | //------------------------------------------------------------------------ 201 | IMPLEMENT_DYNAMIC(CGridEditorDateTimeCtrl, CDateTimeCtrl) 202 | 203 | BEGIN_MESSAGE_MAP(CGridEditorDateTimeCtrl, CDateTimeCtrl) 204 | //{{AFX_MSG_MAP(CGridEditorDateTimeCtrl) 205 | ON_WM_KILLFOCUS() 206 | ON_NOTIFY_REFLECT(DTN_DATETIMECHANGE, OnDateTimeChange) 207 | ON_NOTIFY_REFLECT(DTN_USERSTRINGW, OnUserString) 208 | ON_NOTIFY_REFLECT(DTN_USERSTRINGA, OnUserString) 209 | ON_NOTIFY_REFLECT(DTN_CLOSEUP, OnCloseUp) 210 | ON_WM_CHAR() 211 | //}}AFX_MSG_MAP 212 | END_MESSAGE_MAP() 213 | 214 | //------------------------------------------------------------------------ 215 | //! CGridEditorDateTimeCtrl - Constructor 216 | //! 217 | //! @param nRow The index of the row 218 | //! @param nCol The index of the column 219 | //! @param pColumnTrait The parent column trait, used for datetime validation 220 | //------------------------------------------------------------------------ 221 | CGridEditorDateTimeCtrl::CGridEditorDateTimeCtrl(int nRow, int nCol, CGridColumnTraitDateTime* pColumnTrait) 222 | : m_Row(nRow) 223 | , m_Col(nCol) 224 | , m_Completed(false) 225 | , m_Modified(false) 226 | , m_pColumnTrait(pColumnTrait) 227 | {} 228 | 229 | //------------------------------------------------------------------------ 230 | //! The cell value editor was closed and the entered should be saved. 231 | //! 232 | //! @param bSuccess Should the entered cell value be saved 233 | //------------------------------------------------------------------------ 234 | void CGridEditorDateTimeCtrl::EndEdit(bool bSuccess) 235 | { 236 | // Avoid two messages if key-press is followed by kill-focus 237 | if (m_Completed) 238 | return; 239 | 240 | m_Completed = true; 241 | 242 | // Format time back to string 243 | CString str; 244 | GetWindowText(str); 245 | 246 | // Send Notification to parent of ListView ctrl 247 | LV_DISPINFO dispinfo = { 0 }; 248 | if (bSuccess && m_Modified) 249 | { 250 | dispinfo.item.mask = LVIF_TEXT; 251 | dispinfo.item.pszText = str.GetBuffer(0); 252 | dispinfo.item.cchTextMax = str.GetLength(); 253 | } 254 | ShowWindow(SW_HIDE); 255 | CGridColumnTraitImage::SendEndLabelEdit(*GetParent(), m_Row, m_Col, dispinfo); 256 | PostMessage(WM_CLOSE); 257 | } 258 | 259 | //------------------------------------------------------------------------ 260 | //! WM_KILLFOCUS message handler called when CDateTimeCtrl is loosing focus 261 | //! to other control. Used register that cell value editor should close. 262 | //! 263 | //! @param pNewWnd Pointer to the window that receives the input focus (may be NULL or may be temporary). 264 | //------------------------------------------------------------------------ 265 | void CGridEditorDateTimeCtrl::OnKillFocus(CWnd *pNewWnd) 266 | { 267 | CDateTimeCtrl::OnKillFocus(pNewWnd); 268 | if (GetMonthCalCtrl() == NULL) 269 | { 270 | // Special case when a dynamic CEdit is created (DTS_APPCANPARSE) 271 | if (pNewWnd == NULL || pNewWnd->GetParent() != this) 272 | EndEdit(true); 273 | } 274 | } 275 | 276 | //------------------------------------------------------------------------ 277 | //! DTN_CLOSEUP notification message handler called when CMonthCalCtrl 278 | //! window has closed. Fallback solution for closing inplace CDateTimeCtrl, 279 | //! in case focus is not given back to the CDateTimeCtrl. 280 | //! 281 | //! @param pNMHDR Pointer to NMHDR structure 282 | //! @param pResult Is not used 283 | //------------------------------------------------------------------------ 284 | void CGridEditorDateTimeCtrl::OnCloseUp(NMHDR *pNMHDR, LRESULT *pResult) 285 | { 286 | if (GetFocus() != this) 287 | EndEdit(true); // Force close if focus has been stolen 288 | } 289 | 290 | //------------------------------------------------------------------------ 291 | //! Called by the default OnNcDestroy (WM_NCDESTROY) message handler, 292 | //! when CDateTimeCtrl window has been be destroyed. 293 | //! Used to delete the inplace CDateTimeCtrl editor object as well. 294 | //! This is necessary when the CDateTimeCtrl is created dynamically. 295 | //------------------------------------------------------------------------ 296 | void CGridEditorDateTimeCtrl::PostNcDestroy() 297 | { 298 | CDateTimeCtrl::PostNcDestroy(); 299 | delete this; 300 | } 301 | 302 | //------------------------------------------------------------------------ 303 | //! WM_CHAR message handler to monitor date modifications 304 | //! 305 | //! @param nChar Specifies the virtual key code of the given key. 306 | //! @param nRepCnt Repeat count (the number of times the keystroke is repeated as a result of the user holding down the key). 307 | //! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code 308 | //------------------------------------------------------------------------ 309 | void CGridEditorDateTimeCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 310 | { 311 | m_Modified = true; 312 | CDateTimeCtrl::OnChar(nChar, nRepCnt, nFlags); 313 | } 314 | 315 | //------------------------------------------------------------------------ 316 | //! DTN_DATETIMECHANGE notification handler to monitor date modifications 317 | //! 318 | //! @param pNMHDR Pointer to NMDATETIMECHANGE structure 319 | //! @param pResult Must be set to zero 320 | //------------------------------------------------------------------------ 321 | void CGridEditorDateTimeCtrl::OnDateTimeChange(NMHDR *pNMHDR, LRESULT *pResult) 322 | { 323 | m_Modified = true; 324 | *pResult = 0; 325 | } 326 | 327 | //------------------------------------------------------------------------ 328 | //! DTN_USERSTRING notification handler to convert clipboard to datetime 329 | //! 330 | //! @param pNMHDR Pointer to NMDATETIMESTRING structure 331 | //! @param pResult Must be set to zero 332 | //------------------------------------------------------------------------ 333 | void CGridEditorDateTimeCtrl::OnUserString(NMHDR *pNMHDR, LRESULT *pResult) 334 | { 335 | NMDATETIMESTRINGW* pDateInfoW = reinterpret_cast(pNMHDR); 336 | NMDATETIMESTRINGA* pDateInfoA = reinterpret_cast(pNMHDR); 337 | 338 | CString userstr; 339 | if (pNMHDR->code == DTN_USERSTRINGA) 340 | userstr = pDateInfoA->pszUserString; 341 | else 342 | userstr = pDateInfoW->pszUserString; 343 | 344 | if (m_pColumnTrait) 345 | { 346 | COleDateTime dt; 347 | if (m_pColumnTrait->ParseDateTime(userstr, dt)) 348 | { 349 | if (pNMHDR->code == DTN_USERSTRINGA) 350 | { 351 | pDateInfoA->dwFlags = GDT_VALID; 352 | dt.GetAsSystemTime(pDateInfoA->st); 353 | } 354 | else 355 | { 356 | pDateInfoW->dwFlags = GDT_VALID; 357 | dt.GetAsSystemTime(pDateInfoW->st); 358 | } 359 | } 360 | else 361 | { 362 | if (pNMHDR->code == DTN_USERSTRINGA) 363 | pDateInfoA->dwFlags = GDT_NONE; 364 | else 365 | pDateInfoW->dwFlags = GDT_NONE; 366 | } 367 | } 368 | 369 | *pResult = 0; 370 | } 371 | 372 | //------------------------------------------------------------------------ 373 | //! Hook to proces windows messages before they are dispatched. 374 | //! Catch keyboard events that can should cause the cell value editor to close 375 | //! 376 | //! @param pMsg Points to a MSG structure that contains the message to process 377 | //! @return Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched. 378 | //------------------------------------------------------------------------ 379 | BOOL CGridEditorDateTimeCtrl::PreTranslateMessage(MSG* pMsg) 380 | { 381 | switch (pMsg->message) 382 | { 383 | case WM_KEYDOWN: 384 | { 385 | switch (pMsg->wParam) 386 | { 387 | case VK_RETURN: EndEdit(true); return TRUE; 388 | case VK_TAB: EndEdit(true); return FALSE; 389 | case VK_ESCAPE: EndEdit(false);return TRUE; 390 | } 391 | break; 392 | }; 393 | case WM_MOUSEWHEEL: EndEdit(true); return FALSE; // Don't steal event 394 | } 395 | return CDateTimeCtrl::PreTranslateMessage(pMsg); 396 | } 397 | -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitDateTime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridColumnTraitImage.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CDateTimeCtrl; 17 | #else 18 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 19 | #endif 20 | 21 | //------------------------------------------------------------------------ 22 | //! CGridColumnTraitDateTime implements a CDateTimeCtrl as cell-editor 23 | //------------------------------------------------------------------------ 24 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitDateTime : public CGridColumnTraitImage 25 | { 26 | public: 27 | CGridColumnTraitDateTime(); 28 | 29 | void SetFormat(const CString& strFormat); 30 | CString GetFormat() const; 31 | 32 | void SetStyle(DWORD dwStyle); 33 | DWORD GetStyle() const; 34 | 35 | void SetParseDateTime(DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT); 36 | 37 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol); 38 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) { return CGridColumnTraitImage::OnEditBegin(owner, nRow, nCol, pt); } 39 | virtual int OnSortRows(LPCTSTR pszLeftValue, LPCTSTR pszRightValue, bool bAscending); 40 | virtual int OnSortRows(const LVITEM& leftItem, const LVITEM& rightItem, bool bAscending) { return CGridColumnTraitImage::OnSortRows(leftItem, rightItem, bAscending); } 41 | virtual BOOL ParseDateTime(LPCTSTR lpszDate, COleDateTime& dt); 42 | 43 | protected: 44 | virtual void Accept(CGridColumnTraitVisitor& visitor); 45 | virtual CDateTimeCtrl* CreateDateTimeCtrl(CGridListCtrlEx& owner, int nRow, int nCol, DWORD dwStyle, const CRect& rect); 46 | 47 | CString m_Format; //!< DateTime format used to display the date 48 | DWORD m_ParseDateTimeFlags; //!< Flags for locale settings and parsing (COleDateTime::ParseDateTime) 49 | LCID m_ParseDateTimeLCID; //!< Locale ID to use for the conversion. (COleDateTime::ParseDateTime) 50 | DWORD m_DateTimeCtrlStyle; //!< Style to use when creating CDateTimeCtrl 51 | }; 52 | 53 | //------------------------------------------------------------------------ 54 | //! CDateTimeCtrl for inplace edit. For internal use by CGridColumnTraitDateTime 55 | //------------------------------------------------------------------------ 56 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridEditorDateTimeCtrl : public CDateTimeCtrl 57 | { 58 | DECLARE_DYNAMIC(CGridEditorDateTimeCtrl) 59 | 60 | public: 61 | CGridEditorDateTimeCtrl(int nRow, int nCol, CGridColumnTraitDateTime* pColumnTrait = NULL); 62 | 63 | protected: 64 | afx_msg void OnKillFocus(CWnd *pNewWnd); 65 | afx_msg void OnDateTimeChange(NMHDR *pNMHDR, LRESULT *pResult); 66 | afx_msg void OnUserString(NMHDR *pNMHDR, LRESULT *pResult); 67 | afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); 68 | afx_msg void OnCloseUp(NMHDR *pNMHDR, LRESULT *pResult); 69 | 70 | virtual void EndEdit(bool bSuccess); 71 | virtual void PostNcDestroy(); 72 | virtual BOOL PreTranslateMessage(MSG* pMsg); 73 | 74 | bool m_Completed; //!< Ensure the editor only reacts to a single close event 75 | bool m_Modified; //!< Register if date was modified while the editor was open 76 | int m_Row; //!< The index of the row being edited 77 | int m_Col; //!< The index of the column being edited 78 | 79 | CGridColumnTraitDateTime* m_pColumnTrait; //!< Provides logic for parsing free text editing 80 | 81 | DECLARE_MESSAGE_MAP(); 82 | 83 | private: 84 | CGridEditorDateTimeCtrl(const CGridEditorDateTimeCtrl&); 85 | CGridEditorDateTimeCtrl& operator=(const CGridEditorDateTimeCtrl&); 86 | }; 87 | 88 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 89 | #undef AFX_DATA 90 | #define AFX_DATA 91 | #endif 92 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitEdit.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // Author: Rolf Kristensen 3 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 4 | // License: Free to use for all (New BSD License) 5 | //------------------------------------------------------------------------ 6 | 7 | #include "stdafx.h" 8 | #pragma warning(disable:4100) // unreferenced formal parameter 9 | 10 | #include "CGridColumnTraitEdit.h" 11 | 12 | #include "CGridColumnTraitVisitor.h" 13 | #include "CGridListCtrlEx.h" 14 | 15 | //------------------------------------------------------------------------ 16 | //! CGridColumnTraitEdit - Constructor 17 | //------------------------------------------------------------------------ 18 | CGridColumnTraitEdit::CGridColumnTraitEdit() 19 | : m_EditStyle(ES_AUTOHSCROLL | ES_NOHIDESEL | WS_BORDER) 20 | , m_EditLimitText(UINT_MAX) 21 | { 22 | } 23 | 24 | //------------------------------------------------------------------------ 25 | //! Accept Visitor Pattern 26 | //------------------------------------------------------------------------ 27 | void CGridColumnTraitEdit::Accept(CGridColumnTraitVisitor& visitor) 28 | { 29 | visitor.Visit(*this); 30 | } 31 | 32 | //------------------------------------------------------------------------ 33 | //! Set style used when creating CEdit for cell value editing 34 | //! 35 | //! @param dwStyle Style flags 36 | //------------------------------------------------------------------------ 37 | void CGridColumnTraitEdit::SetStyle(DWORD dwStyle) 38 | { 39 | m_EditStyle = dwStyle; 40 | } 41 | 42 | //------------------------------------------------------------------------ 43 | //! Get style used when creating CEdit for cell value editing 44 | //! 45 | //! @return Style flags 46 | //------------------------------------------------------------------------ 47 | DWORD CGridColumnTraitEdit::GetStyle() const 48 | { 49 | return m_EditStyle; 50 | } 51 | 52 | //------------------------------------------------------------------------ 53 | //! Set max number of characters the CEdit will accept 54 | //! 55 | //! @param nMaxChars The text limit, in characters. 56 | //------------------------------------------------------------------------ 57 | void CGridColumnTraitEdit::SetLimitText(UINT nMaxChars) 58 | { 59 | m_EditLimitText = nMaxChars; 60 | } 61 | 62 | //------------------------------------------------------------------------ 63 | //! Get max number of characters the CEdit will accept 64 | //! 65 | //! @return The text limit, in characters 66 | //------------------------------------------------------------------------ 67 | UINT CGridColumnTraitEdit::GetLimitText() const 68 | { 69 | return m_EditLimitText; 70 | } 71 | 72 | 73 | //------------------------------------------------------------------------ 74 | //! Create a CEdit as cell value editor 75 | //! 76 | //! @param owner The list control starting a cell edit 77 | //! @param nRow The index of the row 78 | //! @param nCol The index of the column 79 | //! @param dwStyle The windows style to use when creating the CEdit 80 | //! @param rect The rectangle where the inplace cell value editor should be placed 81 | //! @return Pointer to the cell editor to use 82 | //------------------------------------------------------------------------ 83 | CEdit* CGridColumnTraitEdit::CreateEdit(CGridListCtrlEx& owner, int nRow, int nCol, DWORD dwStyle, const CRect& rect) 84 | { 85 | CGridEditorText* pEdit = new CGridEditorText(nRow, nCol); 86 | VERIFY(pEdit->Create(WS_CHILD | dwStyle, rect, &owner, 0)); 87 | return pEdit; 88 | } 89 | 90 | //------------------------------------------------------------------------ 91 | //! Overrides OnEditBegin() to provide a CEdit cell value editor 92 | //! 93 | //! @param owner The list control starting edit 94 | //! @param nRow The index of the row for the cell to edit 95 | //! @param nCol The index of the column for the cell to edit 96 | //! @return Pointer to the cell editor to use (NULL if cell edit is not possible) 97 | //------------------------------------------------------------------------ 98 | CWnd* CGridColumnTraitEdit::OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol) 99 | { 100 | // Get position of the cell to edit 101 | CRect rectCell = GetCellEditRect(owner, nRow, nCol); 102 | 103 | // Get the text-style of the cell to edit 104 | DWORD dwStyle = m_EditStyle; 105 | HDITEM hditem = { 0 }; 106 | hditem.mask = HDI_FORMAT; 107 | VERIFY(owner.GetHeaderCtrl()->GetItem(nCol, &hditem)); 108 | if (hditem.fmt & HDF_CENTER) 109 | dwStyle |= ES_CENTER; 110 | else if (hditem.fmt & HDF_RIGHT) 111 | dwStyle |= ES_RIGHT; 112 | else 113 | dwStyle |= ES_LEFT; 114 | 115 | // Create edit control to edit the cell 116 | CEdit* pEdit = CreateEdit(owner, nRow, nCol, dwStyle, rectCell); 117 | VERIFY(pEdit != NULL); 118 | if (pEdit == NULL) 119 | return NULL; 120 | 121 | // Configure font 122 | pEdit->SetFont(owner.GetCellFont()); 123 | 124 | // First column (Label) doesn't have a margin when imagelist is assigned 125 | if (nCol == 0 && owner.GetImageList(LVSIL_SMALL) != NULL) 126 | pEdit->SetMargins(0, 0); 127 | // First column (Label) doesn't have a margin when checkboxes are enabled 128 | else if (nCol == 0 && owner.GetExtendedStyle() & LVS_EX_CHECKBOXES) 129 | pEdit->SetMargins(1, 0); 130 | // Label column doesn't have margin when not first in column order 131 | else if (nCol == 0 && owner.GetFirstVisibleColumn() != nCol) 132 | pEdit->SetMargins(1, 0); 133 | else if (dwStyle & ES_CENTER) 134 | pEdit->SetMargins(0, 0); 135 | else if (dwStyle & ES_RIGHT) 136 | pEdit->SetMargins(0, 7); 137 | else 138 | pEdit->SetMargins(4, 0); 139 | 140 | if (m_EditLimitText != UINT_MAX) 141 | pEdit->SetLimitText(m_EditLimitText); 142 | 143 | CString cellText = owner.GetItemText(nRow, nCol); 144 | pEdit->SetWindowText(cellText); 145 | pEdit->SetSel(0, -1, 0); 146 | return pEdit; 147 | } 148 | 149 | //------------------------------------------------------------------------ 150 | // CGridEditorText (For internal use) 151 | //------------------------------------------------------------------------ 152 | IMPLEMENT_DYNAMIC(CGridEditorText, CEdit) 153 | 154 | BEGIN_MESSAGE_MAP(CGridEditorText, CEdit) 155 | //{{AFX_MSG_MAP(CGridEditorText) 156 | ON_WM_KILLFOCUS() 157 | ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange) 158 | //}}AFX_MSG_MAP 159 | END_MESSAGE_MAP() 160 | 161 | //------------------------------------------------------------------------ 162 | //! CGridEditorText - Constructor 163 | //------------------------------------------------------------------------ 164 | CGridEditorText::CGridEditorText(int nRow, int nCol) 165 | : m_Row(nRow) 166 | , m_Col(nCol) 167 | , m_Completed(false) 168 | , m_Modified(false) 169 | , m_InitialModify(true) 170 | {} 171 | 172 | //------------------------------------------------------------------------ 173 | //! The cell value editor was closed and the entered should be saved. 174 | //! 175 | //! @param bSuccess Should the entered cell value be saved 176 | //------------------------------------------------------------------------ 177 | void CGridEditorText::EndEdit(bool bSuccess) 178 | { 179 | // Avoid two messages if key-press is followed by kill-focus 180 | if (m_Completed) 181 | return; 182 | 183 | m_Completed = true; 184 | 185 | // Send Notification to parent of ListView ctrl 186 | CString str; 187 | GetWindowText(str); 188 | 189 | LV_DISPINFO dispinfo = { 0 }; 190 | if (bSuccess && m_Modified) 191 | { 192 | dispinfo.item.mask = LVIF_TEXT; 193 | dispinfo.item.pszText = str.GetBuffer(0); 194 | dispinfo.item.cchTextMax = str.GetLength(); 195 | } 196 | ShowWindow(SW_HIDE); 197 | CGridColumnTraitImage::SendEndLabelEdit(*GetParent(), m_Row, m_Col, dispinfo); 198 | PostMessage(WM_CLOSE); 199 | } 200 | 201 | //------------------------------------------------------------------------ 202 | //! WM_KILLFOCUS message handler called when CEdit is loosing focus 203 | //! to other control. Used register that cell value editor should close. 204 | //! 205 | //! @param pNewWnd Pointer to the window that receives the input focus (may be NULL or may be temporary). 206 | //------------------------------------------------------------------------ 207 | void CGridEditorText::OnKillFocus(CWnd *pNewWnd) 208 | { 209 | CEdit::OnKillFocus(pNewWnd); 210 | EndEdit(true); 211 | } 212 | 213 | //------------------------------------------------------------------------ 214 | //! Called by the default OnNcDestroy (WM_NCDESTROY) message handler, 215 | //! when CEdit window has been be destroyed. 216 | //! Used to delete the inplace CEdit editor object as well. 217 | //! This is necessary when the CEdit is created dynamically. 218 | //------------------------------------------------------------------------ 219 | void CGridEditorText::PostNcDestroy() 220 | { 221 | CEdit::PostNcDestroy(); 222 | delete this; 223 | } 224 | 225 | //------------------------------------------------------------------------ 226 | //! EN_CHANGE notification handler to monitor text modifications 227 | //------------------------------------------------------------------------ 228 | void CGridEditorText::OnEnChange() 229 | { 230 | if (!m_InitialModify) 231 | m_Modified = true; 232 | else 233 | m_InitialModify = false; 234 | } 235 | 236 | //------------------------------------------------------------------------ 237 | //! Hook to proces windows messages before they are dispatched. 238 | //! Catch keyboard events that can should cause the cell value editor to close 239 | //! 240 | //! @param pMsg Points to a MSG structure that contains the message to process 241 | //! @return Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched. 242 | //------------------------------------------------------------------------ 243 | BOOL CGridEditorText::PreTranslateMessage(MSG* pMsg) 244 | { 245 | switch (pMsg->message) 246 | { 247 | case WM_KEYDOWN: 248 | { 249 | switch (pMsg->wParam) 250 | { 251 | case VK_RETURN: 252 | { 253 | if (GetStyle() & ES_WANTRETURN) 254 | break; 255 | 256 | EndEdit(true); 257 | return TRUE; 258 | } 259 | case VK_TAB: EndEdit(true); return FALSE; 260 | case VK_ESCAPE: EndEdit(false);return TRUE; 261 | } 262 | break; 263 | }; 264 | case WM_MOUSEWHEEL: EndEdit(true); return FALSE; // Don't steal event 265 | } 266 | return CEdit::PreTranslateMessage(pMsg); 267 | } 268 | -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitEdit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridColumnTraitImage.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CEdit; 17 | #else 18 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 19 | #endif 20 | 21 | class CGridEditorText; 22 | 23 | //------------------------------------------------------------------------ 24 | //! CGridColumnTraitEdit implements a CEdit as cell-editor 25 | //------------------------------------------------------------------------ 26 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitEdit : public CGridColumnTraitImage 27 | { 28 | public: 29 | CGridColumnTraitEdit(); 30 | 31 | void SetStyle(DWORD dwStyle); 32 | DWORD GetStyle() const; 33 | 34 | void SetLimitText(UINT nMaxChars); 35 | UINT GetLimitText() const; 36 | 37 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol); 38 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) { return CGridColumnTraitImage::OnEditBegin(owner, nRow, nCol, pt); } 39 | 40 | protected: 41 | virtual void Accept(CGridColumnTraitVisitor& visitor); 42 | virtual CEdit* CreateEdit(CGridListCtrlEx& owner, int nRow, int nCol, DWORD dwStyle, const CRect& rect); 43 | 44 | DWORD m_EditStyle; //!< Style to use when creating CEdit 45 | UINT m_EditLimitText; //!< Max number of characters the CEdit will accept 46 | }; 47 | 48 | //------------------------------------------------------------------------ 49 | //! CEdit for inplace edit. For internal use by CGridColumnTraitEdit 50 | //------------------------------------------------------------------------ 51 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridEditorText : public CEdit 52 | { 53 | DECLARE_DYNAMIC(CGridEditorText) 54 | 55 | public: 56 | CGridEditorText(int nRow, int nCol); 57 | virtual void EndEdit(bool bSuccess); 58 | 59 | protected: 60 | afx_msg void OnKillFocus(CWnd *pNewWnd); 61 | afx_msg void OnEnChange(); 62 | 63 | virtual void PostNcDestroy(); 64 | virtual BOOL PreTranslateMessage(MSG* pMsg); 65 | 66 | int m_Row; //!< The index of the row being edited 67 | int m_Col; //!< The index of the column being edited 68 | bool m_Completed; //!< Ensure the editor only reacts to a single close event 69 | bool m_Modified; //!< Register if text was modified while the editor was open 70 | bool m_InitialModify; //!< Initial text modication should not set that the editor text was modified 71 | 72 | DECLARE_MESSAGE_MAP(); 73 | 74 | private: 75 | CGridEditorText(); 76 | CGridEditorText(const CGridEditorText&); 77 | CGridEditorText& operator=(const CGridEditorText&); 78 | }; 79 | 80 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 81 | #undef AFX_DATA 82 | #define AFX_DATA 83 | #endif 84 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitHyperLink.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // Author: Rolf Kristensen 3 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 4 | // License: Free to use for all (New BSD License) 5 | //------------------------------------------------------------------------ 6 | 7 | #include "stdafx.h" 8 | #include "CGridColumnTraitHyperLink.h" 9 | 10 | #include "CGridListCtrlEx.h" 11 | 12 | //------------------------------------------------------------------------ 13 | //! CGridColumnTraitHyperLink - Constructor 14 | //------------------------------------------------------------------------ 15 | CGridColumnTraitHyperLink::CGridColumnTraitHyperLink() 16 | { 17 | m_ShellFilePrefix = _T("http://google.com/?q="); 18 | m_ShellShowCommand = SW_SHOWNORMAL; 19 | m_LinkColor = RGB(22, 74, 170); 20 | m_LinkColorHot = RGB(0, 85, 255); 21 | SetSingleClickEdit(true); 22 | } 23 | 24 | //------------------------------------------------------------------------ 25 | //! Set the standard link color 26 | //! 27 | //! @param linkColor Link RGB Colors 28 | //------------------------------------------------------------------------ 29 | void CGridColumnTraitHyperLink::SetLinkColor(COLORREF linkColor) 30 | { 31 | m_LinkColor = linkColor; 32 | } 33 | 34 | //------------------------------------------------------------------------ 35 | //! Get the standard link color 36 | //! 37 | //! @return Link RGB Colors 38 | //------------------------------------------------------------------------ 39 | COLORREF CGridColumnTraitHyperLink::GetLinkColor() const 40 | { 41 | return m_LinkColor; 42 | } 43 | 44 | //------------------------------------------------------------------------ 45 | //! Set the link color when mouse is over the cell 46 | //! 47 | //! @param linkColor Link RGB Colors 48 | //------------------------------------------------------------------------ 49 | void CGridColumnTraitHyperLink::SetLinkColorHot(COLORREF linkColor) 50 | { 51 | m_LinkColorHot = linkColor; 52 | } 53 | 54 | //------------------------------------------------------------------------ 55 | //! Get the link color when mouse is over the cell 56 | //! 57 | //! @return Link RGB Colors 58 | //------------------------------------------------------------------------ 59 | COLORREF CGridColumnTraitHyperLink::GetLinkColorHot() const 60 | { 61 | return m_LinkColorHot; 62 | } 63 | 64 | //------------------------------------------------------------------------ 65 | //! Set the ShellExecute file operation to perform on the file-specifier 66 | //! 67 | //! @param strShellOperation Link Action Name 68 | //------------------------------------------------------------------------ 69 | void CGridColumnTraitHyperLink::SetShellOperation(const CString& strShellOperation) 70 | { 71 | m_ShellOperation = strShellOperation; 72 | } 73 | 74 | //------------------------------------------------------------------------ 75 | //! Get the ShellExecute file operation to perform on the file-specifier 76 | //! 77 | //! @return Link Action Name 78 | //------------------------------------------------------------------------ 79 | CString CGridColumnTraitHyperLink::GetShellOperation() const 80 | { 81 | return m_ShellOperation; 82 | } 83 | 84 | //------------------------------------------------------------------------ 85 | //! Set the ShellExecute application to use to launch the file specifier 86 | //! 87 | //! @param strShellAppliction Application path (If blank then it just uses the default handler for the file type) 88 | //------------------------------------------------------------------------ 89 | void CGridColumnTraitHyperLink::SetShellApplication(const CString& strShellAppliction) 90 | { 91 | m_ShellApplication = strShellAppliction; 92 | } 93 | 94 | //------------------------------------------------------------------------ 95 | //! Get the ShellExecute application to use to launch the file specifier 96 | //! 97 | //! @return Application path 98 | //------------------------------------------------------------------------ 99 | CString CGridColumnTraitHyperLink::GetShellApplication() const 100 | { 101 | return m_ShellApplication; 102 | } 103 | 104 | //------------------------------------------------------------------------ 105 | //! Set the file specifier prefix for the ShellExecute operation 106 | //! (Ex. protocol details like 'mailto:' or 'http://') 107 | //! 108 | //! @param strShellFilePrefix Prefix to insert infront of the file-sepecifier 109 | //------------------------------------------------------------------------ 110 | void CGridColumnTraitHyperLink::SetShellFilePrefix(const CString& strShellFilePrefix) 111 | { 112 | m_ShellFilePrefix = strShellFilePrefix; 113 | } 114 | 115 | //------------------------------------------------------------------------ 116 | //! Get the file specifier prefix for the ShellExecute operation 117 | //! 118 | //! @return Prefix to insert infront of the filename specifier 119 | //------------------------------------------------------------------------ 120 | CString CGridColumnTraitHyperLink::GetShellFilePrefix() const 121 | { 122 | return m_ShellFilePrefix; 123 | } 124 | 125 | //------------------------------------------------------------------------ 126 | //! Set the file specifier suffix for the ShellExecute operation 127 | //! 128 | //! @param strShellFileSuffix File operation to perform on the file-specifier 129 | //------------------------------------------------------------------------ 130 | void CGridColumnTraitHyperLink::SetShellFileSuffix(const CString& strShellFileSuffix) 131 | { 132 | m_ShellFileSuffix = strShellFileSuffix; 133 | } 134 | 135 | //------------------------------------------------------------------------ 136 | //! Get the file specifier suffix for the ShellExecute operation 137 | //! 138 | //! @return Suffix to append after the filename specifier 139 | //------------------------------------------------------------------------ 140 | CString CGridColumnTraitHyperLink::GetShellFileSuffix() const 141 | { 142 | return m_ShellFileSuffix; 143 | } 144 | 145 | //------------------------------------------------------------------------ 146 | //! Set the show window flags for the ShellExecute operation 147 | //! 148 | //! @param nShellShowCommand Show Command Flags 149 | //------------------------------------------------------------------------ 150 | void CGridColumnTraitHyperLink::SetShellShowCommand(INT nShellShowCommand) 151 | { 152 | m_ShellShowCommand = nShellShowCommand; 153 | } 154 | 155 | //------------------------------------------------------------------------ 156 | //! Get the show window flags for the ShellExecute operation 157 | //! 158 | //! @return Show Command Flags 159 | //------------------------------------------------------------------------ 160 | INT CGridColumnTraitHyperLink::GetShellShowCommand() const 161 | { 162 | return m_ShellShowCommand; 163 | } 164 | 165 | //------------------------------------------------------------------------ 166 | //! Changes the text color if one is specified 167 | //! 168 | //! @param pLVCD Pointer to NMLVCUSTOMDRAW structure 169 | //! @param textColor Current text color 170 | //! @return New text color was specified (true / false) 171 | //------------------------------------------------------------------------ 172 | bool CGridColumnTraitHyperLink::UpdateTextColor(NMLVCUSTOMDRAW* pLVCD, COLORREF& textColor) 173 | { 174 | if (pLVCD->nmcd.uItemState & CDIS_HOT) 175 | textColor = m_LinkColorHot; 176 | else 177 | textColor = m_LinkColor; 178 | return true; 179 | } 180 | 181 | //------------------------------------------------------------------------ 182 | //! Specifies af the font color if one is specified 183 | //! 184 | //! @param pLVCD Pointer to NMLVCUSTOMDRAW structure 185 | //! @param textFont New font specification 186 | //! @return New font was specified (true / false) 187 | //------------------------------------------------------------------------ 188 | bool CGridColumnTraitHyperLink::UpdateTextFont(NMLVCUSTOMDRAW* pLVCD, LOGFONT& textFont) 189 | { 190 | CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 191 | CFont* pCurrentFont = pDC->GetCurrentFont(); 192 | pCurrentFont->GetLogFont(&textFont); 193 | textFont.lfUnderline = 1; 194 | return true; 195 | } 196 | 197 | //------------------------------------------------------------------------ 198 | //! Returns dimensions of the cell text clicked 199 | //! 200 | //! @param owner The list control being clicked 201 | //! @param nRow The index of the row 202 | //! @param nCol The index of the column 203 | //! @param cellText The contents of the cell clicked 204 | //! @return The dimensions of the cell text 205 | //------------------------------------------------------------------------ 206 | CRect CGridColumnTraitHyperLink::GetTextRect(CGridListCtrlEx& owner, int nRow, int nCol, const CString& cellText) 207 | { 208 | CRect rect; 209 | ASSERT(nRow != -1); 210 | CDC* pDC = owner.GetDC(); 211 | CFont* pOldFont = pDC->SelectObject(owner.GetCellFont()); 212 | CSize size = pDC->GetTextExtent(cellText); 213 | pDC->SelectObject(pOldFont); 214 | owner.ReleaseDC(pDC); 215 | 216 | owner.GetCellRect(nRow, nCol, LVIR_LABEL, rect); 217 | 218 | HDITEM hditem = { 0 }; 219 | hditem.mask = HDI_FORMAT; 220 | owner.GetHeaderCtrl()->GetItem(nCol, &hditem); 221 | 222 | // First item (Label) doesn't have a margin (Subitems does) 223 | if (nCol != 0 && !(hditem.fmt & HDF_CENTER)) 224 | { 225 | if (hditem.fmt & HDF_RIGHT) 226 | rect.OffsetRect(-7, 0); 227 | else 228 | rect.OffsetRect(4, 0); 229 | } 230 | 231 | if (hditem.fmt & HDF_CENTER) 232 | rect.DeflateRect((rect.Width() - size.cx) / 2, 0); 233 | else if (hditem.fmt & HDF_RIGHT) 234 | rect.left = rect.right - size.cx; 235 | else 236 | rect.right = rect.left + size.cx; 237 | return rect; 238 | } 239 | 240 | //------------------------------------------------------------------------ 241 | //! Overrides OnEditBegin() to launch ShellExecute when starting editor 242 | //! 243 | //! @param owner The list control starting edit 244 | //! @param nRow The index of the row for the cell to edit 245 | //! @param nCol The index of the column for the cell to edit 246 | //! @return Pointer to the cell editor to use (NULL if cell edit is not possible) 247 | //------------------------------------------------------------------------ 248 | CWnd* CGridColumnTraitHyperLink::OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol) 249 | { 250 | CString cellText = owner.GetItemText(nRow, nCol); 251 | OnShellExecute(owner, nRow, nCol, cellText); 252 | LV_DISPINFO dispinfo = { 0 }; 253 | SendEndLabelEdit(owner, nRow, nCol, dispinfo); 254 | return NULL; 255 | } 256 | 257 | //------------------------------------------------------------------------ 258 | //! Checks if the mouse click should start the cell editor (OnEditBegin) 259 | //! Validates that the click was on the text-link within the label-part 260 | //! 261 | //! @param owner The list control being clicked 262 | //! @param nRow The index of the row 263 | //! @param nCol The index of the column 264 | //! @param pt The position clicked, in client coordinates. 265 | //! @param bDblClick Whether the position was double clicked 266 | //! @return How should the cell editor be started (0 = No editor, 1 = Start Editor, 2 = Start Editor and block click-event) 267 | //------------------------------------------------------------------------ 268 | int CGridColumnTraitHyperLink::OnClickEditStart(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt, bool bDblClick) 269 | { 270 | int startEdit = CGridColumnTraitImage::OnClickEditStart(owner, nRow, nCol, pt, bDblClick); 271 | if (startEdit) 272 | { 273 | // Check if mouse click was inside the label-part of the cell 274 | CRect labelRect; 275 | if (owner.GetCellRect(nRow, nCol, LVIR_LABEL, labelRect) && labelRect.PtInRect(pt)) 276 | { 277 | // Check if mouse click was inside the text-link of the cell 278 | CString cellText = owner.GetItemText(nRow, nCol); 279 | if (GetTextRect(owner, nRow, nCol, cellText).PtInRect(pt)) 280 | return startEdit; 281 | else 282 | return 0; 283 | } 284 | } 285 | return startEdit; 286 | } 287 | 288 | //------------------------------------------------------------------------ 289 | //! Performs the ShellExecute operation on the given file specifier 290 | //! 291 | //! @param owner The list control starting edit 292 | //! @param nRow The index of the row for the cell to edit 293 | //! @param nCol The index of the column for the cell to edit 294 | //! @param cellText The contents of the cell clicked 295 | //------------------------------------------------------------------------ 296 | void CGridColumnTraitHyperLink::OnShellExecute(CGridListCtrlEx& owner, int nRow, int nCol, const CString& cellText) 297 | { 298 | (nRow); // Avoid unreferenced variable warning 299 | (nCol); // Avoid unreferenced variable warning 300 | if (m_ShellApplication.IsEmpty()) 301 | ShellExecute(owner.m_hWnd, m_ShellOperation.IsEmpty() ? (LPCTSTR)NULL : static_cast(m_ShellOperation), m_ShellFilePrefix + cellText + m_ShellFileSuffix, NULL, NULL, m_ShellShowCommand); 302 | else 303 | ShellExecute(owner.m_hWnd, m_ShellOperation.IsEmpty() ? (LPCTSTR)NULL : static_cast(m_ShellOperation), m_ShellApplication, m_ShellFilePrefix + cellText + m_ShellFileSuffix, NULL, m_ShellShowCommand); 304 | } -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitHyperLink.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridColumnTraitImage.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | #else 17 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 18 | #endif 19 | 20 | //------------------------------------------------------------------------ 21 | //! CGridColumnTraitHyperLink that can launch a link using the web-browser 22 | //------------------------------------------------------------------------ 23 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitHyperLink : public CGridColumnTraitImage 24 | { 25 | public: 26 | CGridColumnTraitHyperLink(); 27 | 28 | void SetLinkColor(COLORREF linkColor); 29 | COLORREF GetLinkColor() const; 30 | 31 | void SetLinkColorHot(COLORREF linkColor); 32 | COLORREF GetLinkColorHot() const; 33 | 34 | void SetShellOperation(const CString& strShellOperation); 35 | CString GetShellOperation() const; 36 | 37 | void SetShellApplication(const CString& strShellAppliction); 38 | CString GetShellApplication() const; 39 | 40 | void SetShellFilePrefix(const CString& strShellFilePrefix); 41 | CString GetShellFilePrefix() const; 42 | 43 | void SetShellFileSuffix(const CString& strShellFileSuffix); 44 | CString GetShellFileSuffix() const; 45 | 46 | void SetShellShowCommand(INT nShellShowCommand); 47 | INT GetShellShowCommand() const; 48 | 49 | protected: 50 | virtual bool UpdateTextColor(NMLVCUSTOMDRAW* pLVCD, COLORREF& textColor); 51 | virtual bool UpdateTextFont(NMLVCUSTOMDRAW* pLVCD, LOGFONT& textFont); 52 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol); 53 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) { return CGridColumnTraitImage::OnEditBegin(owner, nRow, nCol, pt); } 54 | virtual int OnClickEditStart(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt, bool bDblClick); 55 | 56 | virtual void OnShellExecute(CGridListCtrlEx& owner, int nRow, int nCol, const CString& cellText); 57 | virtual CRect GetTextRect(CGridListCtrlEx& owner, int nRow, int nCol, const CString& cellText); 58 | 59 | COLORREF m_LinkColor; //!< Standard link Color 60 | COLORREF m_LinkColorHot; //!< Hot link color (mouse over) 61 | CString m_ShellOperation; //!< ShellExecute operation (Ex. "open") 62 | CString m_ShellApplication; //!< ShellExecute application (If blank it launches cell text with default application) 63 | CString m_ShellFilePrefix; //!< ShellExecute file specifier prefix 64 | CString m_ShellFileSuffix; //!< ShellExecute file specifier suffix 65 | INT m_ShellShowCommand; //!< ShellExecute show application flags (Ex. SW_SHOWNORMAL) 66 | }; 67 | 68 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 69 | #undef AFX_DATA 70 | #define AFX_DATA 71 | #endif 72 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitImage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridColumnTraitText.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | template class CGRIDLISTCTRLEX_AFX_EXT_CLASS CSimpleMap; 17 | template class CGRIDLISTCTRLEX_AFX_EXT_CLASS CSimpleMap; 18 | #else 19 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 20 | #endif 21 | 22 | //------------------------------------------------------------------------ 23 | //! CGridColumnTraitImage implements an image switcher (can mimic a checkbox) 24 | //! 25 | //! By adding checkbox state-images to the official imagelist using 26 | //! AppendStateImages(), then one can use this column trait as checkbox 27 | //! editor. To get/set the checkbox value of a cell use the methods 28 | //! GetCellImage()/SetCellImage() on CGridListCtrlEx 29 | //------------------------------------------------------------------------ 30 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitImage : public CGridColumnTraitText 31 | { 32 | public: 33 | CGridColumnTraitImage(); 34 | CGridColumnTraitImage(int nImageIndex, int nImageCount); 35 | 36 | void AddImageIndex(int nImageIdx); 37 | void AddImageIndex(int nImageIdx, const CString& strImageText, bool bEditable = true); 38 | 39 | void SetImageText(int nImageIdx, const CString& strImageText, bool bEditable = true); 40 | 41 | void SetSortImageIndex(bool bValue); 42 | bool GetSortImageIndex() const; 43 | 44 | void SetToggleSelection(bool bValue); 45 | bool GetToggleSelection() const; 46 | 47 | void SetSingleClickEdit(bool bValue); 48 | bool GetSingleClickEdit() const; 49 | 50 | void SetIconClickBeginEdit(bool bValue); 51 | bool GetIconClickBeginEdit() const; 52 | 53 | static int AppendStateImages(CGridListCtrlEx& owner, CImageList& imagelist); 54 | static LRESULT SendEndLabelEdit(CWnd& wndListCtrl, int nRow, int nCol, LV_DISPINFO& dispInfo); 55 | 56 | protected: 57 | virtual int OnSortRows(LPCTSTR pszLeftValue, LPCTSTR pszRightValue, bool bAscending) { return CGridColumnTraitText::OnSortRows(pszLeftValue, pszRightValue, bAscending); } 58 | virtual int OnSortRows(const LVITEM& leftItem, const LVITEM& rightItem, bool bAscending); 59 | virtual bool IsCellReadOnly(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt) const; 60 | virtual int OnClickEditStart(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt, bool bDblClick); 61 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol) { return CGridColumnTraitText::OnEditBegin(owner, nRow, nCol); } 62 | virtual CWnd* OnEditBegin(CGridListCtrlEx& owner, int nRow, int nCol, CPoint pt); 63 | virtual void Accept(CGridColumnTraitVisitor& visitor); 64 | virtual int FlipImageIndex(CGridListCtrlEx& owner, int nRow, int nCol); 65 | virtual CWnd* OnEditBeginImage(CGridListCtrlEx& owner, int nRow, int nCol); 66 | virtual CWnd* OnEditBeginCheckbox(CGridListCtrlEx& owner, int nRow, int nCol); 67 | 68 | CSimpleMap m_ImageCellText; //!< Fixed list of image items to switch between 69 | CSimpleMap m_ImageCellEdit; //!< Fixed list of image items to switch between 70 | 71 | bool m_SortImageIndex; //!< Should image be used as primary sort index ? 72 | bool m_ToggleSelection; //!< Should the image of all selected rows be flipped, when clicked ? 73 | bool m_SingleClickEdit; //!< Should it start editor on first click, instead of first waiting for cell to have focus first 74 | bool m_IconClickBeginEdit; //!< Should it start editor when clicking the icon area ? 75 | }; 76 | 77 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 78 | #undef AFX_DATA 79 | #define AFX_DATA 80 | #endif 81 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitMultilineEdit.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // Author: Rolf Kristensen 3 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 4 | // License: Free to use for all (New BSD License) 5 | //------------------------------------------------------------------------ 6 | 7 | #include "stdafx.h" 8 | #include "CGridColumnTraitMultilineEdit.h" 9 | 10 | #include "CGridColumnTraitVisitor.h" 11 | #include "CGridListCtrlEx.h" 12 | 13 | //------------------------------------------------------------------------ 14 | //! CGridColumnTraitMultilineEdit - Constructor 15 | //------------------------------------------------------------------------ 16 | CGridColumnTraitMultilineEdit::CGridColumnTraitMultilineEdit() 17 | :m_EditMaxLines(4) 18 | { 19 | m_EditStyle |= ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL; 20 | } 21 | 22 | //------------------------------------------------------------------------ 23 | //! Accept Visitor Pattern 24 | //------------------------------------------------------------------------ 25 | void CGridColumnTraitMultilineEdit::Accept(CGridColumnTraitVisitor& visitor) 26 | { 27 | visitor.Visit(*this); 28 | } 29 | 30 | //------------------------------------------------------------------------ 31 | //! Set max number of lines that can the CEdit will display at a time 32 | //! For multiline editing then add these styles ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL 33 | //! 34 | //! @param nMaxLines The text limit, in lines. 35 | //------------------------------------------------------------------------ 36 | void CGridColumnTraitMultilineEdit::SetMaxLines(UINT nMaxLines) 37 | { 38 | m_EditMaxLines = nMaxLines; 39 | } 40 | 41 | //------------------------------------------------------------------------ 42 | //! Get max number of lines that can the CEdit will display at a time 43 | //! 44 | //! @return Max number of display lines for the multiline CEdit 45 | //------------------------------------------------------------------------ 46 | UINT CGridColumnTraitMultilineEdit::GetMaxLines() const 47 | { 48 | return m_EditMaxLines; 49 | } 50 | 51 | 52 | namespace 53 | { 54 | int CharacterCount(const CString& csHaystack, LPCTSTR sNeedle) 55 | { 56 | if (csHaystack.IsEmpty()) 57 | return 0; 58 | 59 | int nFind = -1; 60 | int nCount = 0; 61 | do 62 | { 63 | nCount++; 64 | nFind = csHaystack.Find(sNeedle, nFind + 1); 65 | } while (nFind != -1); 66 | 67 | return nCount - 1; 68 | } 69 | } 70 | 71 | //------------------------------------------------------------------------ 72 | //! Create a CEdit as cell value editor 73 | //! 74 | //! @param owner The list control starting a cell edit 75 | //! @param nRow The index of the row 76 | //! @param nCol The index of the column 77 | //! @param dwStyle The windows style to use when creating the CEdit 78 | //! @param rect The rectangle where the inplace cell value editor should be placed 79 | //! @return Pointer to the cell editor to use 80 | //------------------------------------------------------------------------ 81 | CEdit* CGridColumnTraitMultilineEdit::CreateEdit(CGridListCtrlEx& owner, int nRow, int nCol, DWORD dwStyle, const CRect& rect) 82 | { 83 | CGridMultilineEditorText* pEdit = new CGridMultilineEditorText(nRow, nCol); 84 | 85 | CRect limitRect(rect); 86 | if (m_EditMaxLines > 1 && GetStyle() & ES_MULTILINE) 87 | { 88 | // Calculate the number of lines in the cell text, expand the CEdit to match this 89 | CString cellText = owner.GetItemText(nRow, nCol); 90 | int nLineHeight = GetCellFontHeight(owner); 91 | int nLineCount = CharacterCount(cellText, _T("\n")); 92 | if (nLineCount > 0) 93 | { 94 | if ((UINT)nLineCount > m_EditMaxLines - 1) 95 | nLineCount = m_EditMaxLines - 1; 96 | limitRect.bottom += nLineHeight*nLineCount; 97 | } 98 | pEdit->SetMaxLines(m_EditMaxLines); 99 | pEdit->SetLineHeight(nLineHeight); 100 | } 101 | 102 | VERIFY(pEdit->Create(WS_CHILD | dwStyle, limitRect, &owner, 0)); 103 | return pEdit; 104 | } 105 | 106 | //------------------------------------------------------------------------ 107 | // CGridMultilineEditorText (For internal use) 108 | //------------------------------------------------------------------------ 109 | IMPLEMENT_DYNAMIC(CGridMultilineEditorText, CGridEditorText) 110 | 111 | BEGIN_MESSAGE_MAP(CGridMultilineEditorText, CGridEditorText) 112 | //{{AFX_MSG_MAP(CGridEditorText) 113 | ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange) 114 | //}}AFX_MSG_MAP 115 | END_MESSAGE_MAP() 116 | 117 | //------------------------------------------------------------------------ 118 | //! CGridMultilineEditorText - Constructor 119 | //------------------------------------------------------------------------ 120 | CGridMultilineEditorText::CGridMultilineEditorText(int nRow, int nCol) 121 | : CGridEditorText(nRow, nCol) 122 | , m_LineHeight(0) 123 | , m_MaxLines(0) 124 | { 125 | } 126 | 127 | //------------------------------------------------------------------------ 128 | //! EN_CHANGE notification handler to monitor text modifications 129 | //------------------------------------------------------------------------ 130 | void CGridMultilineEditorText::OnEnChange() 131 | { 132 | if (m_InitialModify && (GetStyle() & ES_MULTILINE)) 133 | m_InitialModify = false;// ES_MULTILINE causes EN_CHANGE not to fire at initial SetWindowText 134 | 135 | // If multiline support, then resize the edit according to contents 136 | if ((m_MaxLines > 1) && (GetStyle() & ES_MULTILINE) && (m_LineHeight > 0)) 137 | { 138 | // Get number of text lines 139 | CString cellText; 140 | GetWindowText(cellText); 141 | int nLineCount = CharacterCount(cellText, _T("\n")); 142 | if (nLineCount > 0) 143 | { 144 | if ((UINT)nLineCount > m_MaxLines - 1) 145 | nLineCount = m_MaxLines - 1; 146 | } 147 | 148 | // Check if the current rect matches the number of lines 149 | CRect rect; 150 | GetWindowRect(&rect); 151 | if (rect.Height() / m_LineHeight != nLineCount + 1) 152 | { 153 | rect.bottom += (nLineCount + 1 - rect.Height() / m_LineHeight) * m_LineHeight; 154 | GetParent()->ScreenToClient(&rect); 155 | MoveWindow(rect.left, rect.top, rect.Width(), rect.Height(), TRUE); 156 | } 157 | } 158 | CGridEditorText::OnEnChange(); 159 | } -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitMultilineEdit.h: -------------------------------------------------------------------------------- 1 | #include "CGridColumnTraitEdit.h" 2 | 3 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 4 | // Using MFC Extension DLL 5 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 6 | #undef AFX_DATA 7 | #define AFX_DATA AFX_EXT_DATA 8 | #else 9 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 10 | #endif 11 | 12 | //------------------------------------------------------------------------ 13 | //! CGridColumnTraitMultilineEdit implements a CEdit as multiline cell-editor 14 | //------------------------------------------------------------------------ 15 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitMultilineEdit : public CGridColumnTraitEdit 16 | { 17 | public: 18 | CGridColumnTraitMultilineEdit(); 19 | 20 | void SetMaxLines(UINT nMaxLines); 21 | UINT GetMaxLines() const; 22 | 23 | protected: 24 | virtual void Accept(CGridColumnTraitVisitor& visitor); 25 | CEdit* CreateEdit(CGridListCtrlEx& owner, int nRow, int nCol, DWORD dwStyle, const CRect& rect); 26 | 27 | UINT m_EditMaxLines; //!< Max number of lines the CEdit will display at a time 28 | }; 29 | 30 | //------------------------------------------------------------------------ 31 | //! CEdit for inplace edit. For internal use by CGridColumnTraitMultilineEdit 32 | //------------------------------------------------------------------------ 33 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridMultilineEditorText : public CGridEditorText 34 | { 35 | DECLARE_DYNAMIC(CGridMultilineEditorText) 36 | 37 | public: 38 | CGridMultilineEditorText(int nRow, int nCol); 39 | 40 | void SetLineHeight(int nLineHeight) { m_LineHeight = nLineHeight; } 41 | void SetMaxLines(UINT nMaxLines) { m_MaxLines = nMaxLines; } 42 | 43 | protected: 44 | int m_LineHeight; //!< The height of a single line (depends on current font) 45 | UINT m_MaxLines; //!< Max number of lines the CEdit will display at a time 46 | 47 | afx_msg void OnEnChange(); 48 | 49 | DECLARE_MESSAGE_MAP(); 50 | 51 | private: 52 | CGridMultilineEditorText(); 53 | CGridMultilineEditorText(const CGridMultilineEditorText&); 54 | CGridMultilineEditorText& operator=(const CGridMultilineEditorText&); 55 | }; 56 | 57 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 58 | #undef AFX_DATA 59 | #define AFX_DATA 60 | #endif 61 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitText.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/CGridListCtrlEx/CGridColumnTraitText.cpp -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitText.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridColumnTrait.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | #else 17 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 18 | #endif 19 | 20 | //------------------------------------------------------------------------ 21 | //! CGridColumnTraitText provides customization of cell text and background 22 | //------------------------------------------------------------------------ 23 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitText : public CGridColumnTrait 24 | { 25 | public: 26 | CGridColumnTraitText(); 27 | virtual void OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult); 28 | virtual int OnSortRows(LPCTSTR pszLeftValue, LPCTSTR pszRightValue, bool bAscending); 29 | virtual int OnSortRows(const LVITEM& leftItem, const LVITEM& rightItem, bool bAscending) { return CGridColumnTrait::OnSortRows(leftItem, rightItem, bAscending); } 30 | 31 | void SetSortFormatNumber(bool bValue); 32 | 33 | protected: 34 | CFont* m_pOldFont; //!< Backup of the original font while drawing with specified font 35 | COLORREF m_OldTextColor;//!< Backup of the original text color while drawing with specified color 36 | COLORREF m_OldBackColor;//!< Backup of the original background color while drawing with specified color 37 | COLORREF m_TextColor; //!< Text color to use for this column 38 | COLORREF m_BackColor; //!< Background color to use for this column 39 | bool m_SortFormatNumber;//!< Column contains integers 40 | 41 | virtual bool UpdateTextFont(NMLVCUSTOMDRAW* pLVCD, LOGFONT& textFont); 42 | virtual bool UpdateTextColor(NMLVCUSTOMDRAW* pLVCD, COLORREF& textColor); 43 | virtual bool UpdateBackColor(NMLVCUSTOMDRAW* pLVCD, COLORREF& backColor); 44 | 45 | virtual void Accept(CGridColumnTraitVisitor& visitor); 46 | virtual int GetCellFontHeight(CGridListCtrlEx& owner); 47 | virtual CRect GetCellEditRect(CGridListCtrlEx& owner, int nRow, int nCol); 48 | }; 49 | 50 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 51 | #undef AFX_DATA 52 | #define AFX_DATA 53 | #endif 54 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridColumnTraitVisitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 10 | // Using MFC Extension DLL 11 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 12 | #undef AFX_DATA 13 | #define AFX_DATA AFX_EXT_DATA 14 | #else 15 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 16 | #endif 17 | 18 | class CGridColumnTrait; 19 | class CGridColumnTraitImage; 20 | class CGridColumnTraitCombo; 21 | class CGridColumnTraitDateTime; 22 | class CGridColumnTraitEdit; 23 | class CGridColumnTraitText; 24 | 25 | //------------------------------------------------------------------------ 26 | //! CGridColumnTraitVisitor enables the use of the visitor-pattern to 27 | //! add extra behavior to the CGridColumnTrait classes 28 | //------------------------------------------------------------------------ 29 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridColumnTraitVisitor 30 | { 31 | public: 32 | void Visit(CGridColumnTrait&) {} 33 | void Visit(CGridColumnTraitImage&) {} 34 | void Visit(CGridColumnTraitCombo&) {} 35 | void Visit(CGridColumnTraitDateTime&) {} 36 | void Visit(CGridColumnTraitEdit&) {} 37 | void Visit(CGridColumnTraitText&) {} 38 | }; 39 | 40 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 41 | #undef AFX_DATA 42 | #define AFX_DATA 43 | #endif 44 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridListCtrlEx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | // Version: 2.4 8 | // 9 | // Change History: 10 | // 2.4 - CGridListCtrlGroups can perform filtering of items based on cell value 11 | // CGridListCtrlGroups can reorder items within the same group 12 | // Fixed missing call to CListCtrl::OnKillFocus() 13 | // New define CGRIDLISTCTRLEX_AFX_EXT that makes it easier to create MFC Extension DLL 14 | // Fixed several small bugs 15 | // 2.3 - Implemented support for IDropSource::GiveFeedback to allow changing mouse cursor during dragdrop 16 | // Inverted cell focus coloring is now disabled by default. Call SetInvertCellSelection(true) to enable. 17 | // Fixed several small bugs 18 | // 2.2 - CGridColumnTraitCombo now has the option to display dropdown on edit begin (SetShowDropDown) 19 | // All column trait editors now has the option to start editor on first mouse click (SetSingleClickEdit) 20 | // CGridColumnTraitHyperLink will sent LVN_ENDLABELEDIT notification to parent on mouse click (Simulates button click) 21 | // Checkbox state icon used by subitems has been improved on Windows 7/8 by disabling image scaling 22 | // Fixed several small bugs 23 | // 2.1 - Fixed bug introduced in 2.0, where grouping of items no longer worked on WinXP. 24 | // Improved performance when sorting item groups, especially on Vista/Win7+. 25 | // Added new column trait CGridColumnTraitHyperLink, that can display cell text as weblinks. 26 | // Added new column trait CGridColumnTraitMultilineEdit, that can edit cell text that contains newlines 27 | // Fixed several small bugs 28 | // 2.0 - Added copy/paste support for CDateTimeCtrl editor (DTS_APPCANPARSE) 29 | // When having grouped by column, then column header click now sorts instead of grouping by column. 30 | // Changed the row sorting to be case insensitive by default 31 | // Fixed bug where cell editor discarded changes performed using the mouse (copy/paste using context menu) 32 | // Fixed several compiler warnings, and small bugs 33 | // 1.9 - Added new CGridColumnTrait::OnSortRows() to take LVITEM as parameter (2011-05-30) 34 | // Renamed CGridColumnConfig to CViewConfigSection (Now general purpose settings manager) 35 | // Removed CGridColumnManager and moved LoadState/SaveState into CGridListCtrlEx (Breaking change) 36 | // Fixed breaking change in 1.8 where OnEditBegin overrides stopped working 37 | // 1.8 - Added checkbox support for all column editor types (2010-10-01) 38 | // Added checkbox toggle for all selected rows 39 | // Added min and max width for columns 40 | // 1.7 - Added CGridColumnTraitImage, that provides checkbox editing (2009-12-12) 41 | // Renamed OnTraitCustomDraw() to OnCustomDrawCell() 42 | // Renamed OnTraitEditBegin() to OnEditBegin() 43 | // Renamed OnTraitEditComplete() to OnEditComplete() 44 | // 1.6 - Added OLE drag and drop support (2009-08-10) 45 | // Added support for LVS_EX_CHECKBOXES with LVS_OWNERDATA 46 | // Added better support for keyboard search with LVS_OWNERDATA 47 | // 1.5 - Added column manager CGridColumnManager (2009-03-29) 48 | // Added support for groups on VC6 with platform SDK 49 | // Added sample projects for the different versions of Visual Studio 50 | // Improved documentation through Doxygen comments 51 | // 1.4 - Added clipboard support (2008-11-07) 52 | // Renamed the "Callback"-functions to "OnDisplay" 53 | // 1.3 - Added support for compiling on VC6 (2008-10-09) 54 | // 1.2 - Added row traits and CGridRowTraitXP (2008-09-24) 55 | // 1.1 - Added support for groups with CGridListCtrlGroups (2008-09-18) 56 | // Added support for CDateTimeCtrl as cell editor 57 | // 1.0 - Initial Release (2008-09-04) 58 | //------------------------------------------------------------------------ 59 | 60 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 61 | // Using MFC Extension DLL 62 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 63 | #undef AFX_DATA 64 | #define AFX_DATA AFX_EXT_DATA 65 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CListCtrl; 66 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CFont; 67 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CTime; 68 | class CGridColumnTrait; 69 | template class CGRIDLISTCTRLEX_AFX_EXT_CLASS CSimpleArray; 70 | #else 71 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 72 | #endif 73 | 74 | class COleDataSource; 75 | class COleDropSource; 76 | class CViewConfigSection; 77 | class CViewConfigSectionProfiles; 78 | class CGridColumnTrait; 79 | class CGridRowTrait; 80 | template class COleDropTargetWnd; 81 | template class COleDropSourceWnd; 82 | 83 | //------------------------------------------------------------------------ 84 | //! \mainpage Introduction 85 | //! CGridListCtrlEx extends the CListCtrl from MFC. CGridListCtrlGroups 86 | //! extends CGridListCtrlEx even further to support categorization of rows in groups. 87 | //! 88 | //! CGridListCtrlEx makes use of different helper classes that makes it easy 89 | //! to customize and extend it even further. 90 | //! 91 | //! - CGridColumnTrait provides special behavior to the cells in a column 92 | //! - CGridColumnTraitEdit Implements cell editing using CEdit 93 | //! - CGridColumnTraitCombo Implements cell editing using CComboBox 94 | //! - CGridColumnTraitDateTime Implements cell editing using CDateTimeCtrl 95 | //! - CGridColumnTraitHyperLink Implements cell behavior as hyperlinks (can mimic button click) 96 | //! - CGridColumnTraitImage Implements cell editing using cell-image (can mimic checkbox) 97 | //! - CGridColumnTraitMultilineEdit Implements cell editing using multiline CEdit 98 | //! - CGridRowTrait provides an interface to perform custom drawing at row level 99 | //! - CGridRowTraitText implements alternate row coloring 100 | //! - CGridRowTraitXP removes the white background for cell images on WinXP 101 | //! - CViewConfigSection provides column state persistence 102 | //! - CViewConfigSectionProfiles provides the ability switch between different column setups 103 | //------------------------------------------------------------------------ 104 | 105 | //------------------------------------------------------------------------ 106 | //! CGridListCtrlEx extends the CListCtrl with several features. 107 | //! - Cell editing and customization through use of CGridColumnTrait 108 | //! - Sortable 109 | //! - Simple column picker 110 | //! - Cell navigation 111 | //! - Keyboard search navigation 112 | //! - Cell tooltip 113 | //! - Clipboard (copy only) 114 | //! - OLE Drag and drop 115 | //! - Column state persistence (width, order, etc.) 116 | //------------------------------------------------------------------------ 117 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridListCtrlEx : public CListCtrl 118 | { 119 | DECLARE_DYNAMIC(CGridListCtrlEx) 120 | 121 | public: 122 | CGridListCtrlEx(); 123 | virtual ~CGridListCtrlEx(); 124 | 125 | // CListCtrl 126 | LRESULT EnableVisualStyles(bool bValue); 127 | inline bool UsingVisualStyle() const { return m_UsingVisualStyle; } 128 | virtual CFont* GetCellFont(); 129 | virtual void SetCellMargin(double margin); 130 | void SetEmptyMarkupText(const CString& strText); 131 | void SetTooltipMaxWidth(int width) { m_TooltipMaxWidth = width; } 132 | int GetTooltipMaxWidth() const { return m_TooltipMaxWidth; } 133 | static bool CheckOSVersion(WORD requestOS); 134 | 135 | // Row 136 | int GetFocusRow() const; 137 | void SetFocusRow(int nRow); 138 | bool IsRowSelected(int nRow) const; 139 | BOOL SelectRow(int nRow, bool bSelect); 140 | virtual CGridRowTrait* GetRowTrait(int nRow); 141 | virtual void SetDefaultRowTrait(CGridRowTrait* pRowTrait); 142 | 143 | // Column 144 | const CHeaderCtrl* GetHeaderCtrl() const; 145 | CHeaderCtrl* GetHeaderCtrl() { return CListCtrl::GetHeaderCtrl(); } 146 | int GetColumnCount() const; 147 | int GetColumnData(int nCol) const; 148 | int GetColumnOrder(int nCol) const; 149 | CString GetColumnHeading(int nCol) const; 150 | virtual BOOL EnsureColumnVisible(int nCol, bool bPartialOK); 151 | virtual BOOL SetColumnWidthAuto(int nCol = -1, bool bIncludeHeader = false); 152 | virtual void SetSortArrow(int nCol, bool bAscending); 153 | virtual BOOL ShowColumn(int nCol, bool bShow); 154 | virtual bool IsColumnVisible(int nCol); 155 | virtual bool IsColumnResizable(int nCol); 156 | virtual bool IsColumnAlwaysVisible(int nCol); 157 | virtual bool IsColumnAlwaysHidden(int nCol); 158 | virtual int GetFirstVisibleColumn(); 159 | virtual int InsertHiddenLabelColumn(); 160 | virtual int InsertColumnTrait(int nCol, const CString& strColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1, CGridColumnTrait* pTrait = NULL); 161 | virtual CGridColumnTrait* GetColumnTrait(int nCol); 162 | virtual int GetColumnTraitSize() const; 163 | 164 | // Cell / Subitem 165 | UINT CellHitTest(const CPoint& pt, int& nRow, int& nCol) const; 166 | BOOL GetCellRect(int nRow, int nCol, int nCode, CRect& rect); 167 | inline int GetFocusCell() const { return m_FocusCell; } 168 | virtual void SetFocusCell(int nCol, bool bRedraw = false); 169 | virtual CWnd* EditCell(int nRow, int nCol); 170 | virtual CWnd* EditCell(int nRow, int nCol, CPoint pt); 171 | bool IsCellEditorOpen() const; 172 | bool IsCellCallback(int nRow, int nCol) const; 173 | int GetCellImage(int nRow, int nCol) const; 174 | BOOL SetCellImage(int nRow, int nCol, int nImageId); 175 | virtual CGridColumnTrait* GetCellColumnTrait(int nRow, int nCol); 176 | 177 | // Column Editor 178 | virtual void SetupColumnConfig(CViewConfigSectionProfiles* pColumnConfig, bool bConfigOwner = true); 179 | virtual void LoadState(CViewConfigSection& config); 180 | virtual void SaveState(CViewConfigSection& config); 181 | virtual void LoadColumnState(int nConfigCol, int nOwnerCol, CViewConfigSection& config); 182 | virtual void SaveColumnState(int nConfigCol, int nOwnerCol, CViewConfigSection& config); 183 | virtual bool HasColumnEditor(int nCol, CString& strTitle); 184 | virtual void OpenColumnEditor(int nCol); 185 | virtual bool HasColumnPicker(CString& strTitle); 186 | virtual void OpenColumnPicker(); 187 | virtual bool HasColumnDefaultState(CString& strTitle); 188 | virtual void ResetColumnDefaultState(); 189 | virtual CString HasColumnProfiles(CSimpleArray& profiles, CString& strTitle); 190 | virtual void SwichColumnProfile(const CString& strProfile); 191 | virtual void OnSaveStateColumnPick(); 192 | virtual void OnSaveStateColumnResize(); 193 | virtual void OnSaveStateKillFocus(); 194 | 195 | // DataModel callbacks 196 | virtual void OnDisplayCellItem(LVITEM& lvi); 197 | virtual bool OnDisplayCellText(int nRow, int nCol, CString& strResult); 198 | virtual bool OnDisplayCellImage(int nRow, int nCol, int& nImageId); 199 | virtual bool OnDisplayCellTooltip(const CPoint& point) const; 200 | virtual bool OnDisplayCellTooltip(int nRow, int nCol, CString& strResult); 201 | virtual bool OnDisplayCellColor(NMLVCUSTOMDRAW* pLVCD); 202 | virtual bool OnDisplayCellColor(int nRow, int nCol, COLORREF& textColor, COLORREF& backColor); 203 | virtual bool OnDisplayCellFont(NMLVCUSTOMDRAW* pLVCD, LOGFONT& font); 204 | virtual bool OnDisplayCellFont(int nRow, int nCol, LOGFONT& font); 205 | virtual bool OnDisplayRowColor(int nRow, COLORREF& textColor, COLORREF& backColor); 206 | virtual bool OnDisplayRowFont(int nRow, LOGFONT& font); 207 | virtual void OnDisplayDragOverRow(int nRow); 208 | virtual bool OnDisplayToClipboard(CString& strResult, bool includeHeader = true); 209 | virtual bool OnDisplayToClipboard(int nRow, CString& strResult); 210 | virtual bool OnDisplayToClipboard(int nRow, int nCol, CString& strResult); 211 | virtual bool OnDisplayToDragDrop(CString& strResult); 212 | virtual bool OnOwnerDataDisplayCheckbox(int nRow); 213 | virtual void OnOwnerDataToggleCheckBox(int nRow, bool bChecked); 214 | virtual int OnKeyboardSearch(int nCol, int nStartRow, const CString& strSearch); 215 | 216 | protected: 217 | // Maintaining column traits (and visible state) 218 | CSimpleArray m_ColumnTraits; //!< Column traits registered (One for each column) 219 | virtual void InsertColumnTrait(int nCol, CGridColumnTrait* pTrait); 220 | virtual void DeleteColumnTrait(int nCol); 221 | CViewConfigSectionProfiles* m_pColumnConfig; //!< Column state persistence 222 | bool m_bConfigOwner; //!< Column state persistence object is freed by destructor 223 | int InternalColumnPicker(CMenu& menu, UINT offset); 224 | int InternalColumnProfileSwitcher(CMenu& menu, UINT offset, CSimpleArray& profiles); 225 | 226 | // Maintaining row traits 227 | CGridRowTrait* m_pDefaultRowTrait; //!< Default row trait used for special row drawing 228 | 229 | // Maintaining cell/subitem focus 230 | int m_FocusCell; //!< Column currently having focus (-1 means entire row) 231 | virtual void MoveFocusCell(bool bMoveRight); 232 | 233 | // Maintaining Keyboard search 234 | CString m_LastSearchString; //!< Last search criteria for keyboard search 235 | CTime m_LastSearchTime; //!< Time of last search attempt for keyboard search 236 | int m_LastSearchCell; //!< Last column used in keyboard search 237 | int m_LastSearchRow; //!< Last row matched in keyboard search 238 | int m_RepeatSearchCount;//!< How many times the same search have been repeated (same key pressed) 239 | 240 | // Maintaining row sorting 241 | int m_SortCol; //!< Rows are sorted according to this column 242 | bool m_Ascending; //!< Rows are sorted ascending / descending 243 | virtual bool SortColumn(int nCol, bool bAscending); 244 | 245 | // Maintaining cell editing 246 | CWnd* m_pEditor; //!< Cell value editor currently in use 247 | 248 | bool m_UsingVisualStyle; //!< Vista Style has been enabled (alpha blend) 249 | 250 | int m_TooltipMaxWidth; //!< Whether tooltips should be split in multiple lines 251 | 252 | // Maintaining margin 253 | CFont m_GridFont; //!< Original font of the the list control 254 | CFont m_CellFont; //!< Current font to draw rows 255 | double m_Margin; //!< Current margin between original font and cell font 256 | 257 | CString m_EmptyMarkupText; //!< Text to display when list control is empty 258 | bool m_InvalidateMarkupText;//!< Ensure that the empty markup text is cleared properly 259 | 260 | // Maintaining drag drop 261 | COleDropTargetWnd* m_pOleDropTarget; //!< Maintains OLE drag drop target 262 | friend class COleDropTargetWnd; 263 | friend class COleDropSourceWnd; 264 | virtual BOOL RegisterDropTarget(); 265 | virtual DROPEFFECT DoDragDrop(COleDataSource& oleDataSource, 266 | COleDropSource* pDropSource = NULL, 267 | DWORD dropEffects = DROPEFFECT_COPY | DROPEFFECT_MOVE | DROPEFFECT_LINK, 268 | LPCRECT lpRectStartDrag = NULL); 269 | virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 270 | virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 271 | virtual SCODE OnDragGiveFeedback(DROPEFFECT dropEffect); 272 | virtual void OnDragLeave(); 273 | virtual BOOL OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); 274 | virtual BOOL OnDropSelf(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); 275 | virtual BOOL OnDropExternal(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); 276 | virtual bool MoveSelectedRows(int nDropRow); 277 | 278 | // CustomDraw handlers 279 | virtual void OnCustomDrawRow(int nRow, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult); 280 | virtual void OnCustomDrawCell(int nRow, int nCol, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult); 281 | 282 | // Cell editing handlers 283 | virtual int OnClickEditStart(int nRow, int nCol, CPoint pt, bool bDblClick); 284 | virtual CWnd* OnEditBegin(int nRow, int nCol); 285 | virtual CWnd* OnEditBegin(int nRow, int nCol, CPoint pt); 286 | virtual bool OnEditComplete(int nRow, int nCol, CWnd* pEditor, LV_DISPINFO* pLVDI); 287 | 288 | // Context Menu Handlers 289 | virtual void OnContextMenuGrid(CWnd* pWnd, CPoint point); 290 | virtual void OnContextMenuHeader(CWnd* pWnd, CPoint point, int nCol); 291 | virtual void OnContextMenuKeyboard(CWnd* pWnd, CPoint point); 292 | virtual void OnContextMenuCell(CWnd* pWnd, CPoint point, int nRow, int nCol); 293 | 294 | virtual void OnCreateStyle(); 295 | 296 | virtual void OnCopyToClipboard(); 297 | 298 | //{{AFX_VIRTUAL(CGridListCtrlEx) 299 | virtual void PreSubclassWindow(); 300 | #if defined(_WIN64) && !defined(_WDK_BUILD) 301 | virtual INT_PTR OnToolHitTest(CPoint point, TOOLINFO * pTI) const; 302 | #else 303 | virtual int OnToolHitTest(CPoint point, TOOLINFO * pTI) const; 304 | #endif 305 | //}}AFX_VIRTUAL 306 | 307 | //{{AFX_MSG(CGridListCtrlEx) 308 | virtual afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 309 | virtual afx_msg LRESULT OnDeleteColumn(WPARAM wParam, LPARAM lParam); 310 | virtual afx_msg LRESULT OnInsertColumn(WPARAM wParam, LPARAM lParam); 311 | virtual afx_msg BOOL OnItemClick(NMHDR* pNMHDR, LRESULT* pResult); 312 | virtual afx_msg BOOL OnItemDblClick(NMHDR* pNMHDR, LRESULT* pResult); 313 | virtual afx_msg BOOL OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult); 314 | virtual afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); 315 | virtual afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 316 | virtual afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 317 | virtual afx_msg void OnRButtonDown(UINT nFlags, CPoint point); 318 | virtual afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); 319 | virtual afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); 320 | virtual afx_msg LRESULT OnSetColumnWidth(WPARAM wParam, LPARAM lParam); 321 | virtual afx_msg BOOL OnHeaderDividerDblClick(UINT, NMHDR* pNMHDR, LRESULT* pResult); 322 | virtual afx_msg BOOL OnHeaderBeginResize(UINT, NMHDR* pNmhdr, LRESULT* pResult); 323 | virtual afx_msg BOOL OnHeaderBeginDrag(UINT, NMHDR* pNMHDR, LRESULT* pResult); 324 | virtual afx_msg BOOL OnHeaderEndResize(UINT, NMHDR* pNMHDR, LRESULT* pResult); 325 | virtual afx_msg BOOL OnHeaderItemChanging(UINT, NMHDR* pNMHDR, LRESULT* pResult); 326 | virtual afx_msg BOOL OnHeaderEndDrag(UINT, NMHDR* pNmhdr, LRESULT* pResult); 327 | virtual afx_msg BOOL OnHeaderClick(NMHDR* pNMHDR, LRESULT* pResult); 328 | virtual afx_msg BOOL OnToolNeedText(UINT, NMHDR* pNMHDR, LRESULT* pResult); 329 | virtual afx_msg BOOL OnBeginLabelEdit(NMHDR* pNMHDR, LRESULT* pResult); 330 | virtual afx_msg BOOL OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult); 331 | virtual afx_msg BOOL OnOwnerDataFindItem(NMHDR* pNMHDR, LRESULT* pResult); 332 | virtual afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); 333 | virtual afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); 334 | virtual afx_msg void OnContextMenu(CWnd*, CPoint point); 335 | virtual afx_msg void OnDestroy(); 336 | virtual afx_msg void OnPaint(); 337 | virtual afx_msg void OnSetFocus(CWnd* pOldWnd); 338 | virtual afx_msg void OnKillFocus(CWnd* pNewWnd); 339 | virtual afx_msg LRESULT OnCopy(WPARAM wParam, LPARAM lParam); 340 | virtual afx_msg LRESULT OnSetFont(WPARAM wParam, LPARAM lParam); 341 | virtual afx_msg BOOL OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult); 342 | virtual afx_msg BOOL OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult); 343 | //}}AFX_MSG 344 | 345 | DECLARE_MESSAGE_MAP(); 346 | 347 | private: 348 | CGridListCtrlEx(const CGridListCtrlEx&); 349 | CGridListCtrlEx& operator=(const CGridListCtrlEx&); 350 | }; 351 | 352 | //{{AFX_INSERT_LOCATION}} 353 | 354 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 355 | #undef AFX_DATA 356 | #define AFX_DATA 357 | #endif 358 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS 359 | -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridListCtrlEx.ncb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/CGridListCtrlEx/CGridListCtrlEx.ncb -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridListCtrlEx.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CGridListCtrlEx", "CGridListCtrlEx.vcproj", "{A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Debug|Win32.Build.0 = Debug|Win32 14 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Release|Win32.ActiveCfg = Release|Win32 15 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridListCtrlEx.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/CGridListCtrlEx/CGridListCtrlEx.suo -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridListCtrlEx.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 30 | 33 | 36 | 39 | 42 | 45 | 56 | 59 | 62 | 65 | 68 | 71 | 74 | 77 | 80 | 83 | 84 | 93 | 96 | 99 | 102 | 105 | 108 | 121 | 124 | 127 | 130 | 134 | 137 | 140 | 143 | 146 | 149 | 150 | 151 | 152 | 153 | 154 | 157 | 158 | 161 | 162 | 165 | 166 | 169 | 170 | 173 | 174 | 177 | 178 | 181 | 182 | 185 | 186 | 189 | 190 | 193 | 194 | 197 | 198 | 201 | 202 | 205 | 206 | 209 | 210 | 213 | 214 | 217 | 218 | 221 | 222 | 225 | 226 | 229 | 230 | 233 | 234 | 237 | 238 | 241 | 242 | 245 | 246 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridListCtrlGroups.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridListCtrlEx.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | #else 17 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 18 | #endif 19 | 20 | //------------------------------------------------------------------------ 21 | //! CGridListCtrlGroups extends the CGridListCtrlEx with grouping. 22 | //! This can be used to put rows into category groups. 23 | //! 24 | //! Placed in its own file as all features requires _WIN32_WINNT >= 0x0501 25 | //------------------------------------------------------------------------ 26 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridListCtrlGroups : public CGridListCtrlEx 27 | { 28 | DECLARE_DYNAMIC(CGridListCtrlGroups) 29 | 30 | public: 31 | CGridListCtrlGroups(); 32 | 33 | // WIN32 defines for group-support is only available from 2003 PSDK 34 | #if _WIN32_WINNT >= 0x0501 35 | 36 | // VS2008 Marks group-mode functionality as deprecated if not Unicode build (define CGRIDLISTCTRLEX_GROUPMODE in stdafx.h to avoid this check) 37 | #if _MSC_VER < 1500 || defined UNICODE || defined CGRIDLISTCTRLEX_GROUPMODE 38 | virtual LRESULT InsertGroupHeader(int nIndex, int nGroupId, const CString& strHeader, DWORD dwState = 0, DWORD dwAlign = 0); 39 | 40 | virtual CString GetGroupHeader(int nGroupId); 41 | virtual int GetRowGroupId(int nRow); 42 | virtual BOOL SetRowGroupId(int nRow, int nGroupId); 43 | virtual int GroupHitTest(const CPoint& point); 44 | virtual int FixRowGroupId(int nRow); 45 | 46 | virtual BOOL GetGroupIds(CSimpleArray& groupIds); 47 | 48 | virtual BOOL GroupByColumn(int nCol); 49 | virtual BOOL DeleteEntireGroup(int nGroupId); 50 | virtual BOOL FilterByCellText(int nCol, const CString& strNeedle, const CString& strGroupName); 51 | virtual BOOL IsGroupStateEnabled(); 52 | 53 | virtual void CheckEntireGroup(int nGroupId, bool bChecked); 54 | 55 | virtual void SetSortSecondaryGroupView(int nEnable); 56 | virtual bool SortColumn(int nCol, bool bAscending); 57 | 58 | virtual BOOL HasGroupState(int nGroupId, DWORD dwState); 59 | virtual BOOL SetGroupState(int nGroupId, DWORD dwState); 60 | 61 | virtual BOOL CollapseAllGroups(); 62 | virtual BOOL ExpandAllGroups(); 63 | 64 | virtual BOOL SetGroupFooter(int nGroupId, const CString& strFooter, DWORD dwAlign = 0); 65 | virtual BOOL SetGroupTask(int nGroupId, const CString& strTask); 66 | virtual BOOL SetGroupSubtitle(int nGroupId, const CString& strSubtitle); 67 | virtual BOOL SetGroupTitleImage(int nGroupId, int nImage, const CString& strTopDesc, const CString& strBottomDesc); 68 | 69 | // DataModel callbacks 70 | virtual bool OnDisplayCellGroup(int nRow, int nCol, int& nGroupId); 71 | 72 | protected: 73 | // Context Menu Handlers 74 | virtual void OnContextMenuGrid(CWnd* pWnd, CPoint point); 75 | virtual void OnContextMenuHeader(CWnd* pWnd, CPoint point, int nCol); 76 | virtual void OnContextMenuGroup(CWnd* pWnd, CPoint point, int nGroupId); 77 | virtual void OnContextMenuCell(CWnd* pWnd, CPoint point, int nRow, int nCol); 78 | 79 | // Drag Drop Interface 80 | virtual BOOL OnDropSelf(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); 81 | virtual bool MoveSelectedRows(int nGroupId); 82 | 83 | virtual bool OnFilterSingleCellText(int nRow, int nFilterCol, const CString& strNeedle); 84 | 85 | //{{AFX_MSG(CGridListCtrlGroups) 86 | virtual afx_msg void OnContextMenu(CWnd*, CPoint point); 87 | virtual afx_msg BOOL OnGroupTaskClick(NMHDR* pNMHDR, LRESULT* pResult); 88 | virtual afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); 89 | virtual afx_msg BOOL OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult); 90 | virtual afx_msg BOOL OnGetEmptyMarkup(NMHDR* pNMHDR, LRESULT* pResult); 91 | virtual afx_msg void OnDestroy(); 92 | virtual afx_msg void OnPaint(); 93 | virtual afx_msg LRESULT OnRemoveAllGroups(WPARAM wParam, LPARAM lParam); 94 | virtual afx_msg BOOL OnHeaderEndDrag(UINT, NMHDR* pNmhdr, LRESULT* pResult); 95 | //}}AFX_MSG 96 | 97 | DECLARE_MESSAGE_MAP(); 98 | 99 | public: 100 | // MFC headers with group-support is only availabe from VS.NET 101 | #if _MSC_VER < 1300 || defined(_WDK_BUILD) 102 | LRESULT InsertGroup(int index, PLVGROUP pgrp); 103 | int SetGroupInfo(int iGroupId, PLVGROUP pgrp); 104 | int GetGroupInfo(int iGroupId, PLVGROUP pgrp) const; 105 | LRESULT RemoveGroup(int iGroupId); 106 | LRESULT MoveGroup(int iGroupId, int toIndex); 107 | LRESULT MoveItemToGroup(int idItemFrom, int idGroupTo); 108 | void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics); 109 | void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const; 110 | LRESULT EnableGroupView(BOOL fEnable); 111 | BOOL SortGroups(PFNLVGROUPCOMPARE _pfnGroupCompare, LPVOID _plv); 112 | LRESULT InsertGroupSorted(PLVINSERTGROUPSORTED pStructInsert); 113 | void RemoveAllGroups(); 114 | BOOL HasGroup(int iGroupId) const; 115 | BOOL IsGroupViewEnabled() const; 116 | #endif // _MSC_VER < 1300 117 | #endif // _MSC_VER < 1500 || defined UNICODE || defined CGRIDLISTCTRLEX_GROUPMODE 118 | #endif // _WIN32_WINNT >= 0x0501 119 | 120 | protected: 121 | int m_GroupCol; //!< Rows are grouped according to this column 122 | int m_GroupSort; //!< Groups are sorted (-1 = Unsorted, 1 = Ascending, 0 = Descending) 123 | int m_SortSecondaryGroupView; //!< When grouped by primary column, then allow sort of secondary column (0 = Always group, 1 = Allow sort, 2 = Fix sort for xp) 124 | CString m_GroupFilterText; //!< Filter rows by putting them in visible filter-group 125 | 126 | private: 127 | CGridListCtrlGroups(const CGridListCtrlGroups&); 128 | CGridListCtrlGroups& operator=(const CGridListCtrlGroups&); 129 | }; 130 | 131 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 132 | #undef AFX_DATA 133 | #define AFX_DATA 134 | #endif 135 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS 136 | -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridRowTrait.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 10 | // Using MFC Extension DLL 11 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 12 | #undef AFX_DATA 13 | #define AFX_DATA AFX_EXT_DATA 14 | #else 15 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 16 | #endif 17 | 18 | class CGridRowTraitVisitor; 19 | class CGridListCtrlEx; 20 | 21 | #pragma warning(push) 22 | #pragma warning(disable:4100) // unreferenced formal parameter 23 | 24 | //------------------------------------------------------------------------ 25 | //! CGridRowTrait specifies an interface for handling custom drawing at 26 | //! row-level 27 | //------------------------------------------------------------------------ 28 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridRowTrait 29 | { 30 | public: 31 | virtual ~CGridRowTrait() {} 32 | 33 | //! Override OnCustomDraw() to provide your own special row-drawing 34 | virtual void OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult) {} 35 | 36 | //! Override Accept() and update CGridColumnTraitVisitor for new column-trait classes 37 | //! - Will enable the use of the visitor-pattern ex. for serialization of column-traits 38 | virtual void Accept(CGridRowTraitVisitor& visitor) {} 39 | }; 40 | 41 | #pragma warning(pop) 42 | 43 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 44 | #undef AFX_DATA 45 | #define AFX_DATA 46 | #endif 47 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridRowTraitText.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // Author: Rolf Kristensen 3 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 4 | // License: Free to use for all (New BSD License) 5 | //------------------------------------------------------------------------ 6 | 7 | #include "stdafx.h" 8 | #pragma warning(disable:4100) // unreferenced formal parameter 9 | 10 | #include "CGridRowTraitText.h" 11 | 12 | #include "CGridRowTraitVisitor.h" 13 | #include "CGridListCtrlEx.h" 14 | 15 | //------------------------------------------------------------------------ 16 | //! CGridRowTraitText - Constructor 17 | //------------------------------------------------------------------------ 18 | CGridRowTraitText::CGridRowTraitText() 19 | : m_pOldFont(NULL) 20 | , m_FontAllocated(false) 21 | , m_TextColor((COLORREF)-1) 22 | , m_BackColor((COLORREF)-1) 23 | , m_AltTextColor((COLORREF)-1) 24 | , m_AltBackColor((COLORREF)-1) 25 | , m_InvertCellSelection(false) 26 | {} 27 | 28 | //------------------------------------------------------------------------ 29 | //! Sets the same row coloring for all rows 30 | //! 31 | //! @param backColor The background color to use for all rows 32 | //! @param textColor The text color to use for all rows 33 | //------------------------------------------------------------------------ 34 | void CGridRowTraitText::SetRowColor(COLORREF textColor, COLORREF backColor) 35 | { 36 | m_TextColor = textColor; 37 | m_BackColor = backColor; 38 | } 39 | 40 | //------------------------------------------------------------------------ 41 | //! Activates alternate row coloring 42 | //! 43 | //! @param backColor The background color to use for every second row 44 | //! @param textColor The text color to use for every second row 45 | //------------------------------------------------------------------------ 46 | void CGridRowTraitText::SetAltRowColor(COLORREF textColor, COLORREF backColor) 47 | { 48 | m_AltTextColor = textColor; 49 | m_AltBackColor = backColor; 50 | } 51 | 52 | //------------------------------------------------------------------------ 53 | //! Accept Visitor Pattern 54 | //------------------------------------------------------------------------ 55 | void CGridRowTraitText::Accept(CGridRowTraitVisitor& visitor) 56 | { 57 | visitor.Visit(*this); 58 | } 59 | 60 | //------------------------------------------------------------------------ 61 | //! Changes the text color if one is specified 62 | //! 63 | //! @param nRow The index of the row 64 | //! @param textColor Current text color 65 | //! @return New text color was specified (true / false) 66 | //------------------------------------------------------------------------ 67 | bool CGridRowTraitText::UpdateTextColor(int nRow, COLORREF& textColor) 68 | { 69 | if (m_AltTextColor != COLORREF(-1) && nRow % 2) 70 | { 71 | textColor = m_AltTextColor; 72 | return true; 73 | } 74 | 75 | if (m_TextColor != COLORREF(-1)) 76 | { 77 | textColor = m_TextColor; 78 | return true; 79 | } 80 | 81 | return false; 82 | } 83 | 84 | //------------------------------------------------------------------------ 85 | //! Changes the background color if one is specified 86 | //! 87 | //! @param nRow The index of the row 88 | //! @param backColor Current background color 89 | //! @return New background color was specified (true / false) 90 | //------------------------------------------------------------------------ 91 | bool CGridRowTraitText::UpdateBackColor(int nRow, COLORREF& backColor) 92 | { 93 | if (m_AltBackColor != COLORREF(-1) && nRow % 2) 94 | { 95 | backColor = m_AltBackColor; 96 | return true; 97 | } 98 | 99 | if (m_BackColor != COLORREF(-1)) 100 | { 101 | backColor = m_BackColor; 102 | return true; 103 | } 104 | 105 | return false; 106 | } 107 | 108 | //------------------------------------------------------------------------ 109 | //! Overrides the custom draw handler, to allow custom coloring of rows. 110 | //! - Focus rectangle display 111 | //! - Use font size to increase row-height, but keep cell font-size 112 | //! - Alternate row coloring 113 | //! 114 | //! @param owner The list control drawing 115 | //! @param pLVCD Pointer to NMLVCUSTOMDRAW structure 116 | //! @param pResult Modification to the drawing stage (CDRF_NEWFONT, etc.) 117 | //------------------------------------------------------------------------ 118 | void CGridRowTraitText::OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult) 119 | { 120 | int nRow = static_cast(pLVCD->nmcd.dwItemSpec); 121 | 122 | switch (pLVCD->nmcd.dwDrawStage) 123 | { 124 | case CDDS_ITEMPREPAINT | CDDS_SUBITEM: 125 | { 126 | // Remove the selection color for the focus cell, to make it easier to see focus 127 | if (m_InvertCellSelection) 128 | { 129 | int nCol = pLVCD->iSubItem; 130 | if (pLVCD->nmcd.uItemState & CDIS_SELECTED) 131 | { 132 | if (owner.GetFocusCell() == nCol && owner.GetFocusRow() == nRow) 133 | { 134 | pLVCD->nmcd.uItemState &= ~CDIS_SELECTED; 135 | } 136 | } 137 | } 138 | 139 | // Bug in Vista causes the cell color from previous cell to be used in the next 140 | // even if having reverted the cell coloring in subitem-post-paint 141 | if (pLVCD->clrText <= RGB(255, 255, 255) || pLVCD->clrTextBk <= RGB(255, 255, 255)) 142 | { 143 | pLVCD->clrText = CLR_DEFAULT; 144 | pLVCD->clrTextBk = CLR_DEFAULT; 145 | 146 | if (UpdateTextColor(nRow, pLVCD->clrText)) 147 | *pResult |= CDRF_NEWFONT; 148 | 149 | if (UpdateBackColor(nRow, pLVCD->clrTextBk)) 150 | *pResult |= CDRF_NEWFONT; 151 | 152 | if (owner.OnDisplayRowColor(nRow, pLVCD->clrText, pLVCD->clrTextBk)) 153 | *pResult |= CDRF_NEWFONT; 154 | } 155 | } break; 156 | 157 | // Before painting a row 158 | case CDDS_ITEMPREPAINT: 159 | { 160 | if (UpdateTextColor(nRow, pLVCD->clrText)) 161 | *pResult |= CDRF_NEWFONT; 162 | 163 | if (UpdateBackColor(nRow, pLVCD->clrTextBk)) 164 | *pResult |= CDRF_NEWFONT; 165 | 166 | if (owner.OnDisplayRowColor(nRow, pLVCD->clrText, pLVCD->clrTextBk)) 167 | *pResult |= CDRF_NEWFONT; 168 | 169 | LOGFONT newFont = { 0 }; 170 | if (owner.OnDisplayRowFont(nRow, newFont)) 171 | { 172 | // New font provided 173 | CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 174 | CFont* pNewFont = new CFont; 175 | VERIFY(pNewFont->CreateFontIndirect(&newFont)); 176 | m_pOldFont = pDC->SelectObject(pNewFont); 177 | m_FontAllocated = true; 178 | *pResult |= CDRF_NOTIFYPOSTPAINT; // We need to restore the original font 179 | *pResult |= CDRF_NEWFONT; 180 | } 181 | else 182 | { 183 | if (owner.GetFont() != owner.GetCellFont()) 184 | { 185 | // Using special cell font because of SetMargin() 186 | CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 187 | m_pOldFont = pDC->SelectObject(owner.GetCellFont()); 188 | *pResult |= CDRF_NOTIFYPOSTPAINT; // We need to restore the original font 189 | *pResult |= CDRF_NEWFONT; 190 | } 191 | } 192 | 193 | if (pLVCD->nmcd.uItemState & CDIS_FOCUS) 194 | { 195 | if (owner.GetFocus() != &owner) 196 | break; 197 | 198 | // If drawing focus row, then remove focus state and request to draw it later 199 | // - Row paint request can come twice, with and without focus flag 200 | // - Only respond to the one with focus flag, else DrawFocusRect XOR will cause solid or blank focus-rectangle 201 | if (owner.GetFocusRow() == nRow) 202 | { 203 | if (owner.GetFocusCell() >= 0) 204 | { 205 | // We want to draw a cell-focus-rectangle instead of row-focus-rectangle 206 | pLVCD->nmcd.uItemState &= ~CDIS_FOCUS; 207 | *pResult |= CDRF_NOTIFYPOSTPAINT; 208 | } 209 | else if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES) 210 | { 211 | // Avoid bug where bottom of focus rectangle is missing when using grid-lines 212 | // - Draw the focus-rectangle for the entire row (explicit) 213 | pLVCD->nmcd.uItemState &= ~CDIS_FOCUS; 214 | *pResult |= CDRF_NOTIFYPOSTPAINT; 215 | } 216 | } 217 | } 218 | } break; 219 | 220 | // After painting a row 221 | case CDDS_ITEMPOSTPAINT: 222 | { 223 | if (m_pOldFont != NULL) 224 | { 225 | // Restore the original font 226 | CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 227 | CFont* pNewFont = pDC->SelectObject(m_pOldFont); 228 | if (m_FontAllocated) 229 | { 230 | m_FontAllocated = false; 231 | delete pNewFont; 232 | } 233 | m_pOldFont = NULL; 234 | } 235 | 236 | if (CRect(pLVCD->nmcd.rc) == CRect(0, 0, 0, 0)) 237 | break; 238 | 239 | if (owner.GetFocusRow() != nRow) 240 | break; 241 | 242 | if (owner.GetFocus() != &owner) 243 | break; 244 | 245 | // Perform the drawing of the focus rectangle 246 | if (owner.GetFocusCell() >= 0) 247 | { 248 | // Draw the focus-rectangle for a single-cell 249 | CRect rcHighlight; 250 | CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 251 | 252 | VERIFY(owner.GetCellRect(nRow, owner.GetFocusCell(), LVIR_BOUNDS, rcHighlight)); 253 | 254 | int cxborder = ::GetSystemMetrics(SM_CXBORDER); 255 | 256 | // When the label column is placed first it has a left-margin 257 | if (owner.GetFocusCell() == 0 && owner.GetFocusCell() == owner.GetFirstVisibleColumn()) 258 | { 259 | rcHighlight.left += cxborder * 2; 260 | } 261 | else 262 | // Prevent focus rectangle to overlap with cell-image (Only room for this when not first column) 263 | if (owner.GetFirstVisibleColumn() != owner.GetFocusCell()) 264 | { 265 | rcHighlight.left -= cxborder; 266 | } 267 | 268 | // Adjust rectangle according to grid-lines 269 | if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES) 270 | { 271 | rcHighlight.bottom -= cxborder; 272 | } 273 | 274 | pDC->DrawFocusRect(rcHighlight); 275 | } 276 | else if (owner.GetExtendedStyle() & LVS_EX_GRIDLINES) 277 | { 278 | // Avoid bug where bottom of focus rectangle is missing when using grid-lines 279 | // - Draw the focus-rectangle for the entire row (explicit) 280 | CRect rcHighlight; 281 | CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 282 | // Using LVIR_BOUNDS to get the entire row-rectangle 283 | VERIFY(owner.GetItemRect(nRow, rcHighlight, LVIR_BOUNDS)); 284 | 285 | // Adjust rectangle according to grid-lines 286 | int cxborder = ::GetSystemMetrics(SM_CXBORDER); 287 | rcHighlight.bottom -= cxborder; 288 | pDC->DrawFocusRect(rcHighlight); 289 | } 290 | } break; 291 | } 292 | } -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridRowTraitText.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridRowTrait.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | #else 17 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 18 | #endif 19 | 20 | //------------------------------------------------------------------------ 21 | //! CGridRowTraitText provides customization text and background at 22 | //! row-level 23 | //------------------------------------------------------------------------ 24 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridRowTraitText : public CGridRowTrait 25 | { 26 | public: 27 | CGridRowTraitText(); 28 | virtual void OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult); 29 | 30 | void SetRowColor(COLORREF textColor, COLORREF backColor); 31 | void SetAltRowColor(COLORREF textColor, COLORREF backColor); 32 | 33 | void SetInvertCellSelection(bool bValue) { m_InvertCellSelection = bValue; } 34 | bool GetInvertCellSelection() const { return m_InvertCellSelection; } 35 | 36 | protected: 37 | CFont* m_pOldFont; //!< Backup of the original font while drawing with specified font 38 | bool m_FontAllocated;//!< Specified font was allocated by the row trait 39 | COLORREF m_TextColor; //!< Text color to use for this row 40 | COLORREF m_BackColor; //!< Background color to use for this row 41 | 42 | COLORREF m_AltTextColor;//!< Alternate text color to use for every second row 43 | COLORREF m_AltBackColor;//!< Alternate background color to use for every second row 44 | 45 | bool m_InvertCellSelection;//!< When cell has focus in column, then the selection color is removed 46 | 47 | virtual bool UpdateTextColor(int nRow, COLORREF& textColor); 48 | virtual bool UpdateBackColor(int nRow, COLORREF& backColor); 49 | virtual void Accept(CGridRowTraitVisitor& visitor); 50 | }; 51 | 52 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 53 | #undef AFX_DATA 54 | #define AFX_DATA 55 | #endif 56 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridRowTraitVisitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 10 | // Using MFC Extension DLL 11 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 12 | #undef AFX_DATA 13 | #define AFX_DATA AFX_EXT_DATA 14 | #else 15 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 16 | #endif 17 | 18 | class CGridRowTrait; 19 | class CGridRowTraitText; 20 | class CGridRowTraitXP; 21 | 22 | //------------------------------------------------------------------------ 23 | //! CGridRowTraitVisitor enables the use of the visitor-pattern to 24 | //! add extra behavior to the CGridRowTrait classes 25 | //------------------------------------------------------------------------ 26 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridRowTraitVisitor 27 | { 28 | public: 29 | void Visit(CGridRowTrait&) {} 30 | void Visit(CGridRowTraitText&) {} 31 | void Visit(CGridRowTraitXP&) {} 32 | }; 33 | 34 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 35 | #undef AFX_DATA 36 | #define AFX_DATA 37 | #endif 38 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridRowTraitXP.cpp: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------ 2 | // Author: Rolf Kristensen 3 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 4 | // License: Free to use for all (New BSD License) 5 | //------------------------------------------------------------------------ 6 | 7 | #include "stdafx.h" 8 | #pragma warning(disable:4100) // unreferenced formal parameter 9 | 10 | #include "CGridRowTraitXP.h" 11 | 12 | #include "CGridRowTraitVisitor.h" 13 | #include "CGridListCtrlEx.h" 14 | #include "CGridColumnTraitText.h" 15 | 16 | //------------------------------------------------------------------------ 17 | //! Accept Visitor Pattern 18 | //------------------------------------------------------------------------ 19 | void CGridRowTraitXP::Accept(CGridRowTraitVisitor& visitor) 20 | { 21 | visitor.Visit(*this); 22 | } 23 | 24 | //------------------------------------------------------------------------ 25 | //! Overrides the custom draw handler, to allow custom coloring of rows. 26 | //! - Fix white background for icon images 27 | //! - Fix white background between icon and cell text 28 | //! 29 | //! @param owner The list control drawing 30 | //! @param pLVCD Pointer to NMLVCUSTOMDRAW structure 31 | //! @param pResult Modification to the drawing stage (CDRF_NEWFONT, etc.) 32 | //------------------------------------------------------------------------ 33 | void CGridRowTraitXP::OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult) 34 | { 35 | int nRow = static_cast(pLVCD->nmcd.dwItemSpec); 36 | 37 | // Repair the standard drawing 38 | switch (pLVCD->nmcd.dwDrawStage) 39 | { 40 | case CDDS_ITEMPREPAINT | CDDS_SUBITEM: 41 | { 42 | // We want to fix cell images 43 | *pResult |= CDRF_NOTIFYPOSTPAINT; 44 | } break; 45 | 46 | case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM: 47 | { 48 | // Fix CListCtrl selection drawing bug with white background for icon image 49 | // Fix CListCtrl selection drawing bug with white margin between icon and text 50 | int nCol = pLVCD->iSubItem; 51 | 52 | if (CRect(pLVCD->nmcd.rc) == CRect(0, 0, 0, 0)) 53 | break; 54 | 55 | int nImage = owner.GetCellImage(nRow, nCol); 56 | if (nImage == I_IMAGECALLBACK) 57 | break; 58 | 59 | CImageList* pImageList = owner.GetImageList(LVSIL_SMALL); 60 | if (pImageList == NULL) 61 | break; 62 | 63 | COLORREF backColor = COLORREF(-1); 64 | if (owner.GetExtendedStyle() & LVS_EX_TRACKSELECT && owner.GetHotItem() == nRow) 65 | { 66 | #if(WINVER >= 0x0500) 67 | backColor = ::GetSysColor(COLOR_HOTLIGHT); 68 | #else 69 | if (owner.IsRowSelected(nRow)) 70 | backColor = ::GetSysColor(COLOR_HIGHLIGHT); 71 | else 72 | break; 73 | #endif 74 | } 75 | else if ((pLVCD->nmcd.uItemState & CDIS_SELECTED) && owner.IsRowSelected(nRow)) 76 | { 77 | if (owner.GetExtendedStyle() & LVS_EX_FULLROWSELECT || nCol == 0) 78 | { 79 | // Selection must be visible for this cell 80 | if (owner.UsingVisualStyle()) 81 | break; // Row selection is not drawn by background color 82 | 83 | if (m_InvertCellSelection && owner.GetFocusRow() == nRow && owner.GetFocusCell() == nCol) 84 | { 85 | // No drawing of selection color for focus cell 86 | if (pLVCD->clrTextBk > RGB(255, 255, 255)) 87 | break; 88 | 89 | backColor = pLVCD->clrTextBk; 90 | } 91 | else 92 | { 93 | if (owner.GetFocus() != &owner && !owner.IsCellEditorOpen()) 94 | { 95 | // Selection color is different when not having focus 96 | if (owner.GetStyle() & LVS_SHOWSELALWAYS) 97 | { 98 | backColor = ::GetSysColor(COLOR_BTNFACE); 99 | } 100 | else 101 | break; // No drawing of selection, when not in focus 102 | } 103 | else 104 | { 105 | backColor = ::GetSysColor(COLOR_HIGHLIGHT); 106 | } 107 | } 108 | } 109 | else 110 | { 111 | // Redraw with the given background color 112 | if (pLVCD->clrTextBk > RGB(255, 255, 255)) 113 | break; // If a color is more than white, then it is invalid 114 | 115 | backColor = pLVCD->clrTextBk; 116 | } 117 | } 118 | else 119 | { 120 | // Redraw with the given background color 121 | if (pLVCD->clrTextBk > RGB(255, 255, 255)) 122 | break; // If a color is more than white, then it is invalid 123 | 124 | backColor = pLVCD->clrTextBk; 125 | } 126 | 127 | CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); 128 | 129 | CRect rcIcon, rcIconArea; 130 | VERIFY(owner.GetCellRect(nRow, nCol, LVIR_ICON, rcIcon)); 131 | VERIFY(owner.GetCellRect(nRow, nCol, LVIR_BOUNDS, rcIconArea)); 132 | // When the label column is placed first it has a left-margin 133 | if (nCol == 0 && (nCol == owner.GetFirstVisibleColumn() || owner.GetExtendedStyle() & LVS_EX_CHECKBOXES)) 134 | { 135 | int cxborder = ::GetSystemMetrics(SM_CXBORDER); 136 | rcIconArea.left += cxborder * 2; 137 | } 138 | 139 | // Remove white margin between cell-image and cell-text 140 | rcIconArea.right = rcIcon.right + 2; 141 | 142 | // Stay within the limits of the column visible area 143 | if (rcIcon.right > pLVCD->nmcd.rc.right) 144 | rcIcon.right = pLVCD->nmcd.rc.right; 145 | 146 | if (rcIconArea.right > pLVCD->nmcd.rc.right) 147 | rcIconArea.right = pLVCD->nmcd.rc.right; 148 | 149 | CBrush brush(backColor); 150 | pDC->FillRect(&rcIconArea, &brush); 151 | 152 | IMAGEINFO iconSizeInfo = { 0 }; 153 | VERIFY(pImageList->GetImageInfo(0, &iconSizeInfo)); 154 | int iconHeight = iconSizeInfo.rcImage.bottom - iconSizeInfo.rcImage.top; 155 | if (rcIcon.Height() > iconHeight) 156 | rcIcon.top += (rcIcon.Height() - iconHeight) / 2; 157 | 158 | // Draw icon 159 | COLORREF oldBkColor = pImageList->SetBkColor(backColor); 160 | pImageList->Draw(pDC, 161 | nImage, 162 | rcIcon.TopLeft(), 163 | ILD_NORMAL); 164 | pImageList->SetBkColor(oldBkColor); 165 | 166 | if (nCol == 0 && owner.GetExtendedStyle() & LVS_EX_CHECKBOXES) 167 | { 168 | CImageList* pStateImageList = owner.GetImageList(LVSIL_STATE); 169 | if (pImageList == NULL) 170 | break; 171 | 172 | IMAGEINFO stateSizeInfo = { 0 }; 173 | VERIFY(pStateImageList->GetImageInfo(0, &stateSizeInfo)); 174 | int stateIconHeight = stateSizeInfo.rcImage.bottom - stateSizeInfo.rcImage.top; 175 | int stateIconWidth = stateSizeInfo.rcImage.right - stateSizeInfo.rcImage.left; 176 | if (rcIconArea.Height() > stateIconHeight) 177 | rcIconArea.top += (rcIconArea.Height() - stateIconHeight) / 2; 178 | 179 | if ((rcIcon.left - rcIconArea.left) > stateIconWidth) 180 | rcIconArea.left += ((rcIcon.left - rcIconArea.left) - stateIconWidth) / 2; 181 | 182 | int checkState = owner.GetCheck(nRow); 183 | COLORREF oldStateBkColor = pStateImageList->SetBkColor(backColor); 184 | pStateImageList->Draw(pDC, 185 | checkState, 186 | rcIconArea.TopLeft(), 187 | ILD_NORMAL); 188 | pStateImageList->SetBkColor(oldStateBkColor); 189 | } 190 | 191 | } break; 192 | } 193 | 194 | // Perform standard drawing 195 | CGridRowTraitText::OnCustomDraw(owner, pLVCD, pResult); 196 | } -------------------------------------------------------------------------------- /CGridListCtrlEx/CGridRowTraitXP.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #include "CGridRowTraitText.h" 10 | 11 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 12 | // Using MFC Extension DLL 13 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 14 | #undef AFX_DATA 15 | #define AFX_DATA AFX_EXT_DATA 16 | #else 17 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 18 | #endif 19 | 20 | //------------------------------------------------------------------------ 21 | //! CGridRowTraitXP fixes drawing of rows when the application is using 22 | //! classic- or XP-style. 23 | //------------------------------------------------------------------------ 24 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CGridRowTraitXP : public CGridRowTraitText 25 | { 26 | public: 27 | virtual void OnCustomDraw(CGridListCtrlEx& owner, NMLVCUSTOMDRAW* pLVCD, LRESULT* pResult); 28 | 29 | protected: 30 | virtual void Accept(CGridRowTraitVisitor& visitor); 31 | }; 32 | 33 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 34 | #undef AFX_DATA 35 | #define AFX_DATA 36 | #endif 37 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/Debug/CGridListCtrlEx.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/CGridListCtrlEx/Debug/CGridListCtrlEx.lib -------------------------------------------------------------------------------- /CGridListCtrlEx/MAKEFILE: -------------------------------------------------------------------------------- 1 | BUILD_ALLOW_COMPILER_WARNINGS=1 2 | BUILD_ALLOW_LINKER_WARNINGS=1 3 | 4 | # 5 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 6 | # file to this component. This file merely indirects to the real make file 7 | # that is shared by all the driver components of the Windows NT DDK 8 | # 9 | 10 | !INCLUDE $(NTMAKEENV)\makefile.def 11 | 12 | -------------------------------------------------------------------------------- /CGridListCtrlEx/Release/CGridListCtrlEx.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/CGridListCtrlEx/Release/CGridListCtrlEx.lib -------------------------------------------------------------------------------- /CGridListCtrlEx/SOURCES: -------------------------------------------------------------------------------- 1 | TARGETNAME=CGridListCtrlEx 2 | TARGETPATH=obj 3 | TARGETTYPE=LIBRARY 4 | 5 | C_DEFINES=/DUSE_MFC6_WITH_ATL7=1 /D_LIB=1 /D_WDK_BUILD=1 $(C_DEFINES) 6 | INCLUDES= .;..\Filter\; \ 7 | $(DDK_INC_PATH);$(SDK_INC_PATH); $(MFC_INC_PATH); \ 8 | $(MFC_INC_PATH)\..\atlmfc;$(INCLUDES) 9 | 10 | USE_STL=1 11 | STL_VER=70 12 | 13 | MSC_STDCALL=0 14 | 386_STDCALL=0 15 | USE_MFCUNICODE=1 16 | 17 | SOURCES= CGridColumnTraitCombo.cpp CGridColumnTraitDateTime.cpp \ 18 | CGridColumnTraitEdit.cpp CGridColumnTraitHyperLink.cpp \ 19 | CGridColumnTraitImage.cpp CGridColumnTraitMultilineEdit.cpp \ 20 | CGridColumnTraitText.cpp CGridListCtrlEx.cpp \ 21 | CGridListCtrlGroups.cpp CGridRowTraitText.cpp \ 22 | CGridRowTraitXP.cpp ViewConfigSection.cpp 23 | -------------------------------------------------------------------------------- /CGridListCtrlEx/ViewConfigSection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //------------------------------------------------------------------------ 4 | // Author: Rolf Kristensen 5 | // Source: http://www.codeproject.com/KB/list/CGridListCtrlEx.aspx 6 | // License: Free to use for all (New BSD License) 7 | //------------------------------------------------------------------------ 8 | 9 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 10 | // Using MFC Extension DLL 11 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS AFX_EXT_CLASS 12 | #undef AFX_DATA 13 | #define AFX_DATA AFX_EXT_DATA 14 | template class CGRIDLISTCTRLEX_AFX_EXT_CLASS CSimpleMap; 15 | #else 16 | #define CGRIDLISTCTRLEX_AFX_EXT_CLASS 17 | #endif 18 | 19 | //------------------------------------------------------------------------ 20 | //! Abstract interface for persisting view configuration 21 | //------------------------------------------------------------------------ 22 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CViewConfigSection 23 | { 24 | protected: 25 | CString m_ViewName; //!< Configuration name used when persisting the state (Translates into a section name) 26 | 27 | //! Pure virtual interface for reading setting from persisting layer 28 | virtual CString ReadSetting(const CString& strSection, const CString& strSetting, const CString& strDefval) const = 0; 29 | //! Pure virtual interface for writing setting to persisting layer 30 | virtual void WriteSetting(const CString& strSection, const CString& strSetting, const CString& strValue) = 0; 31 | //! Pure virtual interface for removing setting section from persisting layer 32 | virtual void RemoveSection(const CString& strSection) = 0; 33 | 34 | // Converters 35 | virtual CString ConvertBoolSetting(bool bValue) const; 36 | virtual CString ConvertIntSetting(int nValue) const; 37 | virtual CString ConvertFloatSetting(double nValue, int nDecimals = 6) const; 38 | virtual CString ConvertArraySetting(const CSimpleArray& values, const CString& strDelimiter = _T(", ")) const; 39 | virtual CString ConvertArraySetting(const CSimpleArray& values, const CString& strDelimiter = _T(", ")) const; 40 | virtual CString ConvertLogFontSetting(const LOGFONT& font) const; 41 | virtual CString ConvertRectSetting(const RECT& rect) const; 42 | virtual CString ConvertColorSetting(COLORREF color) const; 43 | virtual void SplitArraySetting(const CString& strArray, CSimpleArray& values, const CString& strDelimiter = _T(", ")) const; 44 | 45 | virtual const CString& GetSectionName() const; 46 | 47 | public: 48 | explicit CViewConfigSection(const CString& strViewName); 49 | virtual ~CViewConfigSection(); 50 | 51 | // Getters 52 | virtual CString GetSetting(const CString& strName, const CString& strDefval = _T("")) const; 53 | virtual bool GetBoolSetting(const CString& strName, bool bDefval = false) const; 54 | virtual int GetIntSetting(const CString& strName, int nDefval = 0) const; 55 | virtual double GetFloatSetting(const CString& strName, double nDefval = 0.0) const; 56 | virtual LOGFONT GetLogFontSetting(const CString& strName) const; 57 | virtual CRect GetRectSetting(const CString& strName, const CRect& rectDefval = CRect(0, 0, 0, 0)) const; 58 | virtual COLORREF GetColorSetting(const CString& strName, const COLORREF colorDefval = RGB(0, 0, 0)) const; 59 | virtual void GetArraySetting(const CString& strName, CSimpleArray& values, const CString& strDelimiter = _T(", ")) const; 60 | virtual void GetArraySetting(const CString& strName, CSimpleArray& values, const CString& strDelimiter = _T(", ")) const; 61 | 62 | // Setters 63 | virtual void SetSetting(const CString& strName, const CString& strValue); 64 | virtual void SetBoolSetting(const CString& strName, bool bValue); 65 | virtual void SetIntSetting(const CString& strName, int nValue); 66 | virtual void SetFloatSetting(const CString& strName, double nValue, int nDecimals = 6); 67 | virtual void SetArraySetting(const CString& strName, const CSimpleArray& values, const CString& strDelimiter = _T(", ")); 68 | virtual void SetArraySetting(const CString& strName, const CSimpleArray& values, const CString& strDelimiter = _T(", ")); 69 | virtual void SetLogFontSetting(const CString& strName, const LOGFONT& font); 70 | virtual void SetRectSetting(const CString& strName, const RECT& rect); 71 | virtual void SetColorSetting(const CString& strName, COLORREF color); 72 | 73 | virtual void RemoveCurrentConfig(); 74 | }; 75 | 76 | //------------------------------------------------------------------------ 77 | //! Abstract interface for persisting view configuration, that can use 78 | //! an in-memory default-configuration. 79 | //! 80 | //! It will use the values in the default-config if nothing else can be found 81 | //------------------------------------------------------------------------ 82 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CViewConfigSectionDefault : public CViewConfigSection 83 | { 84 | protected: 85 | //! Inner class that stores the default configuration in memory 86 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CViewConfigSectionLocal : public CViewConfigSection 87 | { 88 | protected: 89 | CSimpleMap m_LocalSettings; //!< Default configuration 90 | 91 | // Persistence of settings 92 | virtual CString ReadSetting(const CString& strSection, const CString& strName, const CString& strDefval) const; 93 | virtual void WriteSetting(const CString& strSection, const CString& strName, const CString& strValue); 94 | virtual void RemoveSection(const CString& strSection); 95 | 96 | public: 97 | explicit CViewConfigSectionLocal(const CString& strViewName); 98 | CViewConfigSectionLocal(const CViewConfigSectionLocal& other); 99 | CViewConfigSectionLocal& operator=(const CViewConfigSectionLocal& other); 100 | 101 | bool HasSettings() const; 102 | void CopySettings(CViewConfigSection& destination) const; 103 | }; 104 | CViewConfigSectionLocal m_DefaultConfig; //!< Default configuration stored in memory 105 | 106 | public: 107 | explicit CViewConfigSectionDefault(const CString& strViewName); 108 | 109 | virtual CViewConfigSection& GetDefaultConfig(); 110 | virtual bool HasDefaultConfig() const; 111 | virtual void ResetConfigDefault(); 112 | 113 | virtual CString GetSetting(const CString& strName, const CString& strDefval = _T("")) const; 114 | }; 115 | 116 | //------------------------------------------------------------------------ 117 | //! Abstract interface for persisting view configuration, that can switch 118 | //! between different view configuration profiles. 119 | //------------------------------------------------------------------------ 120 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CViewConfigSectionProfiles : public CViewConfigSectionDefault 121 | { 122 | protected: 123 | mutable CString m_CurrentSection; //!< Section name combined from the viewname and the current profile name 124 | virtual const CString& GetSectionName() const; 125 | 126 | virtual void SplitSectionName(const CString& strSection, CString& strViewName, CString& strProfile); 127 | virtual CString JoinSectionName(const CString& strViewName, const CString& strProfile) const; 128 | 129 | public: 130 | explicit CViewConfigSectionProfiles(const CString& strViewName); 131 | 132 | virtual void RemoveCurrentConfig(); 133 | 134 | virtual void GetProfiles(CSimpleArray& profiles) const; 135 | virtual CString GetActiveProfile(); 136 | virtual void SetActiveProfile(const CString& strProfile); 137 | virtual void AddProfile(const CString& strProfile); 138 | virtual void DeleteProfile(const CString& strProfile); 139 | }; 140 | 141 | //------------------------------------------------------------------------ 142 | //! Can persist the column configuration using CWinApp::WriteProfile() 143 | //------------------------------------------------------------------------ 144 | class CGRIDLISTCTRLEX_AFX_EXT_CLASS CViewConfigSectionWinApp : public CViewConfigSectionProfiles 145 | { 146 | protected: 147 | virtual CString ReadSetting(const CString& strSection, const CString& strSetting, const CString& strDefval) const; 148 | virtual void WriteSetting(const CString& strSection, const CString& strSetting, const CString& strValue); 149 | virtual void RemoveSection(const CString& strSection); 150 | 151 | public: 152 | explicit CViewConfigSectionWinApp(const CString& strViewName); 153 | }; 154 | 155 | #ifdef CGRIDLISTCTRLEX_AFX_EXT 156 | #undef AFX_DATA 157 | #define AFX_DATA 158 | #endif 159 | #undef CGRIDLISTCTRLEX_AFX_EXT_CLASS -------------------------------------------------------------------------------- /CGridListCtrlEx/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 | #if _MSC_VER >= 1400 8 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 9 | #endif 10 | 11 | #ifndef WIN32_LEAN_AND_MEAN 12 | #define WIN32_LEAN_AND_MEAN 13 | #endif 14 | 15 | #ifndef VC_EXTRALEAN 16 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers (AFXV_W32.h) 17 | #endif 18 | 19 | #ifndef NO_STRICT 20 | #ifndef STRICT 21 | #define STRICT 1 22 | #endif 23 | #endif 24 | 25 | #if _MSC_VER < 1300 26 | // If using VC6 without platform SDK 27 | #ifndef WINVER 28 | #define WINVER 0x0500 29 | #endif 30 | #ifndef _WIN32_WINNT 31 | #define _WIN32_WINNT 0x0500 32 | #endif 33 | #ifndef _WIN32_WINDOWS 34 | #define _WIN32_WINDOWS 0x0500 35 | #endif 36 | #ifndef _WIN32_IE 37 | #define _WIN32_IE 0x0400 38 | #endif 39 | #endif 40 | 41 | // Modify the following defines if you have to target a platform prior to the ones specified below. 42 | // Refer to MSDN for the latest info on corresponding values for different platforms. 43 | #ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. 44 | #define WINVER 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. 45 | #endif 46 | 47 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. 48 | #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. 49 | #endif 50 | 51 | #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. 52 | #define _WIN32_WINDOWS 0x0501 // Change this to the appropriate value to target Windows Me or later. 53 | #endif 54 | 55 | #ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. 56 | #define _WIN32_IE 0x0501 // Change this to the appropriate value to target IE 5.0 or later. 57 | #endif 58 | 59 | #ifndef UNICODE 60 | #define CGRIDLISTCTRLEX_GROUPMODE 61 | #endif 62 | 63 | #ifdef _AFXEXT 64 | #define CGRIDLISTCTRLEX_AFX_EXT // Export/Import as MFC Extension DLL (Remember to use this define when including headers from DLL) 65 | #endif 66 | 67 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 68 | 69 | #pragma warning( disable:4514 ) // warning C4514: unreferenced inline function has been remove 70 | #pragma warning( disable:4710 ) // warning C4710: function not inlined 71 | #pragma warning( disable:4711 ) // warning C4711: function selected for automatic inline expansion 72 | #pragma warning( disable:4820 ) // warning C4820: X bytes padding added after data member 73 | 74 | #pragma warning( push ) 75 | #pragma warning( disable:4548 ) // warning C4548: expression before comma has no effect; expected expression with side-effect 76 | #pragma warning( disable:4812 ) // warning C4812: obsolete declaration style: please use '_CIP<_Interface,_IID>::_CIP' instead 77 | #pragma warning( disable:4996 ) // warning C4996: This function or variable may be unsafe. 78 | #pragma warning( disable:4005 ) // warning C4005: '_WIN32_WINDOWS' : macro redefinition 79 | #pragma warning( disable:4668 ) // warning C4668: '__midl' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' 80 | #pragma warning( disable:4820 ) // warning C4820: X bytes padding added after data member 81 | #pragma warning( disable:4619 ) // warning C4619: #pragma warning : there is no warning number 82 | #pragma warning( disable:4625 ) // warning C4625: copy constructor could not be generated because a base class copy constructor is inaccessible 83 | #pragma warning( disable:4626 ) // warning C4626: assignment operator could not be generated because a base class assignment operator is inaccessible 84 | #pragma warning( disable:4365 ) // warning C4365: '=' : conversion from 'int' to 'size_t', signed/unsigned mismatch 85 | #pragma warning( disable:4244 ) // warning C4244: 'return' : conversion from 'const time_t' to 'LONG_PTR', possible loss of data 86 | #pragma warning( disable:4263 ) // warning C4263: member function does not override any base class virtual member function 87 | #pragma warning( disable:4264 ) // warning C4264: no override available for virtual member function from base; function is hidden 88 | #pragma warning( disable:4917 ) // warning C4917: a GUID can only be associated with a class, interface or namespace 89 | #pragma warning( disable:4555 ) // warning C4555: expression has no effect; expected expression with side-effect 90 | #pragma warning( disable:4640 ) // warning C4640: construction of local static object is not thread-safe 91 | #pragma warning( disable:4571 ) // warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught 92 | #pragma warning( disable:4987 ) // warning C4987: nonstandard extension used: 'throw (...)' 93 | #pragma warning( disable:4266 ) // warning C4266: 'BOOL CException::GetErrorMessage(LPTSTR,UINT,PUINT)': no override available for virtual member function from base 'CException'; function is hidden 94 | 95 | 96 | #include // MFC core and standard components 97 | #include // MFC extensions 98 | 99 | #ifndef _AFX_NO_OLE_SUPPORT 100 | #include // MFC Automation classes 101 | #include // MFC support for Internet Explorer 4 Common Controls 102 | #endif // _AFX_NO_OLE_SUPPORT 103 | 104 | #ifndef _AFX_NO_AFXCMN_SUPPORT 105 | #include // MFC support for Windows Common Controls 106 | #endif // _AFX_NO_AFXCMN_SUPPORT 107 | 108 | #include 109 | 110 | #pragma warning( pop ) 111 | 112 | #include 113 | #include 114 | #include 115 | 116 | using namespace std; -------------------------------------------------------------------------------- /DIRS: -------------------------------------------------------------------------------- 1 | DIRS = Filter CGridListCtrlEx Manager 2 | -------------------------------------------------------------------------------- /Filter/Filter.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 30 | 43 | 44 | 53 | 66 | 67 | 68 | 69 | 70 | 71 | 75 | 78 | 79 | 82 | 83 | 86 | 87 | 90 | 91 | 94 | 95 | 98 | 99 | 102 | 103 | 104 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Filter/Filter.vcproj.vspscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" 10 | } 11 | -------------------------------------------------------------------------------- /Filter/MAKEFILE: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # Copyright 2016 Matt Wu under MIT license 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | # DEALINGS IN THE SOFTWARE. 22 | # 23 | # PROJECT: 24 | # Moure: Swap Mouse Left and Right Buttons 25 | # 26 | 27 | !INCLUDE $(NTMAKEENV)\makefile.def 28 | -------------------------------------------------------------------------------- /Filter/SOURCES: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # Copyright 2016 Matt Wu under MIT license 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a 6 | # copy of this software and associated documentation files (the "Software"), 7 | # to deal in the Software without restriction, including without limitation 8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | # and/or sell copies of the Software, and to permit persons to whom the 10 | # Software is furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included 13 | # in all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | # DEALINGS IN THE SOFTWARE. 22 | # 23 | # PROJECT: 24 | # Moure: Swap Mouse Left and Right Buttons 25 | # 26 | 27 | 28 | TARGETNAME=moure 29 | TARGETPATH=obj 30 | TARGETTYPE=DRIVER 31 | 32 | INCLUDES=.;$(SDK_INC_PATH); 33 | TARGETPATH=.\$(DDK_TARGET_OS)\$(DDKBUILDENV) 34 | TARGETLIBS=$(DDK_LIB_PATH)\wdmsec.lib 35 | 36 | SOURCES=moure.c moure.rc 37 | -------------------------------------------------------------------------------- /Filter/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Device Names 3 | */ 4 | 5 | #define MOURE_DEVICE L"\\Device\\Mousre" /* real device object name */ 6 | #define MOURE_SYMLNK L"\\DosDevices\\Mousre" /* user-visible symlink name */ 7 | #define MOURE_DOSDEV L"\\\\.\\Mousre" /* device for user mode app */ 8 | 9 | /* 10 | * Registry Values 11 | */ 12 | 13 | #define MOURE_DEVLIST L"MouseHWs" 14 | 15 | 16 | /* 17 | * Data Exchange between Kernel and User modes 18 | */ 19 | 20 | typedef struct mr_io_element { 21 | USHORT me_start; 22 | USHORT me_size; 23 | } MR_IO_ELEMENT, *PMR_IO_ELEMENT; 24 | 25 | #define MR_IO_SLOT_MAGIC 'QIRM' 26 | 27 | #define MR_DEV_STATE_ENABLED (1 << 0) 28 | #define MR_DEV_STATE_PERSIST (1 << 1) 29 | 30 | typedef struct mr_io_slot { 31 | 32 | USHORT mi_size; /* size of this slot */ 33 | 34 | USHORT mi_cmd; 35 | ULONG mi_state; 36 | 37 | ULONG mi_magic; 38 | ULONG mi_flags; 39 | 40 | MR_IO_ELEMENT mi_id; 41 | MR_IO_ELEMENT mi_desc; 42 | MR_IO_ELEMENT mi_name; 43 | MR_IO_ELEMENT mi_ven; 44 | 45 | GUID mi_bus; 46 | __int64 mi_dcb; 47 | 48 | UCHAR mi_data[1]; 49 | 50 | } MR_IO_SLOT, *PMR_IO_SLOT; 51 | 52 | #define MR_IO_SLOT_SIZE (FIELD_OFFSET(MR_IO_SLOT, mi_data)) 53 | 54 | #define MR_IO_CMD_BASE '0M' 55 | #define MR_IO_CMD_SET MR_IO_CMD_BASE + 1 56 | 57 | #define MR_IO_MAGIC 'RIRM' 58 | 59 | typedef struct mr_io_record { 60 | 61 | ULONG mi_magic; 62 | ULONG mi_flags; 63 | 64 | ULONG mi_nslots; 65 | ULONG mi_length; 66 | 67 | MR_IO_SLOT mi_slot[1]; 68 | 69 | } MR_IO_RECORD, *PMR_IO_RECORD; 70 | 71 | #define MR_IO_REC_SIZE (FIELD_OFFSET(MR_IO_RECORD, mi_slot)) 72 | 73 | -------------------------------------------------------------------------------- /Filter/moure.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2016 Matt Wu under MIT license 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | * PROJECT: 24 | * Moure: Swap Mouse Left and Right Buttons 25 | * 26 | */ 27 | 28 | #ifndef _MR_HEADER_H_ 29 | #define _MR_HEADER_H_ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /* 38 | * 39 | * Global Defintions 40 | * 41 | */ 42 | 43 | 44 | /* 45 | * Debugging Message Display 46 | */ 47 | 48 | #define DEBUG(format, ...) \ 49 | do { \ 50 | DbgPrint("%d:%d:%s:%d:" format, KeGetCurrentProcessorNumber(), \ 51 | KeGetCurrentIrql(), __FUNCTION__, __LINE__, ## __VA_ARGS__); \ 52 | } while(0) 53 | 54 | 55 | 56 | /* 57 | * 58 | * Core Structures 59 | * 60 | */ 61 | 62 | 63 | /* 64 | * global 65 | */ 66 | 67 | typedef struct mr_core { 68 | 69 | PDEVICE_OBJECT mc_devobj; /* control devobj for manager console */ 70 | ERESOURCE mc_lock; 71 | LIST_ENTRY mc_dcb_list; /* list of mouse devices */ 72 | PWCHAR mc_dev_list; /* buffer for registry settings */ 73 | ULONG mc_dev_bytes;/* bytes of mc_dev_list */ 74 | ULONG mc_dcb_count;/* count of mouse devices */ 75 | UNICODE_STRING mc_reg; /* registry path */ 76 | 77 | } MR_CORE, *PMR_CORE; 78 | 79 | /* 80 | * device extension definition 81 | */ 82 | 83 | typedef struct mr_dcb { 84 | 85 | LIST_ENTRY md_link; /* to be linked to global list */ 86 | PDEVICE_OBJECT md_target; /* target device */ 87 | GUID md_bus; /* bus GUID */ 88 | UNICODE_STRING md_did; /* vendor and device id */ 89 | UNICODE_STRING md_ven; /* manufactor */ 90 | UNICODE_STRING md_desc; /* device desc */ 91 | UNICODE_STRING md_name; /* device desc */ 92 | ULONG md_state; /* flags: swap or not */ 93 | ULONG md_ext; 94 | 95 | } MR_DCB, *PMR_DCB; 96 | 97 | 98 | /* 99 | * 100 | * Function Prototypes 101 | * 102 | */ 103 | 104 | NTSTATUS DriverEntry( 105 | IN PDRIVER_OBJECT DriverObject, 106 | IN PUNICODE_STRING RegistryPath 107 | ); 108 | 109 | #endif /* _MR_HEADER_H_ */ -------------------------------------------------------------------------------- /Filter/moure.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "Windows.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | ///////////////////////////////////////////////////////////////////////////// 11 | #undef APSTUDIO_READONLY_SYMBOLS 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | // 15 | // Version 16 | // 17 | 18 | VS_VERSION_INFO VERSIONINFO 19 | FILEVERSION 1,1,7,14 20 | PRODUCTVERSION 1,1,7,14 21 | FILEFLAGSMASK 0x3fL 22 | #ifdef _DEBUG 23 | FILEFLAGS 0x1L 24 | #else 25 | FILEFLAGS 0x0L 26 | #endif 27 | FILEOS 0x40004L 28 | FILETYPE 0x3L 29 | FILESUBTYPE 0x7L 30 | BEGIN 31 | BLOCK "StringFileInfo" 32 | BEGIN 33 | BLOCK "040904b0" 34 | BEGIN 35 | VALUE "CompanyName", "Ext2Fsd Group" 36 | VALUE "FileDescription", "Windows Mouse Buttons Swapper" 37 | VALUE "FileVersion", "1.1" 38 | VALUE "InternalName", "Moure.sys" 39 | VALUE "LegalCopyright", "Copyright - Matt Wu" 40 | VALUE "OriginalFilename", "moure.sys" 41 | VALUE "ProductName", "Moure" 42 | VALUE "ProductVersion", "1.1" 43 | END 44 | END 45 | BLOCK "VarFileInfo" 46 | BEGIN 47 | VALUE "Translation", 0x409, 1200 48 | END 49 | END 50 | 51 | 52 | #ifdef APSTUDIO_INVOKED 53 | ///////////////////////////////////////////////////////////////////////////// 54 | // 55 | // TEXTINCLUDE 56 | // 57 | 58 | 1 TEXTINCLUDE 59 | BEGIN 60 | END 61 | 62 | 2 TEXTINCLUDE 63 | BEGIN 64 | "\0" 65 | END 66 | 67 | 3 TEXTINCLUDE 68 | BEGIN 69 | "\r\n" 70 | "\0" 71 | END 72 | 73 | #endif // APSTUDIO_INVOKED 74 | 75 | 76 | #ifndef APSTUDIO_INVOKED 77 | ///////////////////////////////////////////////////////////////////////////// 78 | // 79 | // Generated from the TEXTINCLUDE 3 resource. 80 | // 81 | 82 | [ 83 | ///////////////////////////////////////////////////////////////////////////// 84 | #endif // not APSTUDIO_INVOKED 85 | 86 | -------------------------------------------------------------------------------- /Manager/CGridListCtrlEx.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 | #ifdef APSTUDIO_INVOKED 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // 18 | // TEXTINCLUDE 19 | // 20 | 21 | 1 TEXTINCLUDE 22 | BEGIN 23 | "resource.h\0" 24 | END 25 | 26 | 2 TEXTINCLUDE 27 | BEGIN 28 | "#include ""afxres.h""\r\n" 29 | "\0" 30 | END 31 | 32 | 3 TEXTINCLUDE 33 | BEGIN 34 | "#define _AFX_NO_SPLITTER_RESOURCES\r\n" 35 | "#define _AFX_NO_OLE_RESOURCES\r\n" 36 | "#define _AFX_NO_TRACKER_RESOURCES\r\n" 37 | "#define _AFX_NO_PROPERTY_RESOURCES\r\n" 38 | "\r\n" 39 | "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" 40 | "LANGUAGE 9, 1\r\n" 41 | "#pragma code_page(1252)\r\n" 42 | "#include ""res\\CGridListCtrlEx.rc2"" // non-Microsoft Visual C++ edited resources\r\n" 43 | "#include ""afxres.rc"" // Standard components\r\n" 44 | "#endif\r\n" 45 | "\0" 46 | END 47 | 48 | #endif // APSTUDIO_INVOKED 49 | 50 | 51 | ///////////////////////////////////////////////////////////////////////////// 52 | // 53 | // Icon 54 | // 55 | 56 | // Icon with lowest ID value placed first to ensure application icon 57 | // remains consistent on all systems. 58 | IDR_MAINFRAME ICON "res\\CGridListCtrlEx.ico" 59 | ///////////////////////////////////////////////////////////////////////////// 60 | 61 | 62 | ///////////////////////////////////////////////////////////////////////////// 63 | // English (U.S.) resources 64 | 65 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 66 | #ifdef _WIN32 67 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 68 | #pragma code_page(1252) 69 | #endif //_WIN32 70 | 71 | ///////////////////////////////////////////////////////////////////////////// 72 | // 73 | // Dialog 74 | // 75 | 76 | IDD_ABOUTBOX DIALOGEX 0, 0, 195, 45 77 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU 78 | FONT 8, "MS Shell Dlg", 0, 0, 0x1 79 | BEGIN 80 | ICON IDR_MAINFRAME,IDC_STATIC,11,12,21,20 81 | LTEXT "Moure: Swap Your Mouse Buttons",IDC_STATIC,40,10,119,8,SS_NOPREFIX 82 | LTEXT "Matt Wu ",IDC_STATIC,40,25,119,8 83 | DEFPUSHBUTTON "OK",IDOK,160,7,28,29,WS_GROUP 84 | END 85 | 86 | IDD_CGRIDLISTCTRLEX_DIALOG DIALOGEX 0, 0, 385, 92 87 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU 88 | EXSTYLE WS_EX_APPWINDOW 89 | CAPTION "Mouse Buttons Management" 90 | FONT 8, "MS Shell Dlg", 0, 0, 0x1 91 | BEGIN 92 | CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,0,0,385,92 93 | END 94 | 95 | 96 | ///////////////////////////////////////////////////////////////////////////// 97 | // 98 | // Version 99 | // 100 | 101 | VS_VERSION_INFO VERSIONINFO 102 | FILEVERSION 1,41,7,12 103 | PRODUCTVERSION 1,41,7,12 104 | FILEFLAGSMASK 0x3fL 105 | #ifdef _DEBUG 106 | FILEFLAGS 0x1L 107 | #else 108 | FILEFLAGS 0x0L 109 | #endif 110 | FILEOS 0x4L 111 | FILETYPE 0x1L 112 | FILESUBTYPE 0x0L 113 | BEGIN 114 | BLOCK "StringFileInfo" 115 | BEGIN 116 | BLOCK "040904e4" 117 | BEGIN 118 | VALUE "CompanyName", "Ext2Fsd Group" 119 | VALUE "FileDescription", "Swap Your Mouse Buttons" 120 | VALUE "FileVersion", "1.41.7.12" 121 | VALUE "InternalName", "moure.exe" 122 | VALUE "LegalCopyright", "Copyright - Matt Wu" 123 | VALUE "OriginalFilename", "moure.exe" 124 | VALUE "ProductName", "moure by Ext2Fsd" 125 | VALUE "ProductVersion", "1.41.7.12" 126 | END 127 | END 128 | BLOCK "VarFileInfo" 129 | BEGIN 130 | VALUE "Translation", 0x409, 1252 131 | END 132 | END 133 | 134 | 135 | ///////////////////////////////////////////////////////////////////////////// 136 | // 137 | // DESIGNINFO 138 | // 139 | 140 | #ifdef APSTUDIO_INVOKED 141 | GUIDELINES DESIGNINFO 142 | BEGIN 143 | IDD_ABOUTBOX, DIALOG 144 | BEGIN 145 | LEFTMARGIN, 7 146 | RIGHTMARGIN, 188 147 | TOPMARGIN, 7 148 | BOTTOMMARGIN, 38 149 | END 150 | END 151 | #endif // APSTUDIO_INVOKED 152 | 153 | 154 | ///////////////////////////////////////////////////////////////////////////// 155 | // 156 | // String Table 157 | // 158 | 159 | STRINGTABLE 160 | BEGIN 161 | IDS_ABOUTBOX "&About Moure..." 162 | END 163 | 164 | #endif // English (U.S.) resources 165 | ///////////////////////////////////////////////////////////////////////////// 166 | 167 | 168 | 169 | #ifndef APSTUDIO_INVOKED 170 | ///////////////////////////////////////////////////////////////////////////// 171 | // 172 | // Generated from the TEXTINCLUDE 3 resource. 173 | // 174 | #define _AFX_NO_SPLITTER_RESOURCES 175 | #define _AFX_NO_OLE_RESOURCES 176 | #define _AFX_NO_TRACKER_RESOURCES 177 | #define _AFX_NO_PROPERTY_RESOURCES 178 | 179 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 180 | LANGUAGE 9, 1 181 | #pragma code_page(1252) 182 | #include "res\CGridListCtrlEx.rc2" // non-Microsoft Visual C++ edited resources 183 | #include "afxres.rc" // Standard components 184 | #endif 185 | 186 | ///////////////////////////////////////////////////////////////////////////// 187 | #endif // not APSTUDIO_INVOKED 188 | 189 | -------------------------------------------------------------------------------- /Manager/CGridListCtrlExApp.cpp: -------------------------------------------------------------------------------- 1 | // CGridListCtrlEx.cpp : Defines the class behaviors for the application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "CGridListCtrlExApp.h" 6 | #include "CGridListCtrlExDlg.h" 7 | 8 | #ifdef _DEBUG 9 | #define new DEBUG_NEW 10 | #endif 11 | 12 | 13 | // CGridListCtrlExApp 14 | 15 | BEGIN_MESSAGE_MAP(CGridListCtrlExApp, CWinApp) 16 | ON_COMMAND(ID_HELP, CWinApp::OnHelp) 17 | END_MESSAGE_MAP() 18 | 19 | 20 | // CGridListCtrlExApp construction 21 | 22 | CGridListCtrlExApp::CGridListCtrlExApp() 23 | { 24 | // TODO: add construction code here, 25 | // Place all significant initialization in InitInstance 26 | } 27 | 28 | 29 | // The one and only CGridListCtrlExApp object 30 | 31 | CGridListCtrlExApp theApp; 32 | 33 | 34 | // CGridListCtrlExApp initialization 35 | 36 | BOOL CGridListCtrlExApp::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 | AfxEnableControlContainer(); 46 | 47 | AfxOleInit(); 48 | 49 | // Standard initialization 50 | // If you are not using these features and wish to reduce the size 51 | // of your final executable, you should remove from the following 52 | // the specific initialization routines you do not need 53 | // Change the registry key under which our settings are stored 54 | // TODO: You should modify this string to be something appropriate 55 | // such as the name of your company or organization 56 | SetRegistryKey(_T("CGridListCtrlEx Demo Application")); 57 | 58 | CGridListCtrlExDlg dlg; 59 | m_pMainWnd = &dlg; 60 | INT_PTR nResponse = dlg.DoModal(); 61 | if (nResponse == IDOK) 62 | { 63 | // TODO: Place code here to handle when the dialog is 64 | // dismissed with OK 65 | } 66 | else if (nResponse == IDCANCEL) 67 | { 68 | // TODO: Place code here to handle when the dialog is 69 | // dismissed with Cancel 70 | } 71 | 72 | // Since the dialog has been closed, return FALSE so that we exit the 73 | // application, rather than start the application's message pump. 74 | return FALSE; 75 | } 76 | -------------------------------------------------------------------------------- /Manager/CGridListCtrlExApp.h: -------------------------------------------------------------------------------- 1 | // CGridListCtrlEx.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 | // CGridListCtrlExApp: 14 | // See CGridListCtrlEx.cpp for the implementation of this class 15 | // 16 | 17 | class CGridListCtrlExApp : public CWinApp 18 | { 19 | public: 20 | CGridListCtrlExApp(); 21 | 22 | // Overrides 23 | public: 24 | virtual BOOL InitInstance(); 25 | 26 | // Implementation 27 | 28 | DECLARE_MESSAGE_MAP() 29 | 30 | private: 31 | CGridListCtrlExApp(const CGridListCtrlExApp&); 32 | CGridListCtrlExApp& operator=(const CGridListCtrlExApp&); 33 | }; 34 | 35 | extern CGridListCtrlExApp theApp; -------------------------------------------------------------------------------- /Manager/CGridListCtrlExDlg.cpp: -------------------------------------------------------------------------------- 1 | // CGridListCtrlExDlg.cpp : implementation file 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "CGridListCtrlExApp.h" 6 | #include "CGridListCtrlExDlg.h" 7 | 8 | 9 | #include "..\CGridListCtrlEx\CGridColumnTraitDateTime.h" 10 | #include "..\CGridListCtrlEx\CGridColumnTraitEdit.h" 11 | #include "..\CGridListCtrlEx\CGridColumnTraitCombo.h" 12 | #include "..\CGridListCtrlEx\CGridColumnTraitHyperLink.h" 13 | #include "..\CGridListCtrlEx\CGridRowTraitXP.h" 14 | #include "..\CGridListCtrlEx\ViewConfigSection.h" 15 | 16 | #ifdef _DEBUG 17 | #define new DEBUG_NEW 18 | #endif 19 | 20 | // CAboutDlg dialog used for App About 21 | 22 | class CAboutDlg : public CDialog 23 | { 24 | public: 25 | CAboutDlg(); 26 | 27 | // Dialog Data 28 | enum { IDD = IDD_ABOUTBOX }; 29 | 30 | protected: 31 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 32 | 33 | // Implementation 34 | protected: 35 | DECLARE_MESSAGE_MAP() 36 | 37 | private: 38 | CAboutDlg(const CAboutDlg&); 39 | CAboutDlg& operator=(const CAboutDlg&); 40 | }; 41 | 42 | CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 43 | { 44 | } 45 | 46 | void CAboutDlg::DoDataExchange(CDataExchange* pDX) 47 | { 48 | CDialog::DoDataExchange(pDX); 49 | } 50 | 51 | BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 52 | END_MESSAGE_MAP() 53 | 54 | 55 | // CGridListCtrlExDlg dialog 56 | 57 | 58 | 59 | CGridListCtrlExDlg::CGridListCtrlExDlg(CWnd* pParent /*=NULL*/) 60 | : CDialog(CGridListCtrlExDlg::IDD, pParent) 61 | { 62 | m_TimeoutSeconds = 30; 63 | m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 64 | } 65 | 66 | void CGridListCtrlExDlg::DoDataExchange(CDataExchange* pDX) 67 | { 68 | CDialog::DoDataExchange(pDX); 69 | DDX_Control(pDX, IDC_LIST1, m_ListCtrl); 70 | } 71 | 72 | BEGIN_MESSAGE_MAP(CGridListCtrlExDlg, CDialog) 73 | ON_WM_SYSCOMMAND() 74 | ON_WM_PAINT() 75 | ON_WM_QUERYDRAGICON() 76 | ON_WM_TIMER() 77 | //}}AFX_MSG_MAP 78 | END_MESSAGE_MAP() 79 | 80 | 81 | VOID CGridListCtrlExDlg::ClearListView() 82 | { 83 | while (m_ListCtrl.GetItemCount()) 84 | m_ListCtrl.DeleteItem(0); 85 | } 86 | 87 | VOID CGridListCtrlExDlg::UpdateListView() 88 | { 89 | // Insert data into list-control by copying from datamodel 90 | int nItem = 0; 91 | for(size_t rowId = 0; rowId < m_DataModel.GetRowIds() ; ++rowId) 92 | { 93 | nItem = m_ListCtrl.InsertItem(++nItem, m_DataModel.GetCellText(rowId,0)); 94 | m_ListCtrl.SetItemData(nItem, rowId); 95 | for(int col = 0; col < m_DataModel.GetColCount() ; ++col) 96 | { 97 | int nCellCol = col+1; // +1 because of hidden column 98 | const CString& strCellText = m_DataModel.GetCellText(rowId, col); 99 | m_ListCtrl.SetItemText(nItem, nCellCol, strCellText); 100 | if (nCellCol==3) 101 | { 102 | CGridColumnTraitCombo* pComboTrait = (CGridColumnTraitCombo*) 103 | m_ListCtrl.GetCellColumnTrait(rowId, nCellCol); 104 | if (strCellText==_T("")) { 105 | m_ListCtrl.SetCellImage(nItem, nCellCol, m_nStateImageIdx); // unchecked 106 | } else { 107 | m_ListCtrl.SetCellImage(nItem, nCellCol, m_nStateImageIdx + 1); // checked 108 | } 109 | } 110 | } 111 | } 112 | } 113 | 114 | // CGridListCtrlExDlg message handlers 115 | 116 | BOOL CGridListCtrlExDlg::OnInitDialog() 117 | { 118 | CDialog::OnInitDialog(); 119 | 120 | // Add "About..." menu item to system menu. 121 | 122 | // IDM_ABOUTBOX must be in the system command range. 123 | ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 124 | ASSERT(IDM_ABOUTBOX < 0xF000); 125 | 126 | CMenu* pSysMenu = GetSystemMenu(FALSE); 127 | if (pSysMenu != NULL) 128 | { 129 | CString strAboutMenu; 130 | VERIFY(strAboutMenu.LoadString(IDS_ABOUTBOX)); 131 | if (!strAboutMenu.IsEmpty()) 132 | { 133 | pSysMenu->AppendMenu(MF_SEPARATOR); 134 | pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 135 | } 136 | } 137 | 138 | // Set the icon for this dialog. The framework does this automatically 139 | // when the application's main window is not a dialog 140 | SetIcon(m_hIcon, TRUE); // Set big icon 141 | SetIcon(m_hIcon, FALSE); // Set small icon 142 | 143 | // Create and attach image list 144 | m_ImageList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 1, 0); 145 | m_nStateImageIdx =CGridColumnTraitCombo::AppendStateImages(m_ListCtrl, m_ImageList); // Add checkboxes 146 | 147 | // Give better margin to editors 148 | m_ListCtrl.SetCellMargin(1.2); 149 | CGridRowTraitXP* pRowTrait = new CGridRowTraitXP; 150 | m_ListCtrl.SetDefaultRowTrait(pRowTrait); 151 | m_ListCtrl.EnableVisualStyles(true); 152 | 153 | // Create Columns 154 | m_ListCtrl.InsertHiddenLabelColumn(); // Requires one never uses column 0 155 | 156 | for(int col = 0; col < m_DataModel.GetColCount() ; ++col) 157 | { 158 | const CString& title = m_DataModel.GetColTitle(col); 159 | CGridColumnTrait* pTrait = NULL; 160 | if (col==0) // Country 161 | { 162 | pTrait = new CGridColumnTraitText; 163 | } 164 | if (col==1) // City 165 | { 166 | pTrait = new CGridColumnTraitText; 167 | } 168 | if (col==2) // state 169 | { 170 | CGridColumnTraitCombo* pComboTrait = new CGridColumnTraitCombo; 171 | 172 | pComboTrait->AddItem((DWORD_PTR)0, _T("Persistent")); 173 | pComboTrait->AddItem((DWORD_PTR)1, _T("Temporary")); 174 | 175 | pComboTrait->AddImageIndex(m_nStateImageIdx, _T(""), false); // Unchecked (and not editable) 176 | pComboTrait->AddImageIndex(m_nStateImageIdx+1,_T("Persistent") , true); // Checked (and editable) 177 | pComboTrait->SetToggleSelection(true); 178 | pTrait = pComboTrait; 179 | } 180 | if (col==3) // Year won 181 | { 182 | pTrait = new CGridColumnTraitText; 183 | } 184 | 185 | m_ListCtrl.InsertColumnTrait(col+1, title, LVCFMT_LEFT, 100, col, pTrait); 186 | } 187 | 188 | UpdateListView(); 189 | 190 | CViewConfigSectionWinApp* pColumnProfile = new CViewConfigSectionWinApp(_T("Sample List")); 191 | pColumnProfile->AddProfile(_T("Default")); 192 | pColumnProfile->AddProfile(_T("Special")); 193 | m_ListCtrl.SetupColumnConfig(pColumnProfile); 194 | 195 | SetTimer('STAT', 1000, NULL); 196 | 197 | return TRUE; // return TRUE unless you set the focus to a control 198 | } 199 | 200 | void CGridListCtrlExDlg::OnTimer(UINT nIDEvent) 201 | { 202 | if (nIDEvent == 'STAT' && ++m_TickCount > m_TimeoutSeconds) { 203 | m_DataModel.InitDataModel(); 204 | ClearListView(); 205 | UpdateListView(); 206 | m_TickCount = 0; 207 | } 208 | 209 | CDialog::OnTimer(nIDEvent); 210 | } 211 | 212 | 213 | void CGridListCtrlExDlg::OnSysCommand(UINT nID, LPARAM lParam) 214 | { 215 | if ((nID & 0xFFF0) == IDM_ABOUTBOX) 216 | { 217 | CAboutDlg dlgAbout; 218 | dlgAbout.DoModal(); 219 | } 220 | else 221 | { 222 | CDialog::OnSysCommand(nID, lParam); 223 | } 224 | } 225 | 226 | // If you add a minimize button to your dialog, you will need the code below 227 | // to draw the icon. For MFC applications using the document/view model, 228 | // this is automatically done for you by the framework. 229 | 230 | void CGridListCtrlExDlg::OnPaint() 231 | { 232 | if (IsIconic()) 233 | { 234 | CPaintDC dc(static_cast(this)); // device context for painting 235 | 236 | SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); 237 | 238 | // Center icon in client rectangle 239 | int cxIcon = GetSystemMetrics(SM_CXICON); 240 | int cyIcon = GetSystemMetrics(SM_CYICON); 241 | CRect rect; 242 | GetClientRect(&rect); 243 | int x = (rect.Width() - cxIcon + 1) / 2; 244 | int y = (rect.Height() - cyIcon + 1) / 2; 245 | 246 | // Draw the icon 247 | dc.DrawIcon(x, y, m_hIcon); 248 | } 249 | else 250 | { 251 | CDialog::OnPaint(); 252 | } 253 | } 254 | 255 | // The system calls this function to obtain the cursor to display while the user drags 256 | // the minimized window. 257 | HCURSOR CGridListCtrlExDlg::OnQueryDragIcon() 258 | { 259 | return static_cast(m_hIcon); 260 | } 261 | 262 | bool CMoureListCtrlGroups::OnEditComplete(int nRow, int nCol, CWnd* pEditor, LV_DISPINFO* pLVDI) 263 | { 264 | bool rc; 265 | 266 | rc = CGridListCtrlGroups::OnEditComplete(nRow, nCol, pEditor, pLVDI); 267 | 268 | if (nCol != 3) 269 | goto errorout; 270 | 271 | if ((pLVDI->item.mask & LVIF_TEXT) && (pLVDI->item.pszText != NULL)) { 272 | 273 | CGridListCtrlExDlg *dlg = (CGridListCtrlExDlg *)GetParent(); 274 | dlg->m_DataModel.UpdateMouseState(nRow, pLVDI->item.pszText); 275 | dlg->m_TickCount += dlg->m_TimeoutSeconds; 276 | } 277 | 278 | errorout: 279 | return rc; 280 | } -------------------------------------------------------------------------------- /Manager/CGridListCtrlExDlg.h: -------------------------------------------------------------------------------- 1 | // CGridListCtrlExDlg.h : header file 2 | // 3 | 4 | #pragma once 5 | 6 | #include "..\CGridListCtrlEx\CGridListCtrlGroups.h" 7 | #include "CListCtrl_DataModel.h" 8 | 9 | 10 | class CMoureListCtrlGroups : public CGridListCtrlGroups 11 | { 12 | public: 13 | virtual bool OnEditComplete(int nRow, int nCol, CWnd* pEditor, LV_DISPINFO* pLVDI); 14 | }; 15 | 16 | // CGridListCtrlExDlg dialog 17 | class CGridListCtrlExDlg : public CDialog 18 | { 19 | // Construction 20 | public: 21 | explicit CGridListCtrlExDlg(CWnd* pParent = NULL); // standard constructor 22 | 23 | // Dialog Data 24 | enum { IDD = IDD_CGRIDLISTCTRLEX_DIALOG }; 25 | 26 | protected: 27 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 28 | 29 | 30 | // Implementation 31 | protected: 32 | HICON m_hIcon; 33 | 34 | // Generated message map functions 35 | virtual BOOL OnInitDialog(); 36 | afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 37 | afx_msg void OnPaint(); 38 | afx_msg void OnTimer(UINT nIDEvent); 39 | 40 | afx_msg HCURSOR OnQueryDragIcon(); 41 | DECLARE_MESSAGE_MAP() 42 | 43 | public: 44 | 45 | int m_TimeoutSeconds; 46 | int m_TickCount; 47 | 48 | CListCtrl_DataModel m_DataModel; 49 | 50 | private: 51 | int m_nStateImageIdx; 52 | 53 | CMoureListCtrlGroups m_ListCtrl; 54 | CImageList m_ImageList; 55 | 56 | CGridListCtrlExDlg(const CGridListCtrlExDlg&); 57 | CGridListCtrlExDlg& operator=(const CGridListCtrlExDlg&); 58 | 59 | VOID ClearListView(); 60 | VOID UpdateListView(); 61 | }; 62 | -------------------------------------------------------------------------------- /Manager/CListCtrl_DataModel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct CListCtrl_DataRecord 7 | { 8 | CListCtrl_DataRecord() 9 | {} 10 | 11 | CListCtrl_DataRecord(const CString& id, const CString& desc, CString state, CString device, PMR_IO_SLOT slot) 12 | :m_Id(id) 13 | ,m_Desc(desc) 14 | ,m_State(state) 15 | ,m_Device(device) 16 | { 17 | m_Slot = slot; 18 | } 19 | 20 | CString m_Desc; 21 | CString m_Id; 22 | CString m_Device; 23 | CString m_State; 24 | PMR_IO_SLOT m_Slot; 25 | 26 | PMR_IO_SLOT GetIoSlot() const 27 | { 28 | return m_Slot; 29 | } 30 | 31 | CString GetCellText(int col, bool title) const 32 | { 33 | switch(col) 34 | { 35 | case 0: { static const CString title0(_T("Mouse Description")); return title ? title0 : m_Id; } 36 | case 1: { static const CString title1(_T("Hardware ID")); return title ? title1 : m_Desc; } 37 | case 2: { static const CString title2(_T("Swap Buttons")); return title ? title2 : m_State; } 38 | case 3: { static const CString title3(_T("Device Object")); return title ? title3 : m_Device; } 39 | default:{ static const CString emptyStr; return emptyStr; } 40 | } 41 | } 42 | 43 | int GetColCount() const { return 4; } 44 | }; 45 | 46 | class CListCtrl_DataModel 47 | { 48 | private: 49 | 50 | vector m_Records; 51 | int m_LookupTime; 52 | int m_RowMultiplier; 53 | 54 | struct mr_io_record *m_ior; 55 | unsigned long m_iol; 56 | 57 | public: 58 | 59 | ~CListCtrl_DataModel() 60 | { 61 | if (m_ior) 62 | delete []m_ior; 63 | } 64 | 65 | CListCtrl_DataModel() 66 | :m_RowMultiplier(0) 67 | ,m_LookupTime(0) 68 | { 69 | m_iol = 128 * 1024; 70 | m_ior = (struct mr_io_record *)(new char[m_iol]); 71 | 72 | InitDataModel(); 73 | } 74 | 75 | int ReadKernelMoure(PMR_IO_RECORD mir, ULONG len) 76 | { 77 | HANDLE h = 0; 78 | DWORD bytes = 0, le; 79 | BOOL rc; 80 | 81 | h = CreateFile( MOURE_DOSDEV, 82 | GENERIC_READ | GENERIC_WRITE, 83 | 0, 84 | NULL, 85 | CREATE_ALWAYS, 86 | FILE_ATTRIBUTE_NORMAL, 87 | NULL); 88 | 89 | if (h == INVALID_HANDLE_VALUE || h == 0) { 90 | le = GetLastError(); 91 | goto errorout; 92 | } 93 | memset(mir, 0, len); 94 | 95 | rc = ReadFile(h, mir, len, &bytes, NULL); 96 | if (!rc) { 97 | le = GetLastError(); 98 | goto errorout; 99 | } 100 | 101 | errorout: 102 | if (h != INVALID_HANDLE_VALUE && h != NULL) 103 | CloseHandle(h); 104 | 105 | return (int) bytes; 106 | } 107 | 108 | int WriteKernelMoure(PMR_IO_RECORD mir, ULONG len) 109 | { 110 | HANDLE h = 0; 111 | DWORD bytes = 0, le; 112 | BOOL rc; 113 | 114 | h = CreateFile( MOURE_DOSDEV, 115 | GENERIC_READ | GENERIC_WRITE, 116 | 0, 117 | NULL, 118 | CREATE_ALWAYS, 119 | FILE_ATTRIBUTE_NORMAL, 120 | NULL); 121 | 122 | if (h == INVALID_HANDLE_VALUE || h == 0) { 123 | le = GetLastError(); 124 | goto errorout; 125 | } 126 | 127 | rc = WriteFile(h, mir, len, &bytes, NULL); 128 | if (!rc) { 129 | le = GetLastError(); 130 | goto errorout; 131 | } 132 | 133 | errorout: 134 | if (h != INVALID_HANDLE_VALUE && h != NULL) 135 | CloseHandle(h); 136 | 137 | return (int) bytes; 138 | } 139 | 140 | int RefreshLists() 141 | { 142 | CString s1, s2, s3, s4; 143 | PWCHAR t1, t2; 144 | ULONG total = MR_IO_REC_SIZE; 145 | 146 | if (!ReadKernelMoure(m_ior, m_iol)) 147 | return 0; 148 | 149 | if (m_ior->mi_magic != MR_IO_MAGIC || 150 | m_ior->mi_length <= MR_IO_REC_SIZE + MR_IO_SLOT_SIZE) { 151 | return 0; 152 | } 153 | 154 | while (total + MR_IO_SLOT_SIZE < m_ior->mi_length) { 155 | 156 | PMR_IO_SLOT slot = (PMR_IO_SLOT)((PUCHAR)m_ior + total); 157 | if (slot->mi_magic != MR_IO_SLOT_MAGIC || 158 | slot->mi_size == 0 || slot->mi_dcb == 0) { 159 | break; 160 | } 161 | 162 | t1 = (PWCHAR)((PUCHAR)slot + slot->mi_desc.me_start); 163 | t2 = (PWCHAR)((PUCHAR)slot + slot->mi_ven.me_start); 164 | s1.Format(_T("%s (%s)"), t1, t2); 165 | 166 | t1 = (PWCHAR)((PUCHAR)slot + slot->mi_id.me_start); 167 | s2.Format(_T("%s"), t1); 168 | 169 | if (slot->mi_state & MR_DEV_STATE_ENABLED) { 170 | if (slot->mi_state & MR_DEV_STATE_PERSIST) 171 | s3 = _T("Persistent"); 172 | else 173 | s3 = _T("Temporary"); 174 | } else { 175 | s3.Empty(); 176 | } 177 | 178 | t1 = (PWCHAR)((PUCHAR)slot + slot->mi_name.me_start); 179 | s4.Format(_T("%s"), t1); 180 | 181 | m_Records.push_back( CListCtrl_DataRecord(s1, s2, s3, s4, slot)); 182 | total += slot->mi_size; 183 | } 184 | 185 | return m_Records.size(); 186 | } 187 | 188 | int UpdateMouseState(int row, CString state) 189 | { 190 | PMR_IO_SLOT slot, ts; 191 | PMR_IO_RECORD mir = NULL; 192 | ULONG len = 0; 193 | int rc = 0; 194 | 195 | slot = GetIoSlot(row); 196 | if (NULL == slot) 197 | goto errorout; 198 | 199 | len = MR_IO_REC_SIZE + slot->mi_size; 200 | mir = (PMR_IO_RECORD) (new char[len]); 201 | if (NULL == mir) 202 | goto errorout; 203 | 204 | memset(mir, 0, len); 205 | mir->mi_magic = MR_IO_MAGIC; 206 | mir->mi_length = len; 207 | mir->mi_nslots = 1; 208 | ts = &mir->mi_slot[0]; 209 | memcpy(ts, slot, slot->mi_size); 210 | 211 | ts->mi_cmd = MR_IO_CMD_SET; 212 | ts->mi_state = 0; 213 | if (state.IsEmpty()) { 214 | } else if (state == _T("Persistent")) { 215 | ts->mi_state |= MR_DEV_STATE_ENABLED | 216 | MR_DEV_STATE_PERSIST; 217 | } else if (state == _T("Temporary")) { 218 | ts->mi_state |= MR_DEV_STATE_ENABLED; 219 | } 220 | 221 | /* update to kernel module */ 222 | rc = WriteKernelMoure(mir, len); 223 | 224 | /* update registry for next booting */ 225 | 226 | errorout: 227 | if (mir) 228 | delete []mir; 229 | return rc; 230 | } 231 | 232 | void InitDataModel() 233 | { 234 | m_Records.clear(); 235 | 236 | if (!RefreshLists()) 237 | return; 238 | 239 | if (m_RowMultiplier > 1) 240 | { 241 | vector rowset(m_Records); 242 | m_Records.reserve((m_RowMultiplier-1) * rowset.size()); 243 | for(int i = 0 ; i < m_RowMultiplier ; ++i) 244 | { 245 | m_Records.insert(m_Records.end(), rowset.begin(), rowset.end()); 246 | } 247 | } 248 | } 249 | 250 | CString GetCellText(size_t lookupId, int col) const 251 | { 252 | if (lookupId >= m_Records.size()) 253 | { 254 | static CString oob(_T("Out of Bound")); 255 | return oob; 256 | } 257 | // How many times should we search sequential for the row ? 258 | for(int i=0; i < m_LookupTime; ++i) 259 | { 260 | for(size_t rowId = 0; rowId < m_Records.size(); ++rowId) 261 | { 262 | if (rowId==lookupId) 263 | break; 264 | } 265 | } 266 | return m_Records.at(lookupId).GetCellText(col, false); 267 | } 268 | 269 | PMR_IO_SLOT GetIoSlot(size_t rowId) const 270 | { 271 | if (rowId >= m_Records.size()) 272 | { 273 | return NULL; 274 | } 275 | 276 | return m_Records.at(rowId).GetIoSlot(); 277 | } 278 | 279 | size_t GetRowIds() const { return m_Records.size(); } 280 | int GetColCount() const { return CListCtrl_DataRecord().GetColCount(); } 281 | CString GetColTitle(int col) const { return CListCtrl_DataRecord().GetCellText(col, true); } 282 | 283 | vector& GetRecords() { return m_Records; } 284 | void SetLookupTime(int lookupTimes) { m_LookupTime = lookupTimes; } 285 | void SetRowMultiplier(int multiply) { if (m_RowMultiplier != multiply ) { m_RowMultiplier = multiply; InitDataModel(); } } 286 | }; 287 | -------------------------------------------------------------------------------- /Manager/MAKEFILE: -------------------------------------------------------------------------------- 1 | BUILD_ALLOW_COMPILER_WARNINGS=1 2 | BUILD_ALLOW_LINKER_WARNINGS=1 3 | 4 | # 5 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 6 | # file to this component. This file merely indirects to the real make file 7 | # that is shared by all the driver components of the Windows NT DDK 8 | # 9 | 10 | !INCLUDE $(NTMAKEENV)\makefile.def 11 | 12 | -------------------------------------------------------------------------------- /Manager/Manager.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 32 | 35 | 38 | 41 | 44 | 53 | 73 | 76 | 81 | 84 | 101 | 104 | 107 | 110 | 115 | 118 | 121 | 124 | 125 | 135 | 138 | 141 | 144 | 147 | 156 | 172 | 175 | 180 | 183 | 200 | 203 | 206 | 209 | 214 | 217 | 220 | 223 | 224 | 225 | 226 | 227 | 228 | 231 | 232 | 235 | 236 | 239 | 240 | 243 | 244 | 247 | 248 | 251 | 252 | 255 | 256 | 259 | 260 | 263 | 264 | 267 | 268 | 269 | 270 | 274 | 275 | 276 | -------------------------------------------------------------------------------- /Manager/Moure.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | Moure 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Manager/SOURCES: -------------------------------------------------------------------------------- 1 | TARGETNAME=Moure 2 | TARGETPATH=obj 3 | TARGETTYPE=PROGRAM 4 | 5 | 6 | C_DEFINES=/DUSE_MFC6_WITH_ATL7=1 /D_WDK_BUILD=1 $(C_DEFINES) 7 | INCLUDES= .;..\Filter\; \ 8 | $(DDK_INC_PATH);$(SDK_INC_PATH); $(MFC_INC_PATH); \ 9 | $(MFC_INC_PATH)\..\atlmfc;$(INCLUDES) 10 | TARGETLIBS= ..\CGridListCtrlEx\obj$(BUILD_ALT_DIR)\*\CGridListCtrlEx.lib \ 11 | $(SDK_LIB_PATH)\comctl32.lib 12 | 13 | USE_STL=1 14 | STL_VER=70 15 | 16 | MSC_STDCALL=0 17 | 386_STDCALL=0 18 | 19 | USE_MFCUNICODE=1 20 | PRECOMPILED_CXX=1 21 | PRECOMPILED_INCLUDE=stdafx.h 22 | 23 | SXS_MANIFEST=Moure.exe.manifest 24 | SXS_ASSEMBLY_NAME=Moure 25 | SXS_ASSEMBLY_VERSION=1.1 26 | SXS_ASSEMBLY_LANGUAGE_INDEPENDENT=1 27 | SXS_MANIFEST_IN_RESOURCES=1 28 | 29 | SOURCES= CGridListCtrlExApp.cpp CGridListCtrlExDlg.cpp CGridListCtrlEx.rc 30 | -------------------------------------------------------------------------------- /Manager/res/CGridListCtrlEx.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Your app description here 10 | 11 | 12 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Manager/res/CGridListCtrlEx.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/Manager/res/CGridListCtrlEx.ico -------------------------------------------------------------------------------- /Manager/res/CGridListCtrlEx.rc2: -------------------------------------------------------------------------------- 1 | // 2 | // CGridListCtrlEx.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 | -------------------------------------------------------------------------------- /Manager/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by CGridListCtrlEx.rc 4 | // 5 | #define IDM_ABOUTBOX 0x0010 6 | #define IDD_ABOUTBOX 100 7 | #define IDS_ABOUTBOX 101 8 | #define IDD_CGRIDLISTCTRLEX_DIALOG 102 9 | #define IDR_MAINFRAME 128 10 | #define IDI_FLGDEN 132 11 | #define IDI_FLGFRAN 133 12 | #define IDI_FLGGERM 134 13 | #define IDI_FLGGREEC 135 14 | #define IDI_FLGSPAIN 136 15 | #define IDI_FLGSWED 137 16 | #define IDC_LIST1 1000 17 | 18 | // Next default values for new objects 19 | // 20 | #ifdef APSTUDIO_INVOKED 21 | #ifndef APSTUDIO_READONLY_SYMBOLS 22 | #define _APS_NEXT_RESOURCE_VALUE 138 23 | #define _APS_NEXT_COMMAND_VALUE 32771 24 | #define _APS_NEXT_CONTROL_VALUE 1001 25 | #define _APS_NEXT_SYMED_VALUE 101 26 | #endif 27 | #endif 28 | -------------------------------------------------------------------------------- /Manager/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // CGridListCtrlEx.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 | -------------------------------------------------------------------------------- /Manager/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 | #if _MSC_VER >= 1400 8 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 9 | #endif 10 | 11 | #ifndef WIN32_LEAN_AND_MEAN 12 | #define WIN32_LEAN_AND_MEAN 13 | #endif 14 | 15 | #ifndef VC_EXTRALEAN 16 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers (AFXV_W32.h) 17 | #endif 18 | 19 | #ifndef NO_STRICT 20 | #ifndef STRICT 21 | #define STRICT 1 22 | #endif 23 | #endif 24 | 25 | #if _MSC_VER < 1300 26 | // If using VC6 without platform SDK 27 | #ifndef WINVER 28 | #define WINVER 0x0500 29 | #endif 30 | #ifndef _WIN32_WINNT 31 | #define _WIN32_WINNT 0x0500 32 | #endif 33 | #ifndef _WIN32_WINDOWS 34 | #define _WIN32_WINDOWS 0x0500 35 | #endif 36 | #ifndef _WIN32_IE 37 | #define _WIN32_IE 0x0400 38 | #endif 39 | #endif 40 | 41 | // Modify the following defines if you have to target a platform prior to the ones specified below. 42 | // Refer to MSDN for the latest info on corresponding values for different platforms. 43 | #ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. 44 | #define WINVER 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. 45 | #endif 46 | 47 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. 48 | #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. 49 | #endif 50 | 51 | #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. 52 | #define _WIN32_WINDOWS 0x0501 // Change this to the appropriate value to target Windows Me or later. 53 | #endif 54 | 55 | #ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. 56 | #define _WIN32_IE 0x0501 // Change this to the appropriate value to target IE 5.0 or later. 57 | #endif 58 | 59 | #ifndef UNICODE 60 | #define CGRIDLISTCTRLEX_GROUPMODE 61 | #endif 62 | 63 | #ifdef _AFXEXT 64 | #define CGRIDLISTCTRLEX_AFX_EXT // Export/Import as MFC Extension DLL (Remember to use this define when including headers from DLL) 65 | #endif 66 | 67 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 68 | 69 | #pragma warning( disable:4514 ) // warning C4514: unreferenced inline function has been remove 70 | #pragma warning( disable:4710 ) // warning C4710: function not inlined 71 | #pragma warning( disable:4711 ) // warning C4711: function selected for automatic inline expansion 72 | #pragma warning( disable:4820 ) // warning C4820: X bytes padding added after data member 73 | 74 | #pragma warning( push ) 75 | #pragma warning( disable:4548 ) // warning C4548: expression before comma has no effect; expected expression with side-effect 76 | #pragma warning( disable:4812 ) // warning C4812: obsolete declaration style: please use '_CIP<_Interface,_IID>::_CIP' instead 77 | #pragma warning( disable:4996 ) // warning C4996: This function or variable may be unsafe. 78 | #pragma warning( disable:4005 ) // warning C4005: '_WIN32_WINDOWS' : macro redefinition 79 | #pragma warning( disable:4668 ) // warning C4668: '__midl' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' 80 | #pragma warning( disable:4820 ) // warning C4820: X bytes padding added after data member 81 | #pragma warning( disable:4619 ) // warning C4619: #pragma warning : there is no warning number 82 | #pragma warning( disable:4625 ) // warning C4625: copy constructor could not be generated because a base class copy constructor is inaccessible 83 | #pragma warning( disable:4626 ) // warning C4626: assignment operator could not be generated because a base class assignment operator is inaccessible 84 | #pragma warning( disable:4365 ) // warning C4365: '=' : conversion from 'int' to 'size_t', signed/unsigned mismatch 85 | #pragma warning( disable:4244 ) // warning C4244: 'return' : conversion from 'const time_t' to 'LONG_PTR', possible loss of data 86 | #pragma warning( disable:4263 ) // warning C4263: member function does not override any base class virtual member function 87 | #pragma warning( disable:4264 ) // warning C4264: no override available for virtual member function from base; function is hidden 88 | #pragma warning( disable:4917 ) // warning C4917: a GUID can only be associated with a class, interface or namespace 89 | #pragma warning( disable:4555 ) // warning C4555: expression has no effect; expected expression with side-effect 90 | #pragma warning( disable:4640 ) // warning C4640: construction of local static object is not thread-safe 91 | #pragma warning( disable:4571 ) // warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught 92 | #pragma warning( disable:4987 ) // warning C4987: nonstandard extension used: 'throw (...)' 93 | #pragma warning( disable:4266 ) // warning C4266: 'BOOL CException::GetErrorMessage(LPTSTR,UINT,PUINT)': no override available for virtual member function from base 'CException'; function is hidden 94 | 95 | 96 | #include // MFC core and standard components 97 | #include // MFC extensions 98 | 99 | #ifndef _AFX_NO_OLE_SUPPORT 100 | #include // MFC Automation classes 101 | #include // MFC support for Internet Explorer 4 Common Controls 102 | #endif // _AFX_NO_OLE_SUPPORT 103 | 104 | #ifndef _AFX_NO_AFXCMN_SUPPORT 105 | #include // MFC support for Windows Common Controls 106 | #endif // _AFX_NO_AFXCMN_SUPPORT 107 | 108 | #include 109 | 110 | #pragma warning( pop ) 111 | 112 | #include 113 | #include 114 | #include 115 | 116 | using namespace std; -------------------------------------------------------------------------------- /Moure.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Filter", "Filter\Filter.vcproj", "{2328F787-71B4-408B-8E10-B7A95BF9A110}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Manager", "Manager\Manager.vcproj", "{F0E304B5-AF20-49F7-8183-5994C6EA889D}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CGridListCtrlEx", "CGridListCtrlEx\CGridListCtrlEx.vcproj", "{A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}" 9 | EndProject 10 | Global 11 | GlobalSection(SourceCodeControl) = preSolution 12 | SccNumberOfProjects = 4 13 | SccProjectUniqueName0 = Filter\\Filter.vcproj 14 | SccProjectName0 = Filter 15 | SccLocalPath0 = Filter 16 | CanCheckoutShared = true 17 | SccProjectName1 = Moure 18 | SccLocalPath1 = . 19 | SccProvider1 = MSSCCI:Perforce\u0020P4\u0020SCM 20 | CanCheckoutShared = true 21 | SccProjectUniqueName2 = CGridListCtrlEx\\CGridListCtrlEx.vcproj 22 | SccLocalPath2 = . 23 | CanCheckoutShared = true 24 | SccProjectFilePathRelativizedFromConnection2 = CGridListCtrlEx\\ 25 | SccProjectUniqueName3 = Manager\\Manager.vcproj 26 | SccLocalPath3 = . 27 | CanCheckoutShared = true 28 | SccProjectFilePathRelativizedFromConnection3 = Manager\\ 29 | EndGlobalSection 30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 31 | Debug|Win32 = Debug|Win32 32 | Release|Win32 = Release|Win32 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {2328F787-71B4-408B-8E10-B7A95BF9A110}.Debug|Win32.ActiveCfg = Debug|Win32 36 | {2328F787-71B4-408B-8E10-B7A95BF9A110}.Debug|Win32.Build.0 = Debug|Win32 37 | {2328F787-71B4-408B-8E10-B7A95BF9A110}.Release|Win32.ActiveCfg = Release|Win32 38 | {2328F787-71B4-408B-8E10-B7A95BF9A110}.Release|Win32.Build.0 = Release|Win32 39 | {F0E304B5-AF20-49F7-8183-5994C6EA889D}.Debug|Win32.ActiveCfg = Debug|Win32 40 | {F0E304B5-AF20-49F7-8183-5994C6EA889D}.Debug|Win32.Build.0 = Debug|Win32 41 | {F0E304B5-AF20-49F7-8183-5994C6EA889D}.Release|Win32.ActiveCfg = Release|Win32 42 | {F0E304B5-AF20-49F7-8183-5994C6EA889D}.Release|Win32.Build.0 = Release|Win32 43 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Debug|Win32.ActiveCfg = Debug|Win32 44 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Debug|Win32.Build.0 = Debug|Win32 45 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Release|Win32.ActiveCfg = Release|Win32 46 | {A0F8D7E6-2F18-4472-8434-C07BD9C15AB6}.Release|Win32.Build.0 = Release|Win32 47 | EndGlobalSection 48 | GlobalSection(SolutionProperties) = preSolution 49 | HideSolutionNode = FALSE 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Introduction 3 | ------------ 4 | 5 | Moure is a small utility to swap your mouse buttons. As we know Windows 6 | system already supports mouse buttons switching, but it has the following 7 | limitations: 8 | 1) All mouses including touchpad are to be swapped. 9 | 2) In remote desktop (mstsc), will turn back to what it's designed. 10 | 11 | Moure overcomes these 2 limitations. It enables you to only swap buttons 12 | for a particular one or any specified mouses. Other mouse devices or 13 | your touchpad are left unchanged. 14 | 15 | Moure remembers your settings in registry, and it automatically reloads 16 | after system booting. 17 | 18 | 19 | Supported OS 20 | ------------ 21 | 22 | Windows XP and later 23 | 24 | 25 | Story 26 | ----- 27 | 28 | Mostly I'm using my left hand to control the mouse (designed for right 29 | hand). Recently, trying to relieve my left hand from pains of carpal 30 | tunnel syndrome, I bought a new left-hand mouse (Minicute EZ2), then 31 | got troubles to get accustomed to the left & right confusions. 32 | 33 | I'm not a guy of IFIXIT-style, just cann't weld any jump wires. But 34 | as a software engineer, I can make software work as requested, even 35 | weirdly. Then moure was out, proving again the proverb: 36 | 37 | -- if all you have is a hammer, everything looks like a nail -- 38 | 39 | 40 | Development Guides 41 | ------------------- 42 | 43 | Project website: https://github.com/matt-wu/Moure 44 | Requirements: VS2008 and WDK 45 | 46 | Moure is a kernel mouse class filter driver for Windows. So besides 47 | buttons swapping, it can do everything upon HID events for mouses. 48 | 49 | Thanks to Rolf Kristensen for his CGridListCtrlEx project: 50 | https://github.com/snakefoot/cgridlistctrlex 51 | 52 | 53 | Bugs or issues 54 | -------------- 55 | 56 | Matt Wu 57 | http://www.ext2fsd.com 58 | -------------------------------------------------------------------------------- /Setup/setup.iss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/Setup/setup.iss -------------------------------------------------------------------------------- /Snapshots/Moure-ss1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/Snapshots/Moure-ss1.jpg -------------------------------------------------------------------------------- /Snapshots/Moure-ss2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/Snapshots/Moure-ss2.jpg -------------------------------------------------------------------------------- /bin/Moure-1.0.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/bin/Moure-1.0.exe -------------------------------------------------------------------------------- /bin/Moure-1.1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/bin/Moure-1.1.exe -------------------------------------------------------------------------------- /bin/Moure-1.2.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/bin/Moure-1.2.exe -------------------------------------------------------------------------------- /bin/Moure-1.3.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matt-wu/Moure/37a44e90e36b21e666929420bc818547dac7a0a5/bin/Moure-1.3.exe --------------------------------------------------------------------------------