├── version2.27.txt ├── .gitignore ├── GridCell.h ├── GridCellBase.h ├── docs └── assets │ ├── gridctrl.gif │ ├── griddemo.png │ └── gridviewdemo.png ├── Experimental Upgrades ├── GridCellLite.h ├── TitleTip.h ├── InPlaceList.h ├── GridCellLite.cpp ├── InPlaceList.cpp └── TitleTip.cpp ├── README ├── project ├── stdafx.cpp ├── targetver.h ├── stdafx.h ├── GridCtrl.sln ├── GridCtrl.vcxproj.filters └── GridCtrl.vcxproj ├── InPlaceEdit.h ├── GridDropTarget.h ├── TitleTip.h ├── MemDC.h ├── GridDropTarget.cpp ├── CellRange.h ├── GridCell.cpp ├── InPlaceEdit.cpp ├── TitleTip.cpp ├── LICENSE ├── GridCellBase.cpp └── GridCtrl.h /version2.27.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cs 2 | .vs 3 | *.aps 4 | *.user 5 | *.tmp 6 | Debug 7 | Release 8 | -------------------------------------------------------------------------------- /GridCell.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisMaunder/MFC-GridCtrl/HEAD/GridCell.h -------------------------------------------------------------------------------- /GridCellBase.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisMaunder/MFC-GridCtrl/HEAD/GridCellBase.h -------------------------------------------------------------------------------- /docs/assets/gridctrl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisMaunder/MFC-GridCtrl/HEAD/docs/assets/gridctrl.gif -------------------------------------------------------------------------------- /docs/assets/griddemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisMaunder/MFC-GridCtrl/HEAD/docs/assets/griddemo.png -------------------------------------------------------------------------------- /docs/assets/gridviewdemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisMaunder/MFC-GridCtrl/HEAD/docs/assets/gridviewdemo.png -------------------------------------------------------------------------------- /Experimental Upgrades/GridCellLite.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChrisMaunder/MFC-GridCtrl/HEAD/Experimental Upgrades/GridCellLite.h -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ## GridCtrl 2 | 3 | MFC Library for Grid control 4 | 5 | Original project: https://www.codeproject.com/Articles/8/MFC-Grid-control-2-27 6 | 7 | Slightly fixed to working on VS2017 8 | -------------------------------------------------------------------------------- /project/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GridCtrl.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /project/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /project/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 12 | 13 | #include // MFC core and standard components 14 | #include // MFC extensions 15 | #ifndef _AFX_NO_AFXCMN_SUPPORT 16 | #include // MFC support for Windows Common Controls 17 | #endif // _AFX_NO_AFXCMN_SUPPORT 18 | 19 | 20 | // TODO: reference additional headers your program requires here 21 | -------------------------------------------------------------------------------- /project/GridCtrl.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2035 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GridCtrl", "GridCtrl.vcxproj", "{A8267B22-5A84-42D0-8687-9303B193B6C9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Debug|x64.ActiveCfg = Debug|x64 17 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Debug|x64.Build.0 = Debug|x64 18 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Debug|x86.ActiveCfg = Debug|Win32 19 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Debug|x86.Build.0 = Debug|Win32 20 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Release|x64.ActiveCfg = Release|x64 21 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Release|x64.Build.0 = Release|x64 22 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Release|x86.ActiveCfg = Release|Win32 23 | {A8267B22-5A84-42D0-8687-9303B193B6C9}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {62BCD8B2-7F22-4B79-91FC-B6A036906F5C} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Experimental Upgrades/TitleTip.h: -------------------------------------------------------------------------------- 1 | #if !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_) 2 | #define AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_ 3 | 4 | #if _MSC_VER >= 1000 5 | #pragma once 6 | #endif // _MSC_VER >= 1000 7 | // TitleTip.h : header file 8 | // 9 | 10 | #define TITLETIP_CLASSNAME _T("ZTitleTip") 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | // CTitleTip window 14 | 15 | class CTitleTip : public CWnd 16 | { 17 | // Construction 18 | public: 19 | CTitleTip(); 20 | virtual ~CTitleTip(); 21 | virtual BOOL Create( CWnd *pParentWnd); 22 | 23 | // Attributes 24 | public: 25 | 26 | // Operations 27 | public: 28 | void Show(CRect rectTitle, LPCTSTR lpszTitleText, 29 | int xoffset = 0, int nMaxChars = -1, 30 | LPRECT lpHoverRect = NULL, LPLOGFONT lpLogFont = NULL, 31 | DWORD dwFormat = DT_LEFT|DT_NOCLIP|DT_EDITCONTROL|DT_NOPREFIX|DT_WORDBREAK); 32 | void Hide(); 33 | 34 | // Overrides 35 | // ClassWizard generated virtual function overrides 36 | //{{AFX_VIRTUAL(CTitleTip) 37 | public: 38 | virtual BOOL PreTranslateMessage(MSG* pMsg); 39 | //}}AFX_VIRTUAL 40 | 41 | // Implementation 42 | public: 43 | 44 | protected: 45 | CWnd *m_pParentWnd; 46 | CRect m_rectTitle; 47 | CRect m_rectHover; 48 | CRect m_rectDisplay; 49 | CString m_strTitle; // for use in OnPaint() 50 | DWORD m_dwFormat; 51 | 52 | // Generated message map functions 53 | protected: 54 | //{{AFX_MSG(CTitleTip) 55 | afx_msg void OnMouseMove(UINT nFlags, CPoint point); 56 | afx_msg void OnPaint(); 57 | afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 58 | afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 59 | //}}AFX_MSG 60 | DECLARE_MESSAGE_MAP() 61 | }; 62 | 63 | ///////////////////////////////////////////////////////////////////////////// 64 | 65 | //{{AFX_INSERT_LOCATION}} 66 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 67 | 68 | #endif // !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_) 69 | -------------------------------------------------------------------------------- /project/GridCtrl.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | -------------------------------------------------------------------------------- /InPlaceEdit.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////// 2 | // InPlaceEdit.h : header file 3 | // 4 | // MFC Grid Control - inplace editing class 5 | // 6 | // Written by Chris Maunder 7 | // Copyright (c) 1998-2005. All Rights Reserved. 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name and all copyright 13 | // notices remains intact. 14 | // 15 | // An email letting me know how you are using it would be nice as well. 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // For use with CGridCtrl v2.10+ 22 | // 23 | ////////////////////////////////////////////////////////////////////// 24 | 25 | #if !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_) 26 | #define AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_ 27 | 28 | #if _MSC_VER >= 1000 29 | #pragma once 30 | #endif // _MSC_VER >= 1000 31 | 32 | class CInPlaceEdit : public CEdit 33 | { 34 | // Construction 35 | public: 36 | CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, 37 | int nRow, int nColumn, CString sInitText, UINT nFirstChar); 38 | 39 | // Attributes 40 | public: 41 | 42 | // Operations 43 | public: 44 | void EndEdit(); 45 | 46 | // Overrides 47 | // ClassWizard generated virtual function overrides 48 | //{{AFX_VIRTUAL(CInPlaceEdit) 49 | public: 50 | virtual BOOL PreTranslateMessage(MSG* pMsg); 51 | protected: 52 | virtual void PostNcDestroy(); 53 | //}}AFX_VIRTUAL 54 | 55 | // Implementation 56 | public: 57 | virtual ~CInPlaceEdit(); 58 | 59 | // Generated message map functions 60 | protected: 61 | //{{AFX_MSG(CInPlaceEdit) 62 | afx_msg void OnKillFocus(CWnd* pNewWnd); 63 | afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); 64 | afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 65 | afx_msg UINT OnGetDlgCode(); 66 | //}}AFX_MSG 67 | DECLARE_MESSAGE_MAP() 68 | 69 | private: 70 | int m_nRow; 71 | int m_nColumn; 72 | CString m_sInitText; 73 | UINT m_nLastChar; 74 | BOOL m_bExitOnArrows; 75 | CRect m_Rect; 76 | }; 77 | 78 | ///////////////////////////////////////////////////////////////////////////// 79 | 80 | //{{AFX_INSERT_LOCATION}} 81 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 82 | 83 | #endif // !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_) 84 | -------------------------------------------------------------------------------- /GridDropTarget.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////// 2 | // GridDropTarget.h : header file 3 | // 4 | // MFC Grid Control - Drag/Drop target implementation 5 | // 6 | // Written by Chris Maunder 7 | // Copyright (c) 1998-2005. All Rights Reserved. 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name and all copyright 13 | // notices remains intact. 14 | // 15 | // An email letting me know how you are using it would be nice as well. 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // For use with CGridCtrl v2.10+ 22 | // 23 | ////////////////////////////////////////////////////////////////////// 24 | 25 | #if !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_) 26 | #define AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_ 27 | 28 | #if _MSC_VER >= 1000 29 | #pragma once 30 | #endif // _MSC_VER >= 1000 31 | 32 | 33 | #include 34 | 35 | class CGridCtrl; 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | // CGridDropTarget command target 39 | 40 | class CGridDropTarget : public COleDropTarget 41 | { 42 | public: 43 | CGridDropTarget(); 44 | virtual ~CGridDropTarget(); 45 | 46 | // Attributes 47 | public: 48 | CGridCtrl* m_pGridCtrl; 49 | BOOL m_bRegistered; 50 | 51 | // Operations 52 | public: 53 | BOOL Register(CGridCtrl *pGridCtrl); 54 | virtual void Revoke(); 55 | 56 | BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); 57 | DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 58 | void OnDragLeave(CWnd* pWnd); 59 | DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 60 | DROPEFFECT OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point); 61 | 62 | // Overrides 63 | // ClassWizard generated virtual function overrides 64 | //{{AFX_VIRTUAL(CGridDropTarget) 65 | //}}AFX_VIRTUAL 66 | 67 | // Implementation 68 | protected: 69 | 70 | // Generated message map functions 71 | //{{AFX_MSG(CGridDropTarget) 72 | //}}AFX_MSG 73 | 74 | DECLARE_MESSAGE_MAP() 75 | }; 76 | 77 | ///////////////////////////////////////////////////////////////////////////// 78 | 79 | //{{AFX_INSERT_LOCATION}} 80 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 81 | 82 | #endif // !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_) 83 | -------------------------------------------------------------------------------- /TitleTip.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // Titletip.h : header file 3 | // 4 | // MFC Grid Control - cell titletips 5 | // 6 | // Written by Chris Maunder 7 | // Copyright (c) 1998-2005. All Rights Reserved. 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name and all copyright 13 | // notices remains intact. 14 | // 15 | // An email letting me know how you are using it would be nice as well. 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // For use with CGridCtrl v2.10+ 22 | // 23 | ////////////////////////////////////////////////////////////////////// 24 | 25 | #if !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_) 26 | #define AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_ 27 | 28 | #if _MSC_VER >= 1000 29 | #pragma once 30 | #endif // _MSC_VER >= 1000 31 | 32 | #define TITLETIP_CLASSNAME _T("ZTitleTip") 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | // CTitleTip window 36 | 37 | class CTitleTip : public CWnd 38 | { 39 | // Construction 40 | public: 41 | CTitleTip(); 42 | virtual ~CTitleTip(); 43 | virtual BOOL Create( CWnd *pParentWnd); 44 | 45 | // Attributes 46 | public: 47 | void SetParentWnd(CWnd* pParentWnd) { m_pParentWnd = pParentWnd; } 48 | CWnd* GetParentWnd() { return m_pParentWnd; } 49 | 50 | // Operations 51 | public: 52 | void Show(CRect rectTitle, LPCTSTR lpszTitleText, 53 | int xoffset = 0, LPRECT lpHoverRect = NULL, 54 | const LOGFONT* lpLogFont = NULL, 55 | COLORREF crTextClr = CLR_DEFAULT, COLORREF crBackClr = CLR_DEFAULT); 56 | void Hide(); 57 | 58 | // Overrides 59 | // ClassWizard generated virtual function overrides 60 | //{{AFX_VIRTUAL(CTitleTip) 61 | public: 62 | virtual BOOL PreTranslateMessage(MSG* pMsg); 63 | virtual BOOL DestroyWindow(); 64 | //}}AFX_VIRTUAL 65 | 66 | // Implementation 67 | protected: 68 | CWnd *m_pParentWnd; 69 | CRect m_rectTitle; 70 | CRect m_rectHover; 71 | DWORD m_dwLastLButtonDown; 72 | DWORD m_dwDblClickMsecs; 73 | BOOL m_bCreated; 74 | 75 | // Generated message map functions 76 | protected: 77 | //{{AFX_MSG(CTitleTip) 78 | afx_msg void OnMouseMove(UINT nFlags, CPoint point); 79 | //}}AFX_MSG 80 | DECLARE_MESSAGE_MAP() 81 | }; 82 | 83 | ///////////////////////////////////////////////////////////////////////////// 84 | //{{AFX_INSERT_LOCATION}} 85 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 86 | 87 | #endif // !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_) 88 | -------------------------------------------------------------------------------- /MemDC.h: -------------------------------------------------------------------------------- 1 | #if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_) 2 | #define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_ 3 | 4 | #if _MSC_VER >= 1000 5 | #pragma once 6 | #endif // _MSC_VER >= 1000 7 | // MemDC.h : header file 8 | // 9 | 10 | ////////////////////////////////////////////////// 11 | // CMemDC - memory DC 12 | // 13 | // Author: Keith Rule 14 | // Email: keithr@europa.com 15 | // Copyright 1996-1997, Keith Rule 16 | // 17 | // You may freely use or modify this code provided this 18 | // Copyright is included in all derived versions. 19 | // 20 | // History - 10/3/97 Fixed scrolling bug. 21 | // Added print support. 22 | // 25 feb 98 - fixed minor assertion bug 23 | // 24 | // This class implements a memory Device Context 25 | 26 | class CMemDC : public CDC 27 | { 28 | public: 29 | 30 | // constructor sets up the memory DC 31 | CMemDC(CDC* pDC) : CDC() 32 | { 33 | ASSERT(pDC != NULL); 34 | 35 | m_pDC = pDC; 36 | m_pOldBitmap = NULL; 37 | #ifndef _WIN32_WCE_NO_PRINTING 38 | m_bMemDC = !pDC->IsPrinting(); 39 | #else 40 | m_bMemDC = FALSE; 41 | #endif 42 | 43 | if (m_bMemDC) // Create a Memory DC 44 | { 45 | pDC->GetClipBox(&m_rect); 46 | CreateCompatibleDC(pDC); 47 | m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); 48 | m_pOldBitmap = SelectObject(&m_bitmap); 49 | #ifndef _WIN32_WCE 50 | SetWindowOrg(m_rect.left, m_rect.top); 51 | #endif 52 | // EFW - Bug fix - Fill background in case the user has overridden 53 | // WM_ERASEBKGND. We end up with garbage otherwise. 54 | // CJM - moved to fix a bug in the fix. 55 | FillSolidRect(m_rect, pDC->GetBkColor()); 56 | } 57 | else // Make a copy of the relevent parts of the current DC for printing 58 | { 59 | #if !defined(_WIN32_WCE) || ((_WIN32_WCE > 201) && !defined(_WIN32_WCE_NO_PRINTING)) 60 | m_bPrinting = pDC->m_bPrinting; 61 | #endif 62 | m_hDC = pDC->m_hDC; 63 | m_hAttribDC = pDC->m_hAttribDC; 64 | } 65 | 66 | } 67 | 68 | // Destructor copies the contents of the mem DC to the original DC 69 | ~CMemDC() 70 | { 71 | if (m_bMemDC) 72 | { 73 | // Copy the offscreen bitmap onto the screen. 74 | m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), 75 | this, m_rect.left, m_rect.top, SRCCOPY); 76 | 77 | //Swap back the original bitmap. 78 | SelectObject(m_pOldBitmap); 79 | } else { 80 | // All we need to do is replace the DC with an illegal value, 81 | // this keeps us from accidently deleting the handles associated with 82 | // the CDC that was passed to the constructor. 83 | m_hDC = m_hAttribDC = NULL; 84 | } 85 | } 86 | 87 | // Allow usage as a pointer 88 | CMemDC* operator->() {return this;} 89 | 90 | // Allow usage as a pointer 91 | operator CMemDC*() {return this;} 92 | 93 | private: 94 | CBitmap m_bitmap; // Offscreen bitmap 95 | CBitmap* m_pOldBitmap; // bitmap originally found in CMemDC 96 | CDC* m_pDC; // Saves CDC passed in constructor 97 | CRect m_rect; // Rectangle of drawing area. 98 | BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. 99 | }; 100 | 101 | ///////////////////////////////////////////////////////////////////////////// 102 | 103 | //{{AFX_INSERT_LOCATION}} 104 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 105 | 106 | #endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_) 107 | -------------------------------------------------------------------------------- /Experimental Upgrades/InPlaceList.h: -------------------------------------------------------------------------------- 1 | #if !defined(AFX_INPLACELIST_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_) 2 | #define AFX_INPLACELIST_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_ 3 | 4 | #if _MSC_VER >= 1000 5 | #pragma once 6 | #endif // _MSC_VER >= 1000 7 | 8 | ///////////////////////////////////////////////////////////////////////////// 9 | // InPlaceList.h : header file 10 | // 11 | // Written by Chris Maunder 12 | // Copyright (c) 1998-2000. All Rights Reserved. 13 | // 14 | // The code contained in this file is based on the original 15 | // CInPlaceList from http://www.codeguru.com/listview 16 | // 17 | // This code may be used in compiled form in any way you desire. This 18 | // file may be redistributed unmodified by any means PROVIDING it is 19 | // not sold for profit without the authors written consent, and 20 | // providing that this notice and the authors name is included. If 21 | // the source code in this file is used in any commercial application 22 | // then acknowledgement must be made to the author of this file 23 | // (in whatever form you wish). 24 | // 25 | // This file is provided "as is" with no expressed or implied warranty. 26 | // The author accepts no liability for any damage/loss of business that 27 | // this product may cause. 28 | // 29 | // Expect bugs! 30 | // 31 | // Please use and enjoy. Please let me know of any bugs/mods/improvements 32 | // that you have found/implemented and I will fix/incorporate them into this 33 | // file. 34 | // 35 | ///////////////////////////////////////////////////////////////////////////// 36 | 37 | #define IDC_COMBOEDIT 1001 38 | 39 | ///////////////////////////////////////////////////////////////////////////// 40 | // CComboEdit window 41 | 42 | class CComboEdit : public CEdit 43 | { 44 | // Construction 45 | public: 46 | CComboEdit(); 47 | 48 | // Attributes 49 | public: 50 | 51 | // Operations 52 | public: 53 | 54 | // Overrides 55 | // ClassWizard generated virtual function overrides 56 | //{{AFX_VIRTUAL(CComboEdit) 57 | virtual BOOL PreTranslateMessage(MSG* pMsg); 58 | //}}AFX_VIRTUAL 59 | 60 | // Implementation 61 | public: 62 | virtual ~CComboEdit(); 63 | 64 | // Generated message map functions 65 | protected: 66 | //{{AFX_MSG(CComboEdit) 67 | afx_msg void OnKillFocus(CWnd* pNewWnd); 68 | afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 69 | afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); 70 | //}}AFX_MSG 71 | 72 | DECLARE_MESSAGE_MAP() 73 | }; 74 | 75 | ///////////////////////////////////////////////////////////////////////////// 76 | // CInPlaceList window 77 | 78 | class CInPlaceList : public CComboBox 79 | { 80 | friend class CComboEdit; 81 | 82 | // Construction 83 | public: 84 | CInPlaceList(CWnd* pParent, // parent 85 | CRect& rect, // dimensions & location 86 | DWORD dwStyle, // window/combobox style 87 | UINT nID, // control ID 88 | int nRow, int nColumn, // row and column 89 | CStringArray& Items, // Items in list 90 | CString sInitText, // initial selection 91 | UINT nFirstChar); // first character to pass to control 92 | 93 | // Attributes 94 | public: 95 | CComboEdit m_edit; // subclassed edit control 96 | 97 | // Operations 98 | public: 99 | 100 | // Overrides 101 | // ClassWizard generated virtual function overrides 102 | //{{AFX_VIRTUAL(CInPlaceList) 103 | protected: 104 | virtual void PostNcDestroy(); 105 | //}}AFX_VIRTUAL 106 | 107 | // Implementation 108 | public: 109 | virtual ~CInPlaceList(); 110 | protected: 111 | void EndEdit(); 112 | 113 | // Generated message map functions 114 | protected: 115 | //{{AFX_MSG(CInPlaceList) 116 | afx_msg void OnKillFocus(CWnd* pNewWnd); 117 | afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 118 | afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); 119 | //}}AFX_MSG 120 | 121 | DECLARE_MESSAGE_MAP() 122 | 123 | private: 124 | int m_nNumLines; 125 | CString m_sInitText; 126 | int m_nRow; 127 | int m_nCol; 128 | UINT m_nLastChar; 129 | BOOL m_bExitOnArrows; 130 | }; 131 | 132 | ///////////////////////////////////////////////////////////////////////////// 133 | 134 | //{{AFX_INSERT_LOCATION}} 135 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 136 | 137 | #endif // !defined(AFX_INPLACELIST_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_) 138 | -------------------------------------------------------------------------------- /GridDropTarget.cpp: -------------------------------------------------------------------------------- 1 | // GridDropTarget.cpp : implementation file 2 | // 3 | // MFC Grid Control - Drag/Drop target implementation 4 | // 5 | // CGridDropTarget is an OLE drop target for CGridCtrl. All it does 6 | // is handle the drag and drop windows messages and pass them 7 | // directly onto the grid control. 8 | // 9 | // Written by Chris Maunder 10 | // Copyright (c) 1998-2005. All Rights Reserved. 11 | // 12 | // This code may be used in compiled form in any way you desire. This 13 | // file may be redistributed unmodified by any means PROVIDING it is 14 | // not sold for profit without the authors written consent, and 15 | // providing that this notice and the authors name and all copyright 16 | // notices remains intact. 17 | // 18 | // An email letting me know how you are using it would be nice as well. 19 | // 20 | // This file is provided "as is" with no expressed or implied warranty. 21 | // The author accepts no liability for any damage/loss of business that 22 | // this product may cause. 23 | // 24 | // For use with CGridCtrl v2.10+ 25 | // 26 | ///////////////////////////////////////////////////////////////////////////// 27 | 28 | #include "stdafx.h" 29 | #include "GridCtrl.h" 30 | 31 | #ifndef GRIDCONTROL_NO_DRAGDROP 32 | #include "GridDropTarget.h" 33 | 34 | #ifdef _DEBUG 35 | #define new DEBUG_NEW 36 | #undef THIS_FILE 37 | static char THIS_FILE[] = __FILE__; 38 | #endif 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | // CGridDropTarget 42 | 43 | CGridDropTarget::CGridDropTarget() 44 | { 45 | m_pGridCtrl = NULL; 46 | m_bRegistered = FALSE; 47 | } 48 | 49 | CGridDropTarget::~CGridDropTarget() 50 | { 51 | } 52 | 53 | // Overloaded Register() function performs the normal COleDropTarget::Register 54 | // but also serves to connect this COleDropTarget with the parent grid control, 55 | // where all drop messages will ultimately be forwarded. 56 | BOOL CGridDropTarget::Register(CGridCtrl *pGridCtrl) 57 | { 58 | if (m_bRegistered) 59 | return FALSE; 60 | 61 | // Stop re-entry problems 62 | static BOOL bInProcedure = FALSE; 63 | if (bInProcedure) 64 | return FALSE; 65 | bInProcedure = TRUE; 66 | 67 | ASSERT(pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl))); 68 | ASSERT(pGridCtrl); 69 | 70 | if (!pGridCtrl || !pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl))) 71 | { 72 | bInProcedure = FALSE; 73 | return FALSE; 74 | } 75 | 76 | m_pGridCtrl = pGridCtrl; 77 | 78 | m_bRegistered = COleDropTarget::Register(pGridCtrl); 79 | 80 | bInProcedure = FALSE; 81 | return m_bRegistered; 82 | } 83 | 84 | void CGridDropTarget::Revoke() 85 | { 86 | m_bRegistered = FALSE; 87 | COleDropTarget::Revoke(); 88 | } 89 | 90 | BEGIN_MESSAGE_MAP(CGridDropTarget, COleDropTarget) 91 | //{{AFX_MSG_MAP(CGridDropTarget) 92 | //}}AFX_MSG_MAP 93 | END_MESSAGE_MAP() 94 | 95 | ///////////////////////////////////////////////////////////////////////////// 96 | // CGridDropTarget message handlers 97 | 98 | DROPEFFECT CGridDropTarget::OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint /*point*/) 99 | { 100 | // TRACE("In CGridDropTarget::OnDragScroll\n"); 101 | if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) 102 | { 103 | if (dwKeyState & MK_CONTROL) 104 | return DROPEFFECT_COPY; 105 | else 106 | return DROPEFFECT_MOVE; 107 | } else 108 | return DROPEFFECT_NONE; 109 | } 110 | 111 | DROPEFFECT CGridDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, 112 | DWORD dwKeyState, CPoint point) 113 | { 114 | TRACE(_T("In CGridDropTarget::OnDragEnter\n")); 115 | ASSERT(m_pGridCtrl); 116 | 117 | if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) 118 | return m_pGridCtrl->OnDragEnter(pDataObject, dwKeyState, point); 119 | else 120 | return DROPEFFECT_NONE; 121 | } 122 | 123 | void CGridDropTarget::OnDragLeave(CWnd* pWnd) 124 | { 125 | TRACE(_T("In CGridDropTarget::OnDragLeave\n")); 126 | ASSERT(m_pGridCtrl); 127 | 128 | if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) 129 | m_pGridCtrl->OnDragLeave(); 130 | } 131 | 132 | DROPEFFECT CGridDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, 133 | DWORD dwKeyState, CPoint point) 134 | { 135 | // TRACE("In CGridDropTarget::OnDragOver\n"); 136 | ASSERT(m_pGridCtrl); 137 | 138 | if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) 139 | return m_pGridCtrl->OnDragOver(pDataObject, dwKeyState, point); 140 | else 141 | return DROPEFFECT_NONE; 142 | } 143 | 144 | BOOL CGridDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, 145 | DROPEFFECT dropEffect, CPoint point) 146 | { 147 | TRACE(_T("In CGridDropTarget::OnDrop\n")); 148 | ASSERT(m_pGridCtrl); 149 | 150 | if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) 151 | return m_pGridCtrl->OnDrop(pDataObject, dropEffect, point); 152 | else 153 | return FALSE; 154 | } 155 | 156 | #endif // GRIDCONTROL_NO_DRAGDROP -------------------------------------------------------------------------------- /CellRange.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////// 2 | // CellRange.h: header file 3 | // 4 | // MFC Grid Control - interface for the CCellRange class. 5 | // 6 | // Written by Chris Maunder 7 | // Copyright (c) 1998-2002. All Rights Reserved. 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name and all copyright 13 | // notices remains intact. 14 | // 15 | // An email letting me know how you are using it would be nice as well. 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // For use with CGridCtrl v2.20+ 22 | // 23 | ////////////////////////////////////////////////////////////////////// 24 | 25 | #if !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_) 26 | #define AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_ 27 | 28 | #if _MSC_VER >= 1000 29 | #pragma once 30 | #endif // _MSC_VER >= 1000 31 | 32 | // The code contained in this file is based on the original 33 | // WorldCom Grid control written by Joe Willcoxson, 34 | // mailto:chinajoe@aol.com 35 | // http://users.aol.com/chinajoe 36 | 37 | class CCellID 38 | { 39 | // Attributes 40 | public: 41 | int row, col; 42 | 43 | // Operations 44 | public: 45 | explicit CCellID(int nRow = -1, int nCol = -1) : row(nRow), col(nCol) {} 46 | 47 | int IsValid() const { return (row >= 0 && col >= 0); } 48 | int operator==(const CCellID& rhs) const { return (row == rhs.row && col == rhs.col); } 49 | int operator!=(const CCellID& rhs) const { return !operator==(rhs); } 50 | }; 51 | 52 | class CCellRange 53 | { 54 | public: 55 | 56 | CCellRange(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1) 57 | { 58 | Set(nMinRow, nMinCol, nMaxRow, nMaxCol); 59 | } 60 | 61 | void Set(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1); 62 | 63 | int IsValid() const; 64 | int InRange(int row, int col) const; 65 | int InRange(const CCellID& cellID) const; 66 | int Count() { return (m_nMaxRow - m_nMinRow + 1) * (m_nMaxCol - m_nMinCol + 1); } 67 | 68 | CCellID GetTopLeft() const; 69 | CCellRange Intersect(const CCellRange& rhs) const; 70 | 71 | int GetMinRow() const {return m_nMinRow;} 72 | void SetMinRow(int minRow) {m_nMinRow = minRow;} 73 | 74 | int GetMinCol() const {return m_nMinCol;} 75 | void SetMinCol(int minCol) {m_nMinCol = minCol;} 76 | 77 | int GetMaxRow() const {return m_nMaxRow;} 78 | void SetMaxRow(int maxRow) {m_nMaxRow = maxRow;} 79 | 80 | int GetMaxCol() const {return m_nMaxCol;} 81 | void SetMaxCol(int maxCol) {m_nMaxCol = maxCol;} 82 | 83 | int GetRowSpan() const {return m_nMaxRow - m_nMinRow + 1;} 84 | int GetColSpan() const {return m_nMaxCol - m_nMinCol + 1;} 85 | 86 | void operator=(const CCellRange& rhs); 87 | int operator==(const CCellRange& rhs); 88 | int operator!=(const CCellRange& rhs); 89 | 90 | protected: 91 | int m_nMinRow; 92 | int m_nMinCol; 93 | int m_nMaxRow; 94 | int m_nMaxCol; 95 | }; 96 | 97 | inline void CCellRange::Set(int minRow, int minCol, int maxRow, int maxCol) 98 | { 99 | m_nMinRow = minRow; 100 | m_nMinCol = minCol; 101 | m_nMaxRow = maxRow; 102 | m_nMaxCol = maxCol; 103 | } 104 | 105 | inline void CCellRange::operator=(const CCellRange& rhs) 106 | { 107 | if (this != &rhs) Set(rhs.m_nMinRow, rhs.m_nMinCol, rhs.m_nMaxRow, rhs.m_nMaxCol); 108 | } 109 | 110 | inline int CCellRange::operator==(const CCellRange& rhs) 111 | { 112 | return ((m_nMinRow == rhs.m_nMinRow) && (m_nMinCol == rhs.m_nMinCol) && 113 | (m_nMaxRow == rhs.m_nMaxRow) && (m_nMaxCol == rhs.m_nMaxCol)); 114 | } 115 | 116 | inline int CCellRange::operator!=(const CCellRange& rhs) 117 | { 118 | return !operator==(rhs); 119 | } 120 | 121 | inline int CCellRange::IsValid() const 122 | { 123 | return (m_nMinRow >= 0 && m_nMinCol >= 0 && m_nMaxRow >= 0 && m_nMaxCol >= 0 && 124 | m_nMinRow <= m_nMaxRow && m_nMinCol <= m_nMaxCol); 125 | } 126 | 127 | inline int CCellRange::InRange(int row, int col) const 128 | { 129 | return (row >= m_nMinRow && row <= m_nMaxRow && col >= m_nMinCol && col <= m_nMaxCol); 130 | } 131 | 132 | inline int CCellRange::InRange(const CCellID& cellID) const 133 | { 134 | return InRange(cellID.row, cellID.col); 135 | } 136 | 137 | inline CCellID CCellRange::GetTopLeft() const 138 | { 139 | return CCellID(m_nMinRow, m_nMinCol); 140 | } 141 | 142 | inline CCellRange CCellRange::Intersect(const CCellRange& rhs) const 143 | { 144 | return CCellRange(max(m_nMinRow,rhs.m_nMinRow), max(m_nMinCol,rhs.m_nMinCol), 145 | min(m_nMaxRow,rhs.m_nMaxRow), min(m_nMaxCol,rhs.m_nMaxCol)); 146 | } 147 | 148 | #endif // !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_) 149 | -------------------------------------------------------------------------------- /Experimental Upgrades/GridCellLite.cpp: -------------------------------------------------------------------------------- 1 | // GridCell.cpp : implementation file 2 | // 3 | // MFC Grid Control - Main grid cell class 4 | // 5 | // Provides the implementation for the "default" cell type of the 6 | // grid control. Adds in cell editing. 7 | // 8 | // Written by Chris Maunder 9 | // Copyright (c) 1998-2000. All Rights Reserved. 10 | // 11 | // This code may be used in compiled form in any way you desire. This 12 | // file may be redistributed unmodified by any means PROVIDING it is 13 | // not sold for profit without the authors written consent, and 14 | // providing that this notice and the authors name and all copyright 15 | // notices remains intact. 16 | // 17 | // An email letting me know how you are using it would be nice as well. 18 | // 19 | // This file is provided "as is" with no expressed or implied warranty. 20 | // The author accepts no liability for any damage/loss of business that 21 | // this product may cause. 22 | // 23 | // For use with CGridCtrl v2.10 24 | // 25 | // History: 26 | // Eric Woodruff - 20 Feb 2000 - Added PrintCell() plus other minor changes 27 | // Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase 28 | // 29 | // 30 | ///////////////////////////////////////////////////////////////////////////// 31 | 32 | #include "stdafx.h" 33 | #include "GridCell.h" 34 | #include "InPlaceEdit.h" 35 | #include "GridCtrl.h" 36 | 37 | #ifdef _DEBUG 38 | #define new DEBUG_NEW 39 | #undef THIS_FILE 40 | static char THIS_FILE[] = __FILE__; 41 | #endif 42 | 43 | #ifdef GRIDCTRL_MINSIZE 44 | ///////////////////////////////////////////////////////////////////////////// 45 | // CGridCellAttr default static attributes 46 | 47 | DWORD CGridCellAttr::m_nDefFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX 48 | #ifndef _WIN32_WCE 49 | | DT_END_ELLIPSIS 50 | #endif 51 | ; 52 | COLORREF CGridCellAttr::m_crDefBkClr = CLR_DEFAULT; // Background colour (or CLR_DEFAULT) 53 | COLORREF CGridCellAttr::m_crDefFgClr = CLR_DEFAULT; // Forground colour (or CLR_DEFAULT) 54 | LOGFONT CGridCellAttr::m_lfDefFont; // Cell font 55 | UINT CGridCellAttr::m_nDefMargin = 3; // Internal cell margin 56 | 57 | #endif 58 | 59 | IMPLEMENT_DYNCREATE(CGridCell, CGridCellBase) 60 | 61 | ///////////////////////////////////////////////////////////////////////////// 62 | // GridCell 63 | 64 | CGridCell::CGridCell() 65 | { 66 | Reset(); 67 | } 68 | 69 | CGridCell::~CGridCell() 70 | { 71 | #ifdef GRIDCTRL_MINSIZE 72 | delete m_pAttr; 73 | #endif 74 | } 75 | 76 | ///////////////////////////////////////////////////////////////////////////// 77 | // GridCell Attributes 78 | 79 | void CGridCell::Reset() 80 | { 81 | CGridCellBase::Reset(); 82 | 83 | m_strText.Empty(); 84 | m_nImage = -1; 85 | m_pGrid = NULL; 86 | m_bEditing = FALSE; 87 | m_pEditWnd = NULL; 88 | 89 | #ifdef GRIDCTRL_MINSIZE 90 | delete m_pAttr; 91 | m_pAttr = NULL; 92 | #else 93 | #ifdef _WIN32_WCE 94 | m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX; 95 | #else 96 | m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX | DT_END_ELLIPSIS; 97 | #endif 98 | m_crBkClr = CLR_DEFAULT; // Background colour (or CLR_DEFAULT) 99 | m_crFgClr = CLR_DEFAULT; // Forground colour (or CLR_DEFAULT) 100 | m_lfFont; // Cell font 101 | m_nMargin = 3; // Internal cell margin 102 | #endif 103 | } 104 | 105 | ///////////////////////////////////////////////////////////////////////////// 106 | // GridCell Operations 107 | 108 | BOOL CGridCell::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar) 109 | { 110 | DWORD dwStyle = ES_LEFT; 111 | if (GetFormat() & DT_RIGHT) 112 | dwStyle = ES_RIGHT; 113 | else if (GetFormat() & DT_CENTER) 114 | dwStyle = ES_CENTER; 115 | 116 | m_bEditing = TRUE; 117 | 118 | // InPlaceEdit auto-deletes itself 119 | CGridCtrl* pGrid = GetGrid(); 120 | m_pEditWnd = new CInPlaceEdit(pGrid, rect, dwStyle, nID, nRow, nCol, GetText(), nChar); 121 | 122 | return TRUE; 123 | } 124 | 125 | void CGridCell::EndEdit() 126 | { 127 | if (m_pEditWnd) 128 | ((CInPlaceEdit*)m_pEditWnd)->EndEdit(); 129 | } 130 | 131 | void CGridCell::OnEndEdit() 132 | { 133 | m_bEditing = FALSE; 134 | m_pEditWnd = NULL; 135 | } 136 | 137 | inline DWORD CGridCell::GetFormat() { return m_nFormat; } 138 | inline COLORREF CGridCell::GetTextClr() { return m_crFgClr; } 139 | inline COLORREF CGridCell::GetBackClr() { return m_crBkClr; } 140 | inline const LOGFONT* CGridCell::GetFont() { return &m_lfFont; } 141 | inline UINT CGridCell::GetMargin() { return m_nMargin; } 142 | 143 | inline void CGridCell::SetFormat(DWORD nFormat) { m_nFormat = nFormat; } 144 | inline void CGridCell::SetTextClr(COLORREF clr) { m_crFgClr = clr; } 145 | inline void CGridCell::SetBackClr(COLORREF clr) { m_crBkClr = clr; } 146 | inline void CGridCell::SetFont(const LOGFONT* plf) { memcpy(&(m_lfFont), plf, sizeof(LOGFONT)); } 147 | inline void CGridCell::SetMargin( UINT nMargin) { m_nMargin = nMargin; } 148 | -------------------------------------------------------------------------------- /GridCell.cpp: -------------------------------------------------------------------------------- 1 | // GridCell.cpp : implementation file 2 | // 3 | // MFC Grid Control - Main grid cell class 4 | // 5 | // Provides the implementation for the "default" cell type of the 6 | // grid control. Adds in cell editing. 7 | // 8 | // Written by Chris Maunder 9 | // Copyright (c) 1998-2005. All Rights Reserved. 10 | // 11 | // This code may be used in compiled form in any way you desire. This 12 | // file may be redistributed unmodified by any means PROVIDING it is 13 | // not sold for profit without the authors written consent, and 14 | // providing that this notice and the authors name and all copyright 15 | // notices remains intact. 16 | // 17 | // An email letting me know how you are using it would be nice as well. 18 | // 19 | // This file is provided "as is" with no expressed or implied warranty. 20 | // The author accepts no liability for any damage/loss of business that 21 | // this product may cause. 22 | // 23 | // For use with CGridCtrl v2.20+ 24 | // 25 | // History: 26 | // Eric Woodruff - 20 Feb 2000 - Added PrintCell() plus other minor changes 27 | // Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase 28 | // 29 | // C Maunder - 17 Jun 2000 - Font handling optimsed, Added CGridDefaultCell 30 | // 31 | ///////////////////////////////////////////////////////////////////////////// 32 | 33 | #include "stdafx.h" 34 | #include "GridCell.h" 35 | #include "InPlaceEdit.h" 36 | #include "GridCtrl.h" 37 | 38 | #pragma warning(disable:4996) 39 | 40 | #ifdef _DEBUG 41 | #define new DEBUG_NEW 42 | #undef THIS_FILE 43 | static char THIS_FILE[] = __FILE__; 44 | #endif 45 | 46 | IMPLEMENT_DYNCREATE(CGridCell, CGridCellBase) 47 | IMPLEMENT_DYNCREATE(CGridDefaultCell, CGridCell) 48 | 49 | ///////////////////////////////////////////////////////////////////////////// 50 | // GridCell 51 | 52 | CGridCell::CGridCell() 53 | { 54 | m_plfFont = NULL; 55 | CGridCell::Reset(); 56 | } 57 | 58 | CGridCell::~CGridCell() 59 | { 60 | delete m_plfFont; 61 | } 62 | 63 | ///////////////////////////////////////////////////////////////////////////// 64 | // GridCell Attributes 65 | 66 | void CGridCell::operator=(const CGridCell& cell) 67 | { 68 | if (this != &cell) CGridCellBase::operator=(cell); 69 | } 70 | 71 | void CGridCell::Reset() 72 | { 73 | CGridCellBase::Reset(); 74 | 75 | m_strText.Empty(); 76 | m_nImage = -1; 77 | m_lParam = NULL; // BUG FIX J. Bloggs 20/10/03 78 | m_pGrid = NULL; 79 | m_bEditing = FALSE; 80 | m_pEditWnd = NULL; 81 | 82 | m_nFormat = (DWORD)-1; // Use default from CGridDefaultCell 83 | m_crBkClr = CLR_DEFAULT; // Background colour (or CLR_DEFAULT) 84 | m_crFgClr = CLR_DEFAULT; // Forground colour (or CLR_DEFAULT) 85 | m_crFrClr = CLR_DEFAULT; // Frame colour (or CLR_DEFAULT) 86 | m_nMargin = (UINT)-1; // Use default from CGridDefaultCell 87 | 88 | delete m_plfFont; 89 | m_plfFont = NULL; // Cell font 90 | } 91 | 92 | void CGridCell::SetFont(const LOGFONT* plf) 93 | { 94 | if (plf == NULL) 95 | { 96 | delete m_plfFont; 97 | m_plfFont = NULL; 98 | } 99 | else 100 | { 101 | if (!m_plfFont) 102 | m_plfFont = new LOGFONT; 103 | if (m_plfFont) 104 | memcpy(m_plfFont, plf, sizeof(LOGFONT)); 105 | } 106 | } 107 | 108 | LOGFONT* CGridCell::GetFont() const 109 | { 110 | if (m_plfFont == NULL) 111 | { 112 | CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); 113 | if (!pDefaultCell) 114 | return NULL; 115 | 116 | return pDefaultCell->GetFont(); 117 | } 118 | 119 | return m_plfFont; 120 | } 121 | 122 | CFont* CGridCell::GetFontObject() const 123 | { 124 | // If the default font is specified, use the default cell implementation 125 | if (m_plfFont == NULL) 126 | { 127 | CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); 128 | if (!pDefaultCell) 129 | return NULL; 130 | 131 | return pDefaultCell->GetFontObject(); 132 | } 133 | else 134 | { 135 | static CFont Font; 136 | Font.DeleteObject(); 137 | Font.CreateFontIndirect(m_plfFont); 138 | return &Font; 139 | } 140 | } 141 | 142 | DWORD CGridCell::GetFormat() const 143 | { 144 | if (m_nFormat == (DWORD)-1) 145 | { 146 | CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); 147 | if (!pDefaultCell) 148 | return 0; 149 | 150 | return pDefaultCell->GetFormat(); 151 | } 152 | 153 | return m_nFormat; 154 | } 155 | 156 | UINT CGridCell::GetMargin() const 157 | { 158 | if (m_nMargin == (UINT)-1) 159 | { 160 | CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); 161 | if (!pDefaultCell) 162 | return 0; 163 | 164 | return pDefaultCell->GetMargin(); 165 | } 166 | 167 | return m_nMargin; 168 | } 169 | 170 | ///////////////////////////////////////////////////////////////////////////// 171 | // GridCell Operations 172 | 173 | BOOL CGridCell::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar) 174 | { 175 | if ( m_bEditing ) 176 | { 177 | if (m_pEditWnd) 178 | m_pEditWnd->SendMessage ( WM_CHAR, nChar ); 179 | } 180 | else 181 | { 182 | DWORD dwStyle = ES_LEFT; 183 | if (GetFormat() & DT_RIGHT) 184 | dwStyle = ES_RIGHT; 185 | else if (GetFormat() & DT_CENTER) 186 | dwStyle = ES_CENTER; 187 | 188 | m_bEditing = TRUE; 189 | 190 | // InPlaceEdit auto-deletes itself 191 | CGridCtrl* pGrid = GetGrid(); 192 | m_pEditWnd = new CInPlaceEdit(pGrid, rect, dwStyle, nID, nRow, nCol, GetText(), nChar); 193 | } 194 | return TRUE; 195 | } 196 | 197 | void CGridCell::EndEdit() 198 | { 199 | if (m_pEditWnd) 200 | ((CInPlaceEdit*)m_pEditWnd)->EndEdit(); 201 | } 202 | 203 | void CGridCell::OnEndEdit() 204 | { 205 | m_bEditing = FALSE; 206 | m_pEditWnd = NULL; 207 | } 208 | 209 | ///////////////////////////////////////////////////////////////////////////// 210 | // CGridDefaultCell 211 | 212 | CGridDefaultCell::CGridDefaultCell() 213 | { 214 | #ifdef _WIN32_WCE 215 | m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX; 216 | #else 217 | m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX | DT_END_ELLIPSIS; 218 | #endif 219 | m_crFgClr = CLR_DEFAULT; 220 | m_crBkClr = CLR_DEFAULT; 221 | m_Size = CSize(30,10); 222 | m_dwStyle = 0; 223 | 224 | #ifdef _WIN32_WCE 225 | LOGFONT lf; 226 | GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &lf); 227 | SetFont(&lf); 228 | #else // not CE 229 | 230 | NONCLIENTMETRICS ncm; 231 | #if defined(_MSC_VER) && (_MSC_VER < 1300) 232 | ncm.cbSize = sizeof(NONCLIENTMETRICS); // NONCLIENTMETRICS has an extra element after VC6 233 | #else 234 | // Check the operating system's version 235 | OSVERSIONINFOEX osvi; 236 | ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); 237 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 238 | if( !GetVersionEx((OSVERSIONINFO *) &osvi)) 239 | { 240 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 241 | GetVersionEx ((OSVERSIONINFO *)&osvi); 242 | } 243 | 244 | if (osvi.dwMajorVersion > 5) 245 | ncm.cbSize = sizeof(NONCLIENTMETRICS); 246 | else 247 | ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth); 248 | #endif 249 | VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)); 250 | 251 | SetFont(&(ncm.lfMessageFont)); 252 | #endif 253 | } 254 | 255 | CGridDefaultCell::~CGridDefaultCell() 256 | { 257 | m_Font.DeleteObject(); 258 | } 259 | 260 | void CGridDefaultCell::SetFont(const LOGFONT* plf) 261 | { 262 | ASSERT(plf); 263 | 264 | if (!plf) return; 265 | 266 | m_Font.DeleteObject(); 267 | m_Font.CreateFontIndirect(plf); 268 | 269 | CGridCell::SetFont(plf); 270 | 271 | // Get the font size and hence the default cell size 272 | CDC* pDC = CDC::FromHandle(::GetDC(NULL)); 273 | if (pDC) 274 | { 275 | CFont* pOldFont = pDC->SelectObject(&m_Font); 276 | 277 | SetMargin(pDC->GetTextExtent(_T(" "), 1).cx); 278 | m_Size = pDC->GetTextExtent(_T(" XXXXXXXXXXXX "), 14); 279 | m_Size.cy = (m_Size.cy * 3) / 2; 280 | 281 | pDC->SelectObject(pOldFont); 282 | ReleaseDC(NULL, pDC->GetSafeHdc()); 283 | } 284 | else 285 | { 286 | SetMargin(3); 287 | m_Size = CSize(40,16); 288 | } 289 | } 290 | 291 | LOGFONT* CGridDefaultCell::GetFont() const 292 | { 293 | ASSERT(m_plfFont); // This is the default - it CAN'T be NULL! 294 | return m_plfFont; 295 | } 296 | 297 | CFont* CGridDefaultCell::GetFontObject() const 298 | { 299 | ASSERT(m_Font.GetSafeHandle()); 300 | return (CFont*) &m_Font; 301 | } 302 | -------------------------------------------------------------------------------- /project/GridCtrl.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {A8267B22-5A84-42D0-8687-9303B193B6C9} 24 | Win32Proj 25 | GridCtrl 26 | 10.0.17134.0 27 | 28 | 29 | 30 | StaticLibrary 31 | true 32 | v141 33 | MultiByte 34 | Static 35 | 36 | 37 | StaticLibrary 38 | false 39 | v141 40 | true 41 | MultiByte 42 | Static 43 | 44 | 45 | StaticLibrary 46 | true 47 | v141 48 | MultiByte 49 | Static 50 | 51 | 52 | StaticLibrary 53 | false 54 | v141 55 | true 56 | MultiByte 57 | Static 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Use 92 | Level3 93 | Disabled 94 | true 95 | _DEBUG;_LIB;%(PreprocessorDefinitions) 96 | true 97 | 98 | 99 | Windows 100 | true 101 | 102 | 103 | 104 | 105 | Use 106 | Level3 107 | Disabled 108 | true 109 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 110 | true 111 | 112 | 113 | Windows 114 | true 115 | 116 | 117 | 118 | 119 | Use 120 | Level3 121 | MaxSpeed 122 | true 123 | true 124 | true 125 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 126 | true 127 | 128 | 129 | Windows 130 | true 131 | true 132 | true 133 | 134 | 135 | 136 | 137 | Use 138 | Level3 139 | MaxSpeed 140 | true 141 | true 142 | true 143 | NDEBUG;_LIB;%(PreprocessorDefinitions) 144 | true 145 | 146 | 147 | Windows 148 | true 149 | true 150 | true 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | Create 173 | Create 174 | Create 175 | Create 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /InPlaceEdit.cpp: -------------------------------------------------------------------------------- 1 | // InPlaceEdit.cpp : implementation file 2 | // 3 | // Adapted by Chris Maunder 4 | // Copyright (c) 1998-2002. All Rights Reserved. 5 | // 6 | // The code contained in this file is based on the original 7 | // CInPlaceEdit from http://www.codeguru.com/listview/edit_subitems.shtml 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name and all copyright 13 | // notices remains intact. 14 | // 15 | // An email letting me know how you are using it would be nice as well. 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // For use with CGridCtrl v2.10+ 22 | // 23 | // History: 24 | // 10 May 1998 Uses GVN_ notifications instead of LVN_, 25 | // Sends notification messages to the parent, 26 | // instead of the parent's parent. 27 | // 15 May 1998 There was a problem when editing with the in-place editor, 28 | // there arises a general protection fault in user.exe, with a 29 | // few qualifications: 30 | // (1) This only happens with owner-drawn buttons; 31 | // (2) This only happens in Win95 32 | // (3) This only happens if the handler for the button does not 33 | // create a new window (even an AfxMessageBox will avoid the 34 | // crash) 35 | // (4) This will not happen if Spy++ is running. 36 | // PreTranslateMessage was added to route messages correctly. 37 | // (Matt Weagle found and fixed this problem) 38 | // 26 Jul 1998 Removed the ES_MULTILINE style - that fixed a few probs! 39 | // 6 Aug 1998 Added nID to the constructor param list 40 | // 6 Sep 1998 Space no longer clears selection when starting edit (Franco Bez) 41 | // 10 Apr 1999 Enter, Tab and Esc key prob fixed (Koay Kah Hoe) 42 | // Workaround for bizzare "shrinking window" problem in CE 43 | // 44 | ///////////////////////////////////////////////////////////////////////////// 45 | 46 | #include "stdafx.h" 47 | #include "TCHAR.h" 48 | #include "InPlaceEdit.h" 49 | 50 | #include "GridCtrl.h" 51 | 52 | #ifdef _DEBUG 53 | #define new DEBUG_NEW 54 | #undef THIS_FILE 55 | static char THIS_FILE[] = __FILE__; 56 | #endif 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // CInPlaceEdit 60 | 61 | CInPlaceEdit::CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, 62 | int nRow, int nColumn, CString sInitText, 63 | UINT nFirstChar) 64 | { 65 | m_sInitText = sInitText; 66 | m_nRow = nRow; 67 | m_nColumn = nColumn; 68 | m_nLastChar = 0; 69 | m_bExitOnArrows = (nFirstChar != VK_LBUTTON); // If mouse click brought us here, 70 | // then no exit on arrows 71 | 72 | m_Rect = rect; // For bizarre CE bug. 73 | 74 | DWORD dwEditStyle = WS_BORDER|WS_CHILD|WS_VISIBLE| ES_AUTOHSCROLL //|ES_MULTILINE 75 | | dwStyle; 76 | if (!Create(dwEditStyle, rect, pParent, nID)) return; 77 | 78 | SetFont(pParent->GetFont()); 79 | 80 | SetWindowText(sInitText); 81 | SetFocus(); 82 | 83 | switch (nFirstChar){ 84 | case VK_LBUTTON: 85 | case VK_RETURN: SetSel((int)_tcslen(m_sInitText), -1); return; 86 | case VK_BACK: SetSel((int)_tcslen(m_sInitText), -1); break; 87 | case VK_TAB: 88 | case VK_DOWN: 89 | case VK_UP: 90 | case VK_RIGHT: 91 | case VK_LEFT: 92 | case VK_NEXT: 93 | case VK_PRIOR: 94 | case VK_HOME: 95 | case VK_SPACE: 96 | case VK_END: SetSel(0,-1); return; 97 | default: SetSel(0,-1); 98 | } 99 | 100 | // Added by KiteFly. When entering DBCS chars into cells the first char was being lost 101 | // SenMessage changed to PostMessage (John Lagerquist) 102 | if( nFirstChar < 0x80) 103 | PostMessage(WM_CHAR, nFirstChar); 104 | else 105 | PostMessage(WM_IME_CHAR, nFirstChar); 106 | } 107 | 108 | CInPlaceEdit::~CInPlaceEdit() 109 | { 110 | } 111 | 112 | BEGIN_MESSAGE_MAP(CInPlaceEdit, CEdit) 113 | //{{AFX_MSG_MAP(CInPlaceEdit) 114 | ON_WM_KILLFOCUS() 115 | ON_WM_CHAR() 116 | ON_WM_KEYDOWN() 117 | ON_WM_GETDLGCODE() 118 | ON_WM_CREATE() 119 | //}}AFX_MSG_MAP 120 | END_MESSAGE_MAP() 121 | 122 | //////////////////////////////////////////////////////////////////////////// 123 | // CInPlaceEdit message handlers 124 | 125 | // If an arrow key (or associated) is pressed, then exit if 126 | // a) The Ctrl key was down, or 127 | // b) m_bExitOnArrows == TRUE 128 | void CInPlaceEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 129 | { 130 | if ((nChar == VK_PRIOR || nChar == VK_NEXT || 131 | nChar == VK_DOWN || nChar == VK_UP || 132 | nChar == VK_RIGHT || nChar == VK_LEFT) && 133 | (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0)) 134 | { 135 | m_nLastChar = nChar; 136 | GetParent()->SetFocus(); 137 | return; 138 | } 139 | 140 | CEdit::OnKeyDown(nChar, nRepCnt, nFlags); 141 | } 142 | 143 | // As soon as this edit loses focus, kill it. 144 | void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd) 145 | { 146 | CEdit::OnKillFocus(pNewWnd); 147 | EndEdit(); 148 | } 149 | 150 | void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 151 | { 152 | if (nChar == VK_TAB || nChar == VK_RETURN) 153 | { 154 | m_nLastChar = nChar; 155 | GetParent()->SetFocus(); // This will destroy this window 156 | return; 157 | } 158 | if (nChar == VK_ESCAPE) 159 | { 160 | SetWindowText(m_sInitText); // restore previous text 161 | m_nLastChar = nChar; 162 | GetParent()->SetFocus(); 163 | return; 164 | } 165 | 166 | CEdit::OnChar(nChar, nRepCnt, nFlags); 167 | 168 | // Resize edit control if needed 169 | 170 | // Get text extent 171 | CString str; 172 | GetWindowText( str ); 173 | 174 | // add some extra buffer 175 | str += _T(" "); 176 | 177 | CWindowDC dc(this); 178 | CFont *pFontDC = dc.SelectObject(GetFont()); 179 | CSize size = dc.GetTextExtent( str ); 180 | dc.SelectObject( pFontDC ); 181 | 182 | // Get client rect 183 | CRect ParentRect; 184 | GetParent()->GetClientRect( &ParentRect ); 185 | 186 | // Check whether control needs to be resized 187 | // and whether there is space to grow 188 | if (size.cx > m_Rect.Width()) 189 | { 190 | if( size.cx + m_Rect.left < ParentRect.right ) 191 | m_Rect.right = m_Rect.left + size.cx; 192 | else 193 | m_Rect.right = ParentRect.right; 194 | MoveWindow( &m_Rect ); 195 | } 196 | } 197 | 198 | UINT CInPlaceEdit::OnGetDlgCode() 199 | { 200 | return DLGC_WANTALLKEYS; 201 | } 202 | 203 | //////////////////////////////////////////////////////////////////////////// 204 | // CInPlaceEdit overrides 205 | 206 | // Stoopid win95 accelerator key problem workaround - Matt Weagle. 207 | BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg) 208 | { 209 | // Catch the Alt key so we don't choke if focus is going to an owner drawn button 210 | if (pMsg->message == WM_SYSCHAR) 211 | return TRUE; 212 | 213 | return CWnd::PreTranslateMessage(pMsg); 214 | } 215 | 216 | // Auto delete 217 | void CInPlaceEdit::PostNcDestroy() 218 | { 219 | CEdit::PostNcDestroy(); 220 | 221 | delete this; 222 | } 223 | 224 | //////////////////////////////////////////////////////////////////////////// 225 | // CInPlaceEdit implementation 226 | 227 | void CInPlaceEdit::EndEdit() 228 | { 229 | CString str; 230 | 231 | // EFW - BUG FIX - Clicking on a grid scroll bar in a derived class 232 | // that validates input can cause this to get called multiple times 233 | // causing assertions because the edit control goes away the first time. 234 | static BOOL bAlreadyEnding = FALSE; 235 | 236 | if(bAlreadyEnding) 237 | return; 238 | 239 | bAlreadyEnding = TRUE; 240 | GetWindowText(str); 241 | 242 | // Send Notification to parent 243 | GV_DISPINFO dispinfo; 244 | 245 | dispinfo.hdr.hwndFrom = GetSafeHwnd(); 246 | dispinfo.hdr.idFrom = GetDlgCtrlID(); 247 | dispinfo.hdr.code = GVN_ENDLABELEDIT; 248 | 249 | dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM; 250 | dispinfo.item.row = m_nRow; 251 | dispinfo.item.col = m_nColumn; 252 | dispinfo.item.strText = str; 253 | dispinfo.item.lParam = (LPARAM) m_nLastChar; 254 | 255 | CWnd* pOwner = GetOwner(); 256 | if (pOwner) 257 | pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo ); 258 | 259 | // Close this window (PostNcDestroy will delete this) 260 | if (IsWindow(GetSafeHwnd())) 261 | SendMessage(WM_CLOSE, 0, 0); 262 | bAlreadyEnding = FALSE; 263 | } 264 | -------------------------------------------------------------------------------- /Experimental Upgrades/InPlaceList.cpp: -------------------------------------------------------------------------------- 1 | // InPlaceList.cpp : implementation file 2 | // 3 | // Written by Chris Maunder 4 | // Copyright (c) 1998-2000. All Rights Reserved. 5 | // 6 | // The code contained in this file is based on the original 7 | // CInPlaceList from http://www.codeguru.com/listview 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name is included. If 13 | // the source code in this file is used in any commercial application 14 | // then acknowledgement must be made to the author of this file 15 | // (in whatever form you wish). 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // Expect bugs! 22 | // 23 | // Please use and enjoy. Please let me know of any bugs/mods/improvements 24 | // that you have found/implemented and I will fix/incorporate them into this 25 | // file. 26 | // 27 | // 6 Aug 1998 - Added CComboEdit to subclass the edit control - code provided by 28 | // Roelf Werkman . Added nID to the constructor param list. 29 | // 29 Nov 1998 - bug fix in onkeydown (Markus Irtenkauf) 30 | // 31 | ///////////////////////////////////////////////////////////////////////////// 32 | 33 | #include "stdafx.h" 34 | #include "InPlaceList.h" 35 | 36 | #include "GridCtrl.h" 37 | 38 | 39 | #ifdef _DEBUG 40 | #define new DEBUG_NEW 41 | #undef THIS_FILE 42 | static char THIS_FILE[] = __FILE__; 43 | #endif 44 | 45 | 46 | ///////////////////////////////////////////////////////////////////////////// 47 | // CComboEdit 48 | 49 | CComboEdit::CComboEdit() 50 | { 51 | } 52 | 53 | CComboEdit::~CComboEdit() 54 | { 55 | } 56 | 57 | // Stoopid win95 accelerator key problem workaround - Matt Weagle. 58 | BOOL CComboEdit::PreTranslateMessage(MSG* pMsg) 59 | { 60 | // Make sure that the keystrokes continue to the appropriate handlers 61 | if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) 62 | { 63 | ::TranslateMessage(pMsg); 64 | ::DispatchMessage(pMsg); 65 | return TRUE; 66 | } 67 | 68 | // Catch the Alt key so we don't choke if focus is going to an owner drawn button 69 | if (pMsg->message == WM_SYSCHAR) 70 | return TRUE; 71 | 72 | return CEdit::PreTranslateMessage(pMsg); 73 | } 74 | 75 | BEGIN_MESSAGE_MAP(CComboEdit, CEdit) 76 | //{{AFX_MSG_MAP(CComboEdit) 77 | ON_WM_KILLFOCUS() 78 | ON_WM_KEYDOWN() 79 | ON_WM_KEYUP() 80 | //}}AFX_MSG_MAP 81 | END_MESSAGE_MAP() 82 | 83 | ///////////////////////////////////////////////////////////////////////////// 84 | // CComboEdit message handlers 85 | 86 | void CComboEdit::OnKillFocus(CWnd* pNewWnd) 87 | { 88 | CEdit::OnKillFocus(pNewWnd); 89 | 90 | CInPlaceList* pOwner = (CInPlaceList*) GetOwner(); // This MUST be a CInPlaceList 91 | if (pOwner) 92 | pOwner->EndEdit(); 93 | } 94 | 95 | void CComboEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 96 | { 97 | if ((nChar == VK_PRIOR || nChar == VK_NEXT || 98 | nChar == VK_DOWN || nChar == VK_UP || 99 | nChar == VK_RIGHT || nChar == VK_LEFT) && 100 | (GetKeyState(VK_CONTROL) < 0 && GetDlgCtrlID() == IDC_COMBOEDIT)) 101 | { 102 | CWnd* pOwner = GetOwner(); 103 | if (pOwner) 104 | pOwner->SendMessage(WM_KEYDOWN, nChar, nRepCnt+ (((DWORD)nFlags)<<16)); 105 | return; 106 | } 107 | 108 | CEdit::OnKeyDown(nChar, nRepCnt, nFlags); 109 | } 110 | 111 | void CComboEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 112 | { 113 | if (nChar == VK_ESCAPE) 114 | { 115 | CWnd* pOwner = GetOwner(); 116 | if (pOwner) 117 | pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16)); 118 | return; 119 | } 120 | 121 | if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) 122 | { 123 | CWnd* pOwner = GetOwner(); 124 | if (pOwner) 125 | pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16)); 126 | return; 127 | } 128 | 129 | CEdit::OnKeyUp(nChar, nRepCnt, nFlags); 130 | } 131 | 132 | 133 | ///////////////////////////////////////////////////////////////////////////// 134 | // CInPlaceList 135 | 136 | CInPlaceList::CInPlaceList(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, 137 | int nRow, int nColumn, 138 | CStringArray& Items, CString sInitText, 139 | UINT nFirstChar) 140 | { 141 | m_nNumLines = 4; 142 | m_sInitText = sInitText; 143 | m_nRow = nRow; 144 | m_nCol = nColumn; 145 | m_nLastChar = 0; 146 | m_bExitOnArrows = FALSE; //(nFirstChar != VK_LBUTTON); // If mouse click brought us here, 147 | 148 | // Create the combobox 149 | DWORD dwComboStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL| 150 | CBS_AUTOHSCROLL | dwStyle; 151 | int nHeight = rect.Height(); 152 | rect.bottom = rect.bottom + m_nNumLines*nHeight + ::GetSystemMetrics(SM_CYHSCROLL); 153 | if (!Create(dwComboStyle, rect, pParent, nID)) return; 154 | 155 | // Add the strings 156 | for (int i = 0; i < Items.GetSize(); i++) 157 | AddString(Items[i]); 158 | 159 | // Get the maximum width of the text strings 160 | int nMaxLength = 0; 161 | CClientDC dc(GetParent()); 162 | CFont* pOldFont = dc.SelectObject(pParent->GetFont()); 163 | 164 | for (i = 0; i < Items.GetSize(); i++) 165 | nMaxLength = max(nMaxLength, dc.GetTextExtent(Items[i]).cx); 166 | 167 | nMaxLength += (::GetSystemMetrics(SM_CXVSCROLL) + dc.GetTextExtent(_T(" ")).cx*2); 168 | dc.SelectObject(pOldFont); 169 | 170 | if (nMaxLength > rect.Width()) 171 | rect.right = rect.left + nMaxLength; 172 | 173 | // Resize the edit window and the drop down window 174 | MoveWindow(rect); 175 | 176 | SetFont(pParent->GetFont()); 177 | SetItemHeight(-1, nHeight); 178 | 179 | SetDroppedWidth(nMaxLength); 180 | SetHorizontalExtent(0); // no horz scrolling 181 | 182 | // Set the initial text to m_sInitText 183 | if (SelectString(-1, m_sInitText) == CB_ERR) 184 | SetWindowText(m_sInitText); // No text selected, so restore what was there before 185 | 186 | // Subclass the combobox edit control if style includes CBS_DROPDOWN 187 | if ((dwStyle & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST) 188 | { 189 | m_edit.SubclassDlgItem(IDC_COMBOEDIT, this); 190 | SetFocus(); 191 | switch (nFirstChar) 192 | { 193 | case VK_LBUTTON: 194 | case VK_RETURN: m_edit.SetSel((int)_tcslen(m_sInitText), -1); return; 195 | case VK_BACK: m_edit.SetSel((int)_tcslen(m_sInitText), -1); break; 196 | case VK_DOWN: 197 | case VK_UP: 198 | case VK_RIGHT: 199 | case VK_LEFT: 200 | case VK_NEXT: 201 | case VK_PRIOR: 202 | case VK_HOME: 203 | case VK_END: m_edit.SetSel(0,-1); return; 204 | default: m_edit.SetSel(0,-1); 205 | } 206 | SendMessage(WM_CHAR, nFirstChar); 207 | } 208 | else 209 | SetFocus(); 210 | } 211 | 212 | CInPlaceList::~CInPlaceList() 213 | { 214 | } 215 | 216 | void CInPlaceList::EndEdit() 217 | { 218 | CString str; 219 | GetWindowText(str); 220 | 221 | // Send Notification to parent 222 | GV_DISPINFO dispinfo; 223 | 224 | dispinfo.hdr.hwndFrom = GetSafeHwnd(); 225 | dispinfo.hdr.idFrom = GetDlgCtrlID(); 226 | dispinfo.hdr.code = GVN_ENDLABELEDIT; 227 | 228 | dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM; 229 | dispinfo.item.row = m_nRow; 230 | dispinfo.item.col = m_nCol; 231 | dispinfo.item.strText = str; 232 | dispinfo.item.lParam = (LPARAM) m_nLastChar; 233 | 234 | CWnd* pOwner = GetOwner(); 235 | if (IsWindow(pOwner->GetSafeHwnd())) 236 | pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo ); 237 | 238 | // Close this window (PostNcDestroy will delete this) 239 | PostMessage(WM_CLOSE, 0, 0); 240 | } 241 | 242 | void CInPlaceList::PostNcDestroy() 243 | { 244 | CComboBox::PostNcDestroy(); 245 | 246 | delete this; 247 | } 248 | 249 | BEGIN_MESSAGE_MAP(CInPlaceList, CComboBox) 250 | //{{AFX_MSG_MAP(CInPlaceList) 251 | ON_WM_KILLFOCUS() 252 | ON_WM_KEYDOWN() 253 | ON_WM_KEYUP() 254 | //}}AFX_MSG_MAP 255 | END_MESSAGE_MAP() 256 | 257 | 258 | ///////////////////////////////////////////////////////////////////////////// 259 | // CInPlaceList message handlers 260 | 261 | void CInPlaceList::OnKillFocus(CWnd* pNewWnd) 262 | { 263 | CComboBox::OnKillFocus(pNewWnd); 264 | 265 | if (GetSafeHwnd() == pNewWnd->GetSafeHwnd()) 266 | return; 267 | 268 | // Only end editing on change of focus if we're using the CBS_DROPDOWNLIST style 269 | if ((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST) 270 | EndEdit(); 271 | } 272 | 273 | // If an arrow key (or associated) is pressed, then exit if 274 | // a) The Ctrl key was down, or 275 | // b) m_bExitOnArrows == TRUE 276 | void CInPlaceList::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 277 | { 278 | if ((nChar == VK_PRIOR || nChar == VK_NEXT || 279 | nChar == VK_DOWN || nChar == VK_UP || 280 | nChar == VK_RIGHT || nChar == VK_LEFT) && 281 | (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0)) 282 | { 283 | m_nLastChar = nChar; 284 | GetParent()->SetFocus(); 285 | return; 286 | } 287 | 288 | CComboBox::OnKeyDown(nChar, nRepCnt, nFlags); 289 | } 290 | 291 | // Need to keep a lookout for Tabs, Esc and Returns. 292 | void CInPlaceList::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 293 | { 294 | if (nChar == VK_ESCAPE) 295 | SetWindowText(m_sInitText); // restore previous text 296 | 297 | if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) 298 | { 299 | m_nLastChar = nChar; 300 | GetParent()->SetFocus(); // This will destroy this window 301 | return; 302 | } 303 | 304 | CComboBox::OnKeyUp(nChar, nRepCnt, nFlags); 305 | } -------------------------------------------------------------------------------- /TitleTip.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // TitleTip.cpp : implementation file 3 | // 4 | // Based on code by Zafir Anjum 5 | // 6 | // Adapted by Chris Maunder 7 | // Copyright (c) 1998-2002. All Rights Reserved. 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name and all copyright 13 | // notices remains intact. 14 | // 15 | // An email letting me know how you are using it would be nice as well. 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // For use with CGridCtrl v2.20+ 22 | // 23 | // History 24 | // 10 Apr 1999 Now accepts a LOGFONT pointer and 25 | // a tracking rect in Show(...) (Chris Maunder) 26 | // 18 Apr 1999 Resource leak in Show fixed by Daniel Gehriger 27 | // 8 Mar 2000 Added double-click fix found on codeguru 28 | // web site but forgot / can't find who contributed it 29 | // 28 Mar 2000 Aqiruse (marked with //FNA) 30 | // Titletips now use cell color 31 | // 18 Jun 2000 Delayed window creation added 32 | // 33 | ///////////////////////////////////////////////////////////////////////////// 34 | 35 | #include "stdafx.h" 36 | #include "GridCtrl.h" 37 | 38 | #ifndef GRIDCONTROL_NO_TITLETIPS 39 | 40 | #include "TitleTip.h" 41 | 42 | #ifdef _DEBUG 43 | #define new DEBUG_NEW 44 | #undef THIS_FILE 45 | static char THIS_FILE[] = __FILE__; 46 | #endif 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // CTitleTip 50 | 51 | CTitleTip::CTitleTip() 52 | { 53 | // Register the window class if it has not already been registered. 54 | WNDCLASS wndcls; 55 | HINSTANCE hInst = AfxGetInstanceHandle(); 56 | if(!(::GetClassInfo(hInst, TITLETIP_CLASSNAME, &wndcls))) 57 | { 58 | // otherwise we need to register a new class 59 | wndcls.style = CS_SAVEBITS; 60 | wndcls.lpfnWndProc = ::DefWindowProc; 61 | wndcls.cbClsExtra = wndcls.cbWndExtra = 0; 62 | wndcls.hInstance = hInst; 63 | wndcls.hIcon = NULL; 64 | wndcls.hCursor = LoadCursor( hInst, IDC_ARROW ); 65 | wndcls.hbrBackground = (HBRUSH)(COLOR_INFOBK +1); 66 | wndcls.lpszMenuName = NULL; 67 | wndcls.lpszClassName = TITLETIP_CLASSNAME; 68 | 69 | if (!AfxRegisterClass(&wndcls)) 70 | AfxThrowResourceException(); 71 | } 72 | 73 | m_dwLastLButtonDown = ULONG_MAX; 74 | m_dwDblClickMsecs = GetDoubleClickTime(); 75 | m_bCreated = FALSE; 76 | m_pParentWnd = NULL; 77 | } 78 | 79 | CTitleTip::~CTitleTip() 80 | { 81 | } 82 | 83 | 84 | BEGIN_MESSAGE_MAP(CTitleTip, CWnd) 85 | //{{AFX_MSG_MAP(CTitleTip) 86 | ON_WM_MOUSEMOVE() 87 | //}}AFX_MSG_MAP 88 | END_MESSAGE_MAP() 89 | 90 | 91 | ///////////////////////////////////////////////////////////////////////////// 92 | // CTitleTip message handlers 93 | 94 | BOOL CTitleTip::Create(CWnd * pParentWnd) 95 | { 96 | ASSERT_VALID(pParentWnd); 97 | 98 | // Already created? 99 | if (m_bCreated) 100 | return TRUE; 101 | 102 | DWORD dwStyle = WS_BORDER | WS_POPUP; 103 | DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST; 104 | m_pParentWnd = pParentWnd; 105 | 106 | m_bCreated = CreateEx(dwExStyle, TITLETIP_CLASSNAME, NULL, dwStyle, 107 | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 108 | NULL, NULL, NULL ); 109 | 110 | return m_bCreated; 111 | } 112 | 113 | BOOL CTitleTip::DestroyWindow() 114 | { 115 | m_bCreated = FALSE; 116 | 117 | return CWnd::DestroyWindow(); 118 | } 119 | 120 | // Show - Show the titletip if needed 121 | // rectTitle - The rectangle within which the original 122 | // title is constrained - in client coordinates 123 | // lpszTitleText - The text to be displayed 124 | // xoffset - Number of pixel that the text is offset from 125 | // left border of the cell 126 | void CTitleTip::Show(CRect rectTitle, LPCTSTR lpszTitleText, int xoffset /*=0*/, 127 | LPRECT lpHoverRect /*=NULL*/, 128 | const LOGFONT* lpLogFont /*=NULL*/, 129 | COLORREF crTextClr /* CLR_DEFAULT */, 130 | COLORREF crBackClr /* CLR_DEFAULT */) 131 | { 132 | if (!IsWindow(m_hWnd)) 133 | Create(m_pParentWnd); 134 | 135 | ASSERT( ::IsWindow( GetSafeHwnd() ) ); 136 | 137 | if (rectTitle.IsRectEmpty()) 138 | return; 139 | 140 | // If titletip is already displayed, don't do anything. 141 | if( IsWindowVisible() ) 142 | return; 143 | 144 | m_rectHover = (lpHoverRect != NULL)? (CRect)lpHoverRect : rectTitle; 145 | m_rectHover.right++; m_rectHover.bottom++; 146 | 147 | m_pParentWnd->ClientToScreen( m_rectHover ); 148 | ScreenToClient( m_rectHover ); 149 | 150 | // Do not display the titletip is app does not have focus 151 | if( GetFocus() == NULL ) 152 | return; 153 | 154 | // Define the rectangle outside which the titletip will be hidden. 155 | // We add a buffer of one pixel around the rectangle 156 | m_rectTitle.top = -1; 157 | m_rectTitle.left = -xoffset-1; 158 | m_rectTitle.right = rectTitle.Width()-xoffset; 159 | m_rectTitle.bottom = rectTitle.Height()+1; 160 | 161 | // Determine the width of the text 162 | m_pParentWnd->ClientToScreen( rectTitle ); 163 | 164 | CClientDC dc(this); 165 | CString strTitle = _T(""); 166 | strTitle += _T(" "); 167 | strTitle += lpszTitleText; 168 | strTitle += _T(" "); 169 | 170 | CFont font, *pOldFont = NULL; 171 | if (lpLogFont) 172 | { 173 | font.CreateFontIndirect(lpLogFont); 174 | pOldFont = dc.SelectObject( &font ); 175 | } 176 | else 177 | { 178 | // use same font as ctrl 179 | pOldFont = dc.SelectObject( m_pParentWnd->GetFont() ); 180 | } 181 | 182 | CSize size = dc.GetTextExtent( strTitle ); 183 | 184 | TEXTMETRIC tm; 185 | dc.GetTextMetrics(&tm); 186 | size.cx += tm.tmOverhang; 187 | 188 | CRect rectDisplay = rectTitle; 189 | rectDisplay.left += xoffset; 190 | rectDisplay.right = rectDisplay.left + size.cx + xoffset; 191 | 192 | // Do not display if the text fits within available space 193 | if ( rectDisplay.right > rectTitle.right-xoffset ) 194 | { 195 | // Show the titletip 196 | SetWindowPos( &wndTop, rectDisplay.left, rectDisplay.top, 197 | rectDisplay.Width(), rectDisplay.Height(), 198 | SWP_SHOWWINDOW|SWP_NOACTIVATE ); 199 | 200 | // FNA - handle colors correctly 201 | if (crBackClr != CLR_DEFAULT) 202 | { 203 | CBrush backBrush(crBackClr); 204 | CBrush* pOldBrush = dc.SelectObject(&backBrush); 205 | CRect rect; 206 | dc.GetClipBox(&rect); // Erase the area needed 207 | 208 | dc.PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); 209 | dc.SelectObject(pOldBrush); 210 | } 211 | // Set color 212 | if (crTextClr != CLR_DEFAULT)//FNA 213 | dc.SetTextColor(crTextClr);//FA 214 | 215 | dc.SetBkMode( TRANSPARENT ); 216 | dc.TextOut( 0, 0, strTitle ); 217 | SetCapture(); 218 | } 219 | 220 | dc.SelectObject( pOldFont ); 221 | } 222 | 223 | void CTitleTip::Hide() 224 | { 225 | if (!::IsWindow(GetSafeHwnd())) 226 | return; 227 | 228 | if (GetCapture()->GetSafeHwnd() == GetSafeHwnd()) 229 | ReleaseCapture(); 230 | 231 | ShowWindow( SW_HIDE ); 232 | } 233 | 234 | void CTitleTip::OnMouseMove(UINT nFlags, CPoint point) 235 | { 236 | if (!m_rectHover.PtInRect(point)) 237 | { 238 | Hide(); 239 | 240 | // Forward the message 241 | ClientToScreen( &point ); 242 | CWnd *pWnd = WindowFromPoint( point ); 243 | if ( pWnd == this ) 244 | pWnd = m_pParentWnd; 245 | 246 | int hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); 247 | 248 | if (hittest == HTCLIENT) { 249 | pWnd->ScreenToClient( &point ); 250 | pWnd->PostMessage( WM_MOUSEMOVE, nFlags, MAKELONG(point.x,point.y) ); 251 | } else { 252 | pWnd->PostMessage( WM_NCMOUSEMOVE, hittest, MAKELONG(point.x,point.y) ); 253 | } 254 | } 255 | } 256 | 257 | BOOL CTitleTip::PreTranslateMessage(MSG* pMsg) 258 | { 259 | // Used to qualify WM_LBUTTONDOWN messages as double-clicks 260 | DWORD dwTick=0; 261 | BOOL bDoubleClick=FALSE; 262 | 263 | CWnd *pWnd; 264 | int hittest; 265 | switch (pMsg->message) 266 | { 267 | case WM_LBUTTONDOWN: 268 | // Get tick count since last LButtonDown 269 | dwTick = GetTickCount(); 270 | bDoubleClick = ((dwTick - m_dwLastLButtonDown) <= m_dwDblClickMsecs); 271 | m_dwLastLButtonDown = dwTick; 272 | // NOTE: DO NOT ADD break; STATEMENT HERE! Let code fall through 273 | 274 | case WM_RBUTTONDOWN: 275 | case WM_MBUTTONDOWN: 276 | { 277 | POINTS pts = MAKEPOINTS( pMsg->lParam ); 278 | POINT point; 279 | point.x = pts.x; 280 | point.y = pts.y; 281 | 282 | ClientToScreen( &point ); 283 | Hide(); 284 | 285 | pWnd = WindowFromPoint( point ); 286 | if (!pWnd) 287 | return CWnd::PreTranslateMessage(pMsg); 288 | 289 | if( pWnd->GetSafeHwnd() == GetSafeHwnd()) 290 | pWnd = m_pParentWnd; 291 | 292 | hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); 293 | 294 | if (hittest == HTCLIENT) 295 | { 296 | pWnd->ScreenToClient( &point ); 297 | pMsg->lParam = MAKELONG(point.x,point.y); 298 | } 299 | else 300 | { 301 | switch (pMsg->message) { 302 | case WM_LBUTTONDOWN: 303 | pMsg->message = WM_NCLBUTTONDOWN; 304 | break; 305 | case WM_RBUTTONDOWN: 306 | pMsg->message = WM_NCRBUTTONDOWN; 307 | break; 308 | case WM_MBUTTONDOWN: 309 | pMsg->message = WM_NCMBUTTONDOWN; 310 | break; 311 | } 312 | pMsg->wParam = hittest; 313 | pMsg->lParam = MAKELONG(point.x,point.y); 314 | } 315 | 316 | 317 | // If this is the 2nd WM_LBUTTONDOWN in x milliseconds, 318 | // post a WM_LBUTTONDBLCLK message instead of a single click. 319 | pWnd->PostMessage( bDoubleClick ? WM_LBUTTONDBLCLK : pMsg->message, 320 | pMsg->wParam, 321 | pMsg->lParam); 322 | return TRUE; 323 | } 324 | 325 | case WM_KEYDOWN: 326 | case WM_SYSKEYDOWN: 327 | Hide(); 328 | m_pParentWnd->PostMessage( pMsg->message, pMsg->wParam, pMsg->lParam ); 329 | return TRUE; 330 | } 331 | 332 | if( GetFocus() == NULL ) 333 | { 334 | Hide(); 335 | return TRUE; 336 | } 337 | 338 | return CWnd::PreTranslateMessage(pMsg); 339 | } 340 | 341 | #endif // GRIDCONTROL_NO_TITLETIPS -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | https://www.codeproject.com/info/cpol10.aspx 2 | 3 | The Code Project Open License (CPOL) 1.02 4 | The Code Project Open License (CPOL) is intended to provide developers who choose to share their code with a license that protects them and provides users of their code with a clear statement regarding how the code can be used. 5 | 6 | The CPOL is our gift to the community. We encourage everyone to use this license if they wish regardless of whether the code is posted on CodeProject.com. 7 | 8 | Preamble 9 | This License governs Your use of the Work. This License is intended to allow developers to use the Source Code and Executable Files provided as part of the Work in any application in any form. 10 | 11 | The main points subject to the terms of the License are: 12 | 13 | Source Code and Executable Files can be used in commercial applications; 14 | Source Code and Executable Files can be redistributed; and 15 | Source Code can be modified to create derivative works. 16 | No claim of suitability, guarantee, or any warranty whatsoever is provided. The software is provided "as-is". 17 | The Article(s) accompanying the Work may not be distributed or republished without the Author's consent 18 | This License is entered between You, the individual or other entity reading or otherwise making use of the Work licensed pursuant to this License and the individual or other entity which offers the Work under the terms of this License ("Author"). 19 | 20 | License 21 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CODE PROJECT OPEN LICENSE ("LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 22 | 23 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HEREIN, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE AUTHOR GRANTS YOU THE RIGHTS CONTAINED HEREIN IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. IF YOU DO NOT AGREE TO ACCEPT AND BE BOUND BY THE TERMS OF THIS LICENSE, YOU CANNOT MAKE ANY USE OF THE WORK. 24 | 25 | Definitions. 26 | "Articles" means, collectively, all articles written by Author which describes how the Source Code and Executable Files for the Work may be used by a user. 27 | "Author" means the individual or entity that offers the Work under the terms of this License. 28 | "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works. 29 | "Executable Files" refer to the executables, binary files, configuration and any required data files included in the Work. 30 | "Publisher" means the provider of the website, magazine, CD-ROM, DVD or other medium from or by which the Work is obtained by You. 31 | "Source Code" refers to the collection of source code and configuration files used to create the Executable Files. 32 | "Standard Version" refers to such a Work if it has not been modified, or has been modified in accordance with the consent of the Author, such consent being in the full discretion of the Author. 33 | "Work" refers to the collection of files distributed by the Publisher, including the Source Code, Executable Files, binaries, data files, documentation, whitepapers and the Articles. 34 | "You" is you, an individual or entity wishing to use the Work and exercise your rights under this License. 35 | Fair Use/Fair Use Rights. Nothing in this License is intended to reduce, limit, or restrict any rights arising from fair use, fair dealing, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws. 36 | License Grant. Subject to the terms and conditions of this License, the Author hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: 37 | You may use the standard version of the Source Code or Executable Files in Your own applications. 38 | You may apply bug fixes, portability fixes and other modifications obtained from the Public Domain or from the Author. A Work modified in such a way shall still be considered the standard version and will be subject to this License. 39 | You may otherwise modify Your copy of this Work (excluding the Articles) in any way to create a Derivative Work, provided that You insert a prominent notice in each changed file stating how, when and where You changed that file. 40 | You may distribute the standard version of the Executable Files and Source Code or Derivative Work in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution. 41 | The Articles discussing the Work published in any form by the author may not be distributed or republished without the Author's consent. The author retains copyright to any such Articles. You may use the Executable Files and Source Code pursuant to this License but you may not repost or republish or otherwise distribute or make available the Articles, without the prior written consent of the Author. 42 | Any subroutines or modules supplied by You and linked into the Source Code or Executable Files of this Work shall not be considered part of this Work and will not be subject to the terms of this License. 43 | Patent License. Subject to the terms and conditions of this License, each Author hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, import, and otherwise transfer the Work. 44 | Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: 45 | You agree not to remove any of the original copyright, patent, trademark, and attribution notices and associated disclaimers that may appear in the Source Code or Executable Files. 46 | You agree not to advertise or in any way imply that this Work is a product of Your own. 47 | The name of the Author may not be used to endorse or promote products derived from the Work without the prior written consent of the Author. 48 | You agree not to sell, lease, or rent any part of the Work. This does not restrict you from including the Work or any part of the Work inside a larger software distribution that itself is being sold. The Work by itself, though, cannot be sold, leased or rented. 49 | You may distribute the Executable Files and Source Code only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy of the Executable Files or Source Code You distribute and ensure that anyone receiving such Executable Files and Source Code agrees that the terms of this License apply to such Executable Files and/or Source Code. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute the Executable Files or Source Code with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License. 50 | You agree not to use the Work for illegal, immoral or improper purposes, or on pages containing illegal, immoral or improper material. The Work is subject to applicable export laws. You agree to comply with all such laws and regulations that may apply to the Work after Your receipt of the Work. 51 | Representations, Warranties and Disclaimer. THIS WORK IS PROVIDED "AS IS", "WHERE IS" AND "AS AVAILABLE", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OR CONDITIONS OR GUARANTEES. YOU, THE USER, ASSUME ALL RISK IN ITS USE, INCLUDING COPYRIGHT INFRINGEMENT, PATENT INFRINGEMENT, SUITABILITY, ETC. AUTHOR EXPRESSLY DISCLAIMS ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES OR CONDITIONS, INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY OR FITNESS FOR A PARTICULAR PURPOSE, OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT, OR THAT THE WORK (OR ANY PORTION THEREOF) IS CORRECT, USEFUL, BUG-FREE OR FREE OF VIRUSES. YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE WORK OR DERIVATIVE WORKS. 52 | Indemnity. You agree to defend, indemnify and hold harmless the Author and the Publisher from and against any claims, suits, losses, damages, liabilities, costs, and expenses (including reasonable legal or attorneys’ fees) resulting from or relating to any use of the Work by You. 53 | Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL THE AUTHOR OR THE PUBLISHER BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK OR OTHERWISE, EVEN IF THE AUTHOR OR THE PUBLISHER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 54 | Termination. 55 | This License and the rights granted hereunder will terminate automatically upon any breach by You of any term of this License. Individuals or entities who have received Derivative Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 6, 7, 8, 9, 10 and 11 will survive any termination of this License. 56 | If You bring a copyright, trademark, patent or any other infringement claim against any contributor over infringements You claim are made by the Work, your License from such contributor to the Work ends automatically. 57 | Subject to the above terms and conditions, this License is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, the Author reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 58 | Publisher. The parties hereby confirm that the Publisher shall not, under any circumstances, be responsible for and shall not have any liability in respect of the subject matter of this License. The Publisher makes no warranty whatsoever in connection with the Work and shall not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. The Publisher reserves the right to cease making the Work available to You at any time without notice 59 | Miscellaneous 60 | This License shall be governed by the laws of the location of the head office of the Author or if the Author is an individual, the laws of location of the principal place of residence of the Author. 61 | If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this License, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 62 | No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. 63 | This License constitutes the entire agreement between the parties with respect to the Work licensed herein. There are no understandings, agreements or representations with respect to the Work not specified herein. The Author shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Author and You. 64 | -------------------------------------------------------------------------------- /Experimental Upgrades/TitleTip.cpp: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////// 2 | // TitleTip.cpp : implementation file 3 | // 4 | // Adapted from code written by Zafir Anjum 5 | // 6 | // Modifed 10 Apr 1999 Now accepts a LOGFONT pointer and 7 | // a tracking rect in Show(...) (Chris Maunder) 8 | // 18 Apr 1999 Resource leak in Show fixed by Daniel Gehriger 9 | // 7 Jan 2000 Added multiline capabilities, and the ability to 10 | // specify the maximum length of the tip (Mark Findlay) 11 | 12 | 13 | #include "stdafx.h" 14 | #include "TitleTip.h" 15 | 16 | #ifdef _DEBUG 17 | #define new DEBUG_NEW 18 | #undef THIS_FILE 19 | static char THIS_FILE[] = __FILE__; 20 | #endif 21 | 22 | ///////////////////////////////////////////////////////////////////////////// 23 | // CTitleTip 24 | 25 | CTitleTip::CTitleTip() 26 | { 27 | // Register the window class if it has not already been registered. 28 | WNDCLASS wndcls; 29 | HINSTANCE hInst = AfxGetInstanceHandle(); 30 | if(!(::GetClassInfo(hInst, TITLETIP_CLASSNAME, &wndcls))) 31 | { 32 | // otherwise we need to register a new class 33 | wndcls.style = CS_SAVEBITS; 34 | wndcls.lpfnWndProc = ::DefWindowProc; 35 | wndcls.cbClsExtra = wndcls.cbWndExtra = 0; 36 | wndcls.hInstance = hInst; 37 | wndcls.hIcon = NULL; 38 | wndcls.hCursor = LoadCursor( hInst, IDC_ARROW ); 39 | wndcls.hbrBackground = (HBRUSH)(COLOR_INFOBK + 1); 40 | wndcls.lpszMenuName = NULL; 41 | wndcls.lpszClassName = TITLETIP_CLASSNAME; 42 | 43 | if (!AfxRegisterClass(&wndcls)) 44 | AfxThrowResourceException(); 45 | } 46 | } 47 | 48 | CTitleTip::~CTitleTip() 49 | { 50 | if (::IsWindow(m_hWnd)) 51 | DestroyWindow(); 52 | } 53 | 54 | 55 | BEGIN_MESSAGE_MAP(CTitleTip, CWnd) 56 | //{{AFX_MSG_MAP(CTitleTip) 57 | ON_WM_MOUSEMOVE() 58 | ON_WM_PAINT() 59 | ON_WM_SYSKEYDOWN() 60 | ON_WM_KEYDOWN() 61 | //}}AFX_MSG_MAP 62 | END_MESSAGE_MAP() 63 | 64 | 65 | ///////////////////////////////////////////////////////////////////////////// 66 | // CTitleTip message handlers 67 | 68 | BOOL CTitleTip::Create(CWnd * pParentWnd) 69 | { 70 | ASSERT_VALID(pParentWnd); 71 | 72 | DWORD dwStyle = WS_BORDER | WS_POPUP; 73 | DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST; 74 | m_pParentWnd = pParentWnd; 75 | 76 | return CreateEx(dwExStyle, TITLETIP_CLASSNAME, NULL, dwStyle, 77 | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 78 | NULL, NULL, NULL ); 79 | } 80 | 81 | 82 | // Show - Show the titletip if needed 83 | // rectTitle - The rectangle within which the original 84 | // title is constrained - in client coordinates 85 | // lpszTitleText - The text to be displayed 86 | // xoffset - Number of pixel that the text is offset from 87 | // left border of the cell 88 | void CTitleTip::Show(CRect rectTitle, LPCTSTR lpszTitleText, 89 | int xoffset /*=0*/, int nMaxChars /*=-1*/, 90 | LPRECT lpHoverRect /*=NULL*/, 91 | LPLOGFONT lpLogFont /*=NULL*/, 92 | DWORD dwFormat /*=...*/) 93 | { 94 | ASSERT( ::IsWindow( GetSafeHwnd() ) ); 95 | 96 | if (rectTitle.IsRectEmpty()) 97 | return; 98 | 99 | // If titletip is already displayed, don't do anything. 100 | if( IsWindowVisible() ) 101 | return; 102 | 103 | m_rectHover = (lpHoverRect != NULL)? lpHoverRect : rectTitle; 104 | m_rectHover.right++; m_rectHover.bottom++; 105 | 106 | m_pParentWnd->ClientToScreen( m_rectHover ); 107 | ScreenToClient( m_rectHover ); 108 | 109 | 110 | // Do not display the titletip is app does not have focus 111 | if( GetFocus() == NULL ) 112 | return; 113 | 114 | // Define the rectangle outside which the titletip will be hidden. 115 | // We add a buffer of one pixel around the rectangle 116 | m_rectTitle.top = -1; 117 | m_rectTitle.left = -xoffset-1; 118 | m_rectTitle.right = rectTitle.Width()-xoffset; 119 | m_rectTitle.bottom = rectTitle.Height()+1; 120 | 121 | // Determine the width of the text 122 | m_pParentWnd->ClientToScreen( rectTitle ); 123 | 124 | CClientDC dc(this); 125 | m_strTitle = _T(""); 126 | //m_strTitle += _T(" "); 127 | m_strTitle += lpszTitleText; 128 | //m_strTitle += _T(" "); 129 | 130 | CFont font, *pOldFont = NULL; 131 | if (lpLogFont) 132 | { 133 | font.CreateFontIndirect(lpLogFont); 134 | pOldFont = dc.SelectObject( &font ); 135 | } 136 | else 137 | { 138 | // use same font as ctrl 139 | pOldFont = dc.SelectObject( m_pParentWnd->GetFont() ); 140 | } 141 | 142 | CSize size = dc.GetTextExtent( m_strTitle ); 143 | 144 | TEXTMETRIC tm; 145 | dc.GetTextMetrics(&tm); 146 | size.cx += tm.tmOverhang; 147 | 148 | dc.SelectObject( pOldFont ); 149 | 150 | m_rectDisplay = rectTitle; 151 | m_rectDisplay.left += xoffset-1; 152 | m_rectDisplay.top += 0; 153 | m_rectDisplay.right = m_rectDisplay.left + size.cx + xoffset; 154 | m_rectDisplay.bottom = m_rectDisplay.top + size.cy; 155 | 156 | // Do not display if the text fits within available space 157 | if ( m_rectDisplay.right <= rectTitle.right-xoffset ) 158 | return; 159 | 160 | // We will use avg char width to set max tooltip width 161 | int nMaxTooltipWidth = -1; 162 | if (nMaxChars > 0) 163 | { 164 | int nMaxTooltipWidth = (tm.tmAveCharWidth * nMaxChars); 165 | if (nMaxTooltipWidth < 0) 166 | nMaxTooltipWidth *= -1; 167 | 168 | // Rect display to be set to max chars 169 | if (m_rectDisplay.Width() > nMaxTooltipWidth) 170 | m_rectDisplay.right = m_rectDisplay.left + nMaxTooltipWidth; 171 | } 172 | 173 | //*************************************************************************************** 174 | //Adjust the dimensions of the rect to fit within the client 175 | 176 | // Get the coordinates of the parents client area. (In this case the ListView's client 177 | // area) and convert coordinates to those of the tooltip. 178 | CRect rectClient; 179 | m_pParentWnd->GetClientRect( rectClient ); 180 | m_pParentWnd->ClientToScreen( rectClient ); 181 | 182 | 183 | // ------------------------------------------------------------------------------ 184 | // Use the screen's right edge as the right hand border, not the right edge of the client. 185 | // You can comment this out to use the right client as the border. 186 | CWindowDC wdc(NULL); 187 | rectClient.right = GetDeviceCaps(wdc, HORZRES) - 8; 188 | rectClient.bottom = GetDeviceCaps(wdc, VERTRES) - 8; 189 | //--------------------------------------------------------------------------------------- 190 | 191 | 192 | //If the right edge exceeds the right edge of the client: 193 | // see how much room there is to move the display to the left and adjust the 194 | // rectangle that far to the left. If the rect still exceeds the right edge, clip 195 | // the right edge to match the client right edge. 196 | // 197 | // Does the right display edge exceed the right client edge? 198 | if (m_rectDisplay.right > rectClient.right) 199 | { 200 | // establish what is available left shift wise and what is needed 201 | int nAvail = 0; 202 | int nNeeded = m_rectDisplay.right - rectClient.right; 203 | 204 | if (m_rectDisplay.left > rectClient.left) 205 | nAvail = m_rectDisplay.left - rectClient.left; 206 | 207 | // is there room to move left? 208 | if (nAvail >= nNeeded) 209 | { 210 | m_rectDisplay.OffsetRect(-nNeeded,0); // yes, move all that is needed 211 | // increase the size of the window that will be inspected to see if the 212 | // cursor has gone outside of the tooltip area by the number of units we 213 | // offset our display rect. 214 | m_rectTitle.right += nNeeded; 215 | } 216 | else 217 | { 218 | m_rectDisplay.OffsetRect(-nAvail,0); // no, at least move to left edge of client 219 | // increase the size of the window that will be inspected to see if the 220 | // cursor has gone outside of the tooltip area by the number of units we 221 | // offset our display rect. 222 | m_rectTitle.right += nAvail; 223 | } 224 | 225 | // Did we move enough? If not, clip right edge to match client right edge 226 | if (m_rectDisplay.right > rectClient.right) 227 | m_rectDisplay.right = rectClient.right; 228 | } 229 | 230 | 231 | //If the left edge exceeds the left edge of the client: 232 | // see how much room there is to move the display to the right and adjust the 233 | // rectangle that far to the right. If the rect still exceeds the left edge, clip 234 | // the left edge to match the client left edge. 235 | // 236 | // Does the left display edge exceed the left client edge? 237 | if (m_rectDisplay.left < rectClient.left) 238 | { 239 | // establish what is available right shift wise and what is needed 240 | int nAvail = 0; 241 | int nNeeded = rectClient.left - m_rectDisplay.left; 242 | 243 | if (m_rectDisplay.right < rectClient.right) 244 | nAvail = rectClient.right - m_rectDisplay.right; 245 | 246 | // is there room to move left? 247 | if (nAvail >= nNeeded) 248 | { 249 | m_rectDisplay.OffsetRect(+nNeeded,0); // yes, move all that is needed 250 | // increase the size of the window that will be inspected to see if the 251 | // cursor has gone outside of the tooltip area by the number of units we 252 | // offset our display rect. 253 | m_rectTitle.left -= nNeeded; 254 | } 255 | else 256 | { 257 | m_rectDisplay.OffsetRect(+nAvail,0); // no, at least move to left edge of client 258 | // increase the size of the window that will be inspected to see if the 259 | // cursor has gone outside of the tooltip area by the number of units we 260 | // offset our display rect. 261 | m_rectTitle.left -= nAvail; 262 | } 263 | 264 | // Did we move enough? If not, clip left edge to match client left edge 265 | if (m_rectDisplay.left < rectClient.left) 266 | m_rectDisplay.left = rectClient.left; 267 | } 268 | 269 | 270 | // if the calculated width > maxwidth set above then truncate 271 | if (nMaxTooltipWidth > 0 && m_rectDisplay.Width() > nMaxTooltipWidth) 272 | m_rectDisplay.right = m_rectDisplay.left + nMaxTooltipWidth; 273 | 274 | //*************************************************************************************** 275 | 276 | // Use a "work" rect to calculate the bottom. This work rect will be inset 277 | // slightly from the rect we have just created so the tooltip does not touch 278 | // the sides. 279 | CRect rectCalc = m_rectDisplay; 280 | 281 | // rectCalc.top += 1; 282 | 283 | int nHeight = dc.DrawText(m_strTitle, rectCalc, dwFormat | DT_CALCRECT); 284 | m_dwFormat = dwFormat; 285 | 286 | // If this is a single line, shorten the display to get rid of any excess blank space 287 | if (nHeight == tm.tmHeight) 288 | { 289 | rectCalc.right = rectCalc.left + size.cx + 3; 290 | } 291 | 292 | 293 | m_rectDisplay.bottom = m_rectDisplay.top + nHeight; 294 | 295 | // ensure the tooltip does not exceed the bottom of the screen 296 | if (m_rectDisplay.bottom > rectClient.bottom) 297 | { 298 | m_rectDisplay.bottom = rectClient.bottom; 299 | rectCalc.bottom = rectClient.bottom; 300 | } 301 | 302 | SetWindowPos( &wndTop, 303 | m_rectDisplay.left, 304 | m_rectDisplay.top, 305 | m_rectDisplay.Width(), 306 | m_rectDisplay.Height(), 307 | SWP_SHOWWINDOW|SWP_NOACTIVATE ); 308 | SetCapture(); 309 | } 310 | 311 | void CTitleTip::Hide() 312 | { 313 | if (!::IsWindow(GetSafeHwnd())) 314 | return; 315 | 316 | if (GetCapture()->GetSafeHwnd() == GetSafeHwnd()) 317 | ReleaseCapture(); 318 | 319 | ShowWindow( SW_HIDE ); 320 | } 321 | 322 | void CTitleTip::OnMouseMove(UINT nFlags, CPoint point) 323 | { 324 | if (!m_rectHover.PtInRect(point)) 325 | { 326 | Hide(); 327 | 328 | // Forward the message 329 | ClientToScreen( &point ); 330 | CWnd *pWnd = WindowFromPoint( point ); 331 | if ( pWnd == this ) 332 | pWnd = m_pParentWnd; 333 | 334 | int hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); 335 | 336 | if (hittest == HTCLIENT) 337 | { 338 | pWnd->ScreenToClient( &point ); 339 | pWnd->PostMessage( WM_MOUSEMOVE, nFlags, MAKELONG(point.x,point.y) ); 340 | } 341 | else 342 | pWnd->PostMessage( WM_NCMOUSEMOVE, hittest, MAKELONG(point.x,point.y) ); 343 | } 344 | } 345 | 346 | BOOL CTitleTip::PreTranslateMessage(MSG* pMsg) 347 | { 348 | CWnd *pWnd; 349 | int hittest; 350 | switch (pMsg->message) 351 | { 352 | case WM_LBUTTONDOWN: 353 | case WM_RBUTTONDOWN: 354 | case WM_MBUTTONDOWN: 355 | POINTS pts = MAKEPOINTS( pMsg->lParam ); 356 | POINT point; 357 | point.x = pts.x; 358 | point.y = pts.y; 359 | ClientToScreen( &point ); 360 | pWnd = WindowFromPoint( point ); 361 | if( pWnd == this ) 362 | pWnd = m_pParentWnd; 363 | 364 | hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); 365 | 366 | if (hittest == HTCLIENT) 367 | { 368 | pWnd->ScreenToClient( &point ); 369 | pMsg->lParam = MAKELONG(point.x,point.y); 370 | } 371 | else 372 | { 373 | switch (pMsg->message) 374 | { 375 | case WM_LBUTTONDOWN: 376 | pMsg->message = WM_NCLBUTTONDOWN; 377 | break; 378 | case WM_RBUTTONDOWN: 379 | pMsg->message = WM_NCRBUTTONDOWN; 380 | break; 381 | case WM_MBUTTONDOWN: 382 | pMsg->message = WM_NCMBUTTONDOWN; 383 | break; 384 | } 385 | pMsg->wParam = hittest; 386 | pMsg->lParam = MAKELONG(point.x,point.y); 387 | } 388 | 389 | Hide(); 390 | pWnd->PostMessage(pMsg->message,pMsg->wParam,pMsg->lParam); 391 | return TRUE; 392 | 393 | case WM_KEYDOWN: 394 | case WM_SYSKEYDOWN: 395 | Hide(); 396 | m_pParentWnd->PostMessage( pMsg->message, pMsg->wParam, pMsg->lParam ); 397 | return TRUE; 398 | } 399 | 400 | if( GetFocus() == NULL ) 401 | { 402 | Hide(); 403 | return TRUE; 404 | } 405 | 406 | return CWnd::PreTranslateMessage(pMsg); 407 | } 408 | 409 | void CTitleTip::OnPaint() 410 | { 411 | CPaintDC dc(this); // device context for painting 412 | 413 | TEXTMETRIC tm; 414 | dc.GetTextMetrics(&tm); 415 | 416 | CFont *pFont = m_pParentWnd->GetFont(); // use same font as ctrl 417 | CFont *pFontDC = dc.SelectObject( pFont ); 418 | int nHeight=0; 419 | 420 | CRect rect = m_rectDisplay; 421 | ScreenToClient(rect); 422 | 423 | dc.SetBkMode( TRANSPARENT ); 424 | 425 | nHeight = dc.DrawText(m_strTitle, rect, m_dwFormat); 426 | 427 | dc.SelectObject( pFontDC ); 428 | 429 | // Do not call CWnd::OnPaint() for painting messages 430 | } 431 | 432 | void CTitleTip::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 433 | { 434 | Hide(); 435 | CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags); 436 | } 437 | 438 | void CTitleTip::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 439 | { 440 | Hide(); 441 | CWnd::OnKeyDown(nChar, nRepCnt, nFlags); 442 | } 443 | -------------------------------------------------------------------------------- /GridCellBase.cpp: -------------------------------------------------------------------------------- 1 | // GridCellBase.cpp : implementation file 2 | // 3 | // MFC Grid Control - Main grid cell base class 4 | // 5 | // Provides the implementation for the base cell type of the 6 | // grid control. No data is stored (except for state) but default 7 | // implementations of drawing, printingetc provided. MUST be derived 8 | // from to be used. 9 | // 10 | // Written by Chris Maunder 11 | // Copyright (c) 1998-2005. All Rights Reserved. 12 | // 13 | // This code may be used in compiled form in any way you desire. This 14 | // file may be redistributed unmodified by any means PROVIDING it is 15 | // not sold for profit without the authors written consent, and 16 | // providing that this notice and the authors name and all copyright 17 | // notices remains intact. 18 | // 19 | // An email letting me know how you are using it would be nice as well. 20 | // 21 | // This file is provided "as is" with no expressed or implied warranty. 22 | // The author accepts no liability for any damage/loss of business that 23 | // this product may cause. 24 | // 25 | // For use with CGridCtrl v2.22+ 26 | // 27 | // History: 28 | // Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase 29 | // C Maunder - 19 May 2000 - Fixed sort arrow drawing (Ivan Ilinov) 30 | // C Maunder - 29 Aug 2000 - operator= checks for NULL font before setting (Martin Richter) 31 | // C Maunder - 15 Oct 2000 - GetTextExtent fixed (Martin Richter) 32 | // C Maunder - 1 Jan 2001 - Added ValidateEdit 33 | // Yogurt - 13 Mar 2004 - GetCellExtent fixed 34 | // 35 | // NOTES: Each grid cell should take care of it's own drawing, though the Draw() 36 | // method takes an "erase background" paramter that is called if the grid 37 | // decides to draw the entire grid background in on hit. Certain ambient 38 | // properties such as the default font to use, and hints on how to draw 39 | // fixed cells should be fetched from the parent grid. The grid trusts the 40 | // cells will behave in a certain way, and the cells trust the grid will 41 | // supply accurate information. 42 | // 43 | ///////////////////////////////////////////////////////////////////////////// 44 | 45 | #include "stdafx.h" 46 | #include "GridCtrl.h" 47 | #include "GridCellBase.h" 48 | 49 | #ifdef _DEBUG 50 | #define new DEBUG_NEW 51 | #undef THIS_FILE 52 | static char THIS_FILE[] = __FILE__; 53 | #endif 54 | 55 | IMPLEMENT_DYNAMIC(CGridCellBase, CObject) 56 | 57 | ///////////////////////////////////////////////////////////////////////////// 58 | // GridCellBase 59 | 60 | CGridCellBase::CGridCellBase() 61 | { 62 | Reset(); 63 | } 64 | 65 | CGridCellBase::~CGridCellBase() 66 | { 67 | } 68 | 69 | ///////////////////////////////////////////////////////////////////////////// 70 | // GridCellBase Operations 71 | 72 | void CGridCellBase::Reset() 73 | { 74 | m_nState = 0; 75 | } 76 | 77 | void CGridCellBase::operator=(const CGridCellBase& cell) 78 | { 79 | if (this == &cell) return; 80 | 81 | SetGrid(cell.GetGrid()); // do first in case of dependencies 82 | 83 | SetText(cell.GetText()); 84 | SetImage(cell.GetImage()); 85 | SetData(cell.GetData()); 86 | SetState(cell.GetState()); 87 | SetFormat(cell.GetFormat()); 88 | SetTextClr(cell.GetTextClr()); 89 | SetBackClr(cell.GetBackClr()); 90 | SetFont(cell.IsDefaultFont()? NULL : cell.GetFont()); 91 | SetMargin(cell.GetMargin()); 92 | } 93 | 94 | ///////////////////////////////////////////////////////////////////////////// 95 | // CGridCellBase Attributes 96 | 97 | // Returns a pointer to a cell that holds default values for this particular type of cell 98 | CGridCellBase* CGridCellBase::GetDefaultCell() const 99 | { 100 | if (GetGrid()) 101 | return GetGrid()->GetDefaultCell(IsFixedRow(), IsFixedCol()); 102 | return NULL; 103 | } 104 | 105 | 106 | ///////////////////////////////////////////////////////////////////////////// 107 | // CGridCellBase Operations 108 | 109 | // EFW - Various changes to make it draw cells better when using alternate 110 | // color schemes. Also removed printing references as that's now done 111 | // by PrintCell() and fixed the sort marker so that it doesn't draw out 112 | // of bounds. 113 | BOOL CGridCellBase::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/) 114 | { 115 | // Note - all through this function we totally brutalise 'rect'. Do not 116 | // depend on it's value being that which was passed in. 117 | 118 | CGridCtrl* pGrid = GetGrid(); 119 | ASSERT(pGrid); 120 | 121 | if (!pGrid || !pDC) 122 | return FALSE; 123 | 124 | if( rect.Width() <= 0 || rect.Height() <= 0) // prevents imagelist item from drawing even 125 | return FALSE; // though cell is hidden 126 | 127 | //TRACE3("Drawing %scell %d, %d\n", IsFixed()? _T("Fixed ") : _T(""), nRow, nCol); 128 | 129 | int nSavedDC = pDC->SaveDC(); 130 | pDC->SetBkMode(TRANSPARENT); 131 | 132 | // Get the default cell implementation for this kind of cell. We use it if this cell 133 | // has anything marked as "default" 134 | CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); 135 | if (!pDefaultCell) 136 | return FALSE; 137 | 138 | // Set up text and background colours 139 | COLORREF TextClr, TextBkClr; 140 | 141 | TextClr = (GetTextClr() == CLR_DEFAULT)? pDefaultCell->GetTextClr() : GetTextClr(); 142 | if (GetBackClr() == CLR_DEFAULT) 143 | TextBkClr = pDefaultCell->GetBackClr(); 144 | else 145 | { 146 | bEraseBkgnd = TRUE; 147 | TextBkClr = GetBackClr(); 148 | } 149 | 150 | COLORREF FrameClr = GetFrameClr(); 151 | 152 | // Draw cell background and highlighting (if necessary) 153 | if ( IsFocused() || IsDropHighlighted() ) 154 | { 155 | // Always draw even in list mode so that we can tell where the 156 | // cursor is at. Use the highlight colors though. 157 | if(GetState() & GVIS_SELECTED) 158 | { 159 | TextBkClr = ::GetSysColor(COLOR_HIGHLIGHT); 160 | TextClr = ::GetSysColor(COLOR_HIGHLIGHTTEXT); 161 | bEraseBkgnd = TRUE; 162 | } 163 | 164 | if (bEraseBkgnd) 165 | { 166 | rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom 167 | TRY 168 | { 169 | CBrush brush(TextBkClr); 170 | pDC->FillRect(rect, &brush); 171 | } 172 | CATCH(CResourceException, e) 173 | { 174 | //e->ReportError(); 175 | } 176 | END_CATCH 177 | rect.right--; rect.bottom--; 178 | } 179 | 180 | if (pGrid->GetFrameFocusCell()) 181 | { 182 | FrameClr = TextClr; 183 | } 184 | 185 | //rect.DeflateRect(0,1,1,1); - Removed by Yogurt 186 | } 187 | else if ((GetState() & GVIS_SELECTED)) 188 | { 189 | rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom 190 | pDC->FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT)); 191 | rect.right--; rect.bottom--; 192 | pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); 193 | } 194 | else 195 | { 196 | if (bEraseBkgnd) 197 | { 198 | rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom 199 | CBrush brush(TextBkClr); 200 | pDC->FillRect(rect, &brush); 201 | rect.right--; rect.bottom--; 202 | } 203 | pDC->SetTextColor(TextClr); 204 | } 205 | 206 | if (FrameClr != CLR_DEFAULT) { 207 | // Don't adjust frame rect if no grid lines so that the 208 | // whole cell is enclosed. 209 | if (pGrid->GetGridLines() == GVL_NONE) 210 | { 211 | rect.right++; 212 | rect.bottom++; 213 | } 214 | 215 | // Use same color as text to outline the cell so that it shows 216 | // up if the background is black. 217 | TRY 218 | { 219 | CBrush brush(FrameClr); 220 | pDC->FrameRect(rect, &brush); 221 | } 222 | CATCH(CResourceException, e) 223 | { 224 | //e->ReportError(); 225 | } 226 | END_CATCH 227 | 228 | pDC->SetTextColor(TextClr); 229 | 230 | // Adjust rect after frame draw if no grid lines 231 | if (pGrid->GetGridLines() == GVL_NONE) 232 | { 233 | rect.right--; 234 | rect.bottom--; 235 | } 236 | } 237 | 238 | // Draw lines only when wanted 239 | if (IsFixed() && pGrid->GetGridLines() != GVL_NONE) 240 | { 241 | CCellID FocusCell = pGrid->GetFocusCell(); 242 | 243 | // As above, always show current location even in list mode so 244 | // that we know where the cursor is at. 245 | BOOL bHiliteFixed = pGrid->GetTrackFocusCell() && pGrid->IsValid(FocusCell) && 246 | (FocusCell.row == nRow || FocusCell.col == nCol); 247 | 248 | // If this fixed cell is on the same row/col as the focus cell, 249 | // highlight it. 250 | if (bHiliteFixed) 251 | { 252 | rect.right++; rect.bottom++; 253 | pDC->DrawEdge(rect, BDR_SUNKENINNER /*EDGE_RAISED*/, BF_RECT); 254 | rect.DeflateRect(1,1); 255 | } 256 | else 257 | { 258 | CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)), 259 | darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)), 260 | *pOldPen = pDC->GetCurrentPen(); 261 | 262 | pDC->SelectObject(&lightpen); 263 | pDC->MoveTo(rect.right, rect.top); 264 | pDC->LineTo(rect.left, rect.top); 265 | pDC->LineTo(rect.left, rect.bottom); 266 | 267 | pDC->SelectObject(&darkpen); 268 | pDC->MoveTo(rect.right, rect.top); 269 | pDC->LineTo(rect.right, rect.bottom); 270 | pDC->LineTo(rect.left, rect.bottom); 271 | 272 | pDC->SelectObject(pOldPen); 273 | rect.DeflateRect(1,1); 274 | } 275 | } 276 | 277 | // Draw Text and image 278 | #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) 279 | if (!pDC->m_bPrinting) 280 | #endif 281 | { 282 | CFont *pFont = GetFontObject(); 283 | ASSERT(pFont); 284 | if (pFont) 285 | pDC->SelectObject(pFont); 286 | } 287 | 288 | //rect.DeflateRect(GetMargin(), 0); - changed by Yogurt 289 | rect.DeflateRect(GetMargin(), GetMargin()); 290 | rect.right++; 291 | rect.bottom++; 292 | 293 | if (pGrid->GetImageList() && GetImage() >= 0) 294 | { 295 | IMAGEINFO Info; 296 | if (pGrid->GetImageList()->GetImageInfo(GetImage(), &Info)) 297 | { 298 | // would like to use a clipping region but seems to have issue 299 | // working with CMemDC directly. Instead, don't display image 300 | // if any part of it cut-off 301 | // 302 | // CRgn rgn; 303 | // rgn.CreateRectRgnIndirect(rect); 304 | // pDC->SelectClipRgn(&rgn); 305 | // rgn.DeleteObject(); 306 | 307 | /* 308 | // removed by Yogurt 309 | int nImageWidth = Info.rcImage.right-Info.rcImage.left+1; 310 | int nImageHeight = Info.rcImage.bottom-Info.rcImage.top+1; 311 | if( nImageWidth + rect.left <= rect.right + (int)(2*GetMargin()) 312 | && nImageHeight + rect.top <= rect.bottom + (int)(2*GetMargin()) ) 313 | { 314 | pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL); 315 | } 316 | */ 317 | // Added by Yogurt 318 | int nImageWidth = Info.rcImage.right-Info.rcImage.left; 319 | int nImageHeight = Info.rcImage.bottom-Info.rcImage.top; 320 | if ((nImageWidth + rect.left <= rect.right) && (nImageHeight + rect.top <= rect.bottom)) 321 | pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL); 322 | 323 | //rect.left += nImageWidth+GetMargin(); 324 | } 325 | } 326 | 327 | // Draw sort arrow 328 | if (pGrid->GetSortColumn() == nCol && nRow == 0) 329 | { 330 | CSize size = pDC->GetTextExtent(_T("M")); 331 | int nOffset = 2; 332 | 333 | // Base the size of the triangle on the smaller of the column 334 | // height or text height with a slight offset top and bottom. 335 | // Otherwise, it can get drawn outside the bounds of the cell. 336 | size.cy -= (nOffset * 2); 337 | 338 | if (size.cy >= rect.Height()) 339 | size.cy = rect.Height() - (nOffset * 2); 340 | 341 | size.cx = size.cy; // Make the dimensions square 342 | 343 | // Kludge for vertical text 344 | BOOL bVertical = (GetFont()->lfEscapement == 900); 345 | 346 | // Only draw if it'll fit! 347 | //if (size.cx + rect.left < rect.right + (int)(2*GetMargin())) - changed / Yogurt 348 | if (size.cx + rect.left < rect.right) 349 | { 350 | int nTriangleBase = rect.bottom - nOffset - size.cy; // Triangle bottom right 351 | //int nTriangleBase = (rect.top + rect.bottom - size.cy)/2; // Triangle middle right 352 | //int nTriangleBase = rect.top + nOffset; // Triangle top right 353 | 354 | //int nTriangleLeft = rect.right - size.cx; // Triangle RHS 355 | //int nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle 356 | //int nTriangleLeft = rect.left; // Triangle LHS 357 | 358 | int nTriangleLeft; 359 | if (bVertical) 360 | nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle 361 | else 362 | nTriangleLeft = rect.right - size.cx; // Triangle RHS 363 | 364 | CPen penShadow(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW)); 365 | CPen penLight(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT)); 366 | if (pGrid->GetSortAscending()) 367 | { 368 | // Draw triangle pointing upwards 369 | CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight); 370 | pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1); 371 | pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + 1 ); 372 | pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + size.cy + 1); 373 | pDC->LineTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1); 374 | 375 | pDC->SelectObject(&penShadow); 376 | pDC->MoveTo( nTriangleLeft, nTriangleBase + size.cy ); 377 | pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase ); 378 | pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase + size.cy ); 379 | pDC->LineTo( nTriangleLeft, nTriangleBase + size.cy ); 380 | pDC->SelectObject(pOldPen); 381 | } 382 | else 383 | { 384 | // Draw triangle pointing downwards 385 | CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight); 386 | pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + 1 ); 387 | pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + size.cy + 1 ); 388 | pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + 1 ); 389 | pDC->LineTo( nTriangleLeft + 1, nTriangleBase + 1 ); 390 | 391 | pDC->SelectObject(&penShadow); 392 | pDC->MoveTo( nTriangleLeft, nTriangleBase ); 393 | pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase + size.cy ); 394 | pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase ); 395 | pDC->LineTo( nTriangleLeft, nTriangleBase ); 396 | pDC->SelectObject(pOldPen); 397 | } 398 | 399 | if (!bVertical) 400 | rect.right -= size.cy; 401 | } 402 | } 403 | 404 | // We want to see '&' characters so use DT_NOPREFIX 405 | GetTextRect(rect); 406 | rect.right++; 407 | rect.bottom++; 408 | 409 | DrawText(pDC->m_hDC, GetText(), -1, rect, GetFormat() | DT_NOPREFIX); 410 | 411 | pDC->RestoreDC(nSavedDC); 412 | 413 | return TRUE; 414 | } 415 | 416 | ///////////////////////////////////////////////////////////////////////////// 417 | // CGridCellBase Mouse and Cursor events 418 | 419 | // Not yet implemented 420 | void CGridCellBase::OnMouseEnter() 421 | { 422 | TRACE0("Mouse entered cell\n"); 423 | } 424 | 425 | void CGridCellBase::OnMouseOver() 426 | { 427 | //TRACE0("Mouse over cell\n"); 428 | } 429 | 430 | // Not Yet Implemented 431 | void CGridCellBase::OnMouseLeave() 432 | { 433 | TRACE0("Mouse left cell\n"); 434 | } 435 | 436 | void CGridCellBase::OnClick( CPoint PointCellRelative) 437 | { 438 | UNUSED_ALWAYS(PointCellRelative); 439 | TRACE2("Mouse Left btn up in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); 440 | } 441 | 442 | void CGridCellBase::OnClickDown( CPoint PointCellRelative) 443 | { 444 | UNUSED_ALWAYS(PointCellRelative); 445 | TRACE2("Mouse Left btn down in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); 446 | } 447 | 448 | void CGridCellBase::OnRClick( CPoint PointCellRelative) 449 | { 450 | UNUSED_ALWAYS(PointCellRelative); 451 | TRACE2("Mouse right-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); 452 | } 453 | 454 | void CGridCellBase::OnDblClick( CPoint PointCellRelative) 455 | { 456 | UNUSED_ALWAYS(PointCellRelative); 457 | TRACE2("Mouse double-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); 458 | } 459 | 460 | // Return TRUE if you set the cursor 461 | BOOL CGridCellBase::OnSetCursor() 462 | { 463 | #ifndef _WIN32_WCE_NO_CURSOR 464 | SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); 465 | #endif 466 | return TRUE; 467 | } 468 | 469 | ///////////////////////////////////////////////////////////////////////////// 470 | // CGridCellBase editing 471 | 472 | void CGridCellBase::OnEndEdit() 473 | { 474 | ASSERT( FALSE); 475 | } 476 | 477 | BOOL CGridCellBase::ValidateEdit(LPCTSTR str) 478 | { 479 | UNUSED_ALWAYS(str); 480 | return TRUE; 481 | } 482 | 483 | ///////////////////////////////////////////////////////////////////////////// 484 | // CGridCellBase Sizing 485 | 486 | BOOL CGridCellBase::GetTextRect( LPRECT pRect) // i/o: i=dims of cell rect; o=dims of text rect 487 | { 488 | if (GetImage() >= 0) 489 | { 490 | IMAGEINFO Info; 491 | 492 | CGridCtrl* pGrid = GetGrid(); 493 | CImageList* pImageList = pGrid->GetImageList(); 494 | 495 | if (pImageList && pImageList->GetImageInfo( GetImage(), &Info)) 496 | { 497 | int nImageWidth = Info.rcImage.right-Info.rcImage.left+1; 498 | pRect->left += nImageWidth + GetMargin(); 499 | } 500 | } 501 | 502 | return TRUE; 503 | } 504 | 505 | // By default this uses the selected font (which is a bigger font) 506 | CSize CGridCellBase::GetTextExtent(LPCTSTR szText, CDC* pDC /*= NULL*/) 507 | { 508 | CGridCtrl* pGrid = GetGrid(); 509 | ASSERT(pGrid); 510 | 511 | BOOL bReleaseDC = FALSE; 512 | if (pDC == NULL || szText == NULL) 513 | { 514 | if (szText) 515 | pDC = pGrid->GetDC(); 516 | if (pDC == NULL || szText == NULL) 517 | { 518 | CGridDefaultCell* pDefCell = (CGridDefaultCell*) GetDefaultCell(); 519 | ASSERT(pDefCell); 520 | return CSize(pDefCell->GetWidth(), pDefCell->GetHeight()); 521 | } 522 | bReleaseDC = TRUE; 523 | } 524 | 525 | CFont *pOldFont = NULL, 526 | *pFont = GetFontObject(); 527 | if (pFont) 528 | pOldFont = pDC->SelectObject(pFont); 529 | 530 | CSize size; 531 | int nFormat = GetFormat(); 532 | 533 | // If the cell is a multiline cell, then use the width of the cell 534 | // to get the height 535 | if ((nFormat & DT_WORDBREAK) && !(nFormat & DT_SINGLELINE)) 536 | { 537 | CString str = szText; 538 | int nMaxWidth = 0; 539 | while (TRUE) 540 | { 541 | int nPos = str.Find(_T('\n')); 542 | CString TempStr = (nPos < 0)? str : str.Left(nPos); 543 | int nTempWidth = pDC->GetTextExtent(TempStr).cx; 544 | if (nTempWidth > nMaxWidth) 545 | nMaxWidth = nTempWidth; 546 | 547 | if (nPos < 0) 548 | break; 549 | str = str.Mid(nPos + 1); // Bug fix by Thomas Steinborn 550 | } 551 | 552 | CRect rect; 553 | rect.SetRect(0,0, nMaxWidth+1, 0); 554 | pDC->DrawText(szText, -1, rect, nFormat | DT_CALCRECT); 555 | size = rect.Size(); 556 | } 557 | else 558 | size = pDC->GetTextExtent(szText, (int)_tcslen(szText)); 559 | 560 | // Removed by Yogurt 561 | //TEXTMETRIC tm; 562 | //pDC->GetTextMetrics(&tm); 563 | //size.cx += (tm.tmOverhang); 564 | 565 | if (pOldFont) 566 | pDC->SelectObject(pOldFont); 567 | 568 | size += CSize(2*GetMargin(), 2*GetMargin()); 569 | 570 | // Kludge for vertical text 571 | LOGFONT *pLF = GetFont(); 572 | if (pLF->lfEscapement == 900 || pLF->lfEscapement == -900) 573 | { 574 | int nTemp = size.cx; 575 | size.cx = size.cy; 576 | size.cy = nTemp; 577 | size += CSize(0, 4*GetMargin()); 578 | } 579 | 580 | if (bReleaseDC) 581 | pGrid->ReleaseDC(pDC); 582 | 583 | return size; 584 | } 585 | 586 | 587 | CSize CGridCellBase::GetCellExtent(CDC* pDC) 588 | { 589 | CSize size = GetTextExtent(GetText(), pDC); 590 | CSize ImageSize(0,0); 591 | 592 | int nImage = GetImage(); 593 | if (nImage >= 0) 594 | { 595 | CGridCtrl* pGrid = GetGrid(); 596 | ASSERT(pGrid); 597 | IMAGEINFO Info; 598 | if (pGrid->GetImageList() && pGrid->GetImageList()->GetImageInfo(nImage, &Info)) 599 | { 600 | ImageSize = CSize(Info.rcImage.right-Info.rcImage.left, 601 | Info.rcImage.bottom-Info.rcImage.top); 602 | if (size.cx > 2*(int)GetMargin ()) 603 | ImageSize.cx += GetMargin(); 604 | ImageSize.cy += 2*(int)GetMargin (); 605 | } 606 | } 607 | size.cx += ImageSize.cx + 1; 608 | size.cy = max(size.cy, ImageSize.cy) + 1; 609 | if (IsFixed()) 610 | { 611 | size.cx++; 612 | size.cy++; 613 | } 614 | return size; 615 | } 616 | 617 | // EFW - Added to print cells so that grids that use different colors are 618 | // printed correctly. 619 | BOOL CGridCellBase::PrintCell(CDC* pDC, int /*nRow*/, int /*nCol*/, CRect rect) 620 | { 621 | #if defined(_WIN32_WCE_NO_PRINTING) || defined(GRIDCONTROL_NO_PRINTING) 622 | return FALSE; 623 | #else 624 | COLORREF crFG, crBG; 625 | GV_ITEM Item; 626 | 627 | CGridCtrl* pGrid = GetGrid(); 628 | if (!pGrid || !pDC) 629 | return FALSE; 630 | 631 | if( rect.Width() <= 0 632 | || rect.Height() <= 0) // prevents imagelist item from drawing even 633 | return FALSE; // though cell is hidden 634 | 635 | int nSavedDC = pDC->SaveDC(); 636 | 637 | pDC->SetBkMode(TRANSPARENT); 638 | 639 | if (pGrid->GetShadedPrintOut()) 640 | { 641 | // Get the default cell implementation for this kind of cell. We use it if this cell 642 | // has anything marked as "default" 643 | CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); 644 | if (!pDefaultCell) 645 | return FALSE; 646 | 647 | // Use custom color if it doesn't match the default color and the 648 | // default grid background color. If not, leave it alone. 649 | if(IsFixed()) 650 | crBG = (GetBackClr() != CLR_DEFAULT) ? GetBackClr() : pDefaultCell->GetBackClr(); 651 | else 652 | crBG = (GetBackClr() != CLR_DEFAULT && GetBackClr() != pDefaultCell->GetBackClr()) ? 653 | GetBackClr() : CLR_DEFAULT; 654 | 655 | // Use custom color if the background is different or if it doesn't 656 | // match the default color and the default grid text color. 657 | if(IsFixed()) 658 | crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr(); 659 | else 660 | crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr(); 661 | 662 | // If not printing on a color printer, adjust the foreground color 663 | // to a gray scale if the background color isn't used so that all 664 | // colors will be visible. If not, some colors turn to solid black 665 | // or white when printed and may not show up. This may be caused by 666 | // coarse dithering by the printer driver too (see image note below). 667 | if(pDC->GetDeviceCaps(NUMCOLORS) == 2 && crBG == CLR_DEFAULT) 668 | crFG = RGB(GetRValue(crFG) * 0.30, GetGValue(crFG) * 0.59, 669 | GetBValue(crFG) * 0.11); 670 | 671 | // Only erase the background if the color is not the default 672 | // grid background color. 673 | if(crBG != CLR_DEFAULT) 674 | { 675 | CBrush brush(crBG); 676 | rect.right++; rect.bottom++; 677 | pDC->FillRect(rect, &brush); 678 | rect.right--; rect.bottom--; 679 | } 680 | } 681 | else 682 | { 683 | crBG = CLR_DEFAULT; 684 | crFG = RGB(0, 0, 0); 685 | } 686 | 687 | pDC->SetTextColor(crFG); 688 | 689 | CFont *pFont = GetFontObject(); 690 | if (pFont) 691 | pDC->SelectObject(pFont); 692 | 693 | /* 694 | // *************************************************** 695 | // Disabled - if you need this functionality then you'll need to rewrite. 696 | // Create the appropriate font and select into DC. 697 | CFont Font; 698 | // Bold the fixed cells if not shading the print out. Use italic 699 | // font it it is enabled. 700 | const LOGFONT* plfFont = GetFont(); 701 | if(IsFixed() && !pGrid->GetShadedPrintOut()) 702 | { 703 | Font.CreateFont(plfFont->lfHeight, 0, 0, 0, FW_BOLD, plfFont->lfItalic, 0, 0, 704 | ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 705 | #ifndef _WIN32_WCE 706 | PROOF_QUALITY, 707 | #else 708 | DEFAULT_QUALITY, 709 | #endif 710 | VARIABLE_PITCH | FF_SWISS, plfFont->lfFaceName); 711 | } 712 | else 713 | Font.CreateFontIndirect(plfFont); 714 | 715 | pDC->SelectObject(&Font); 716 | // *************************************************** 717 | */ 718 | 719 | // Draw lines only when wanted on fixed cells. Normal cell grid lines 720 | // are handled in OnPrint. 721 | if(pGrid->GetGridLines() != GVL_NONE && IsFixed()) 722 | { 723 | CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)), 724 | darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)), 725 | *pOldPen = pDC->GetCurrentPen(); 726 | 727 | pDC->SelectObject(&lightpen); 728 | pDC->MoveTo(rect.right, rect.top); 729 | pDC->LineTo(rect.left, rect.top); 730 | pDC->LineTo(rect.left, rect.bottom); 731 | 732 | pDC->SelectObject(&darkpen); 733 | pDC->MoveTo(rect.right, rect.top); 734 | pDC->LineTo(rect.right, rect.bottom); 735 | pDC->LineTo(rect.left, rect.bottom); 736 | 737 | rect.DeflateRect(1,1); 738 | pDC->SelectObject(pOldPen); 739 | } 740 | 741 | rect.DeflateRect(GetMargin(), 0); 742 | 743 | if(pGrid->GetImageList() && GetImage() >= 0) 744 | { 745 | // NOTE: If your printed images look like fuzzy garbage, check the 746 | // settings on your printer driver. If it's using coarse 747 | // dithering and/or vector graphics, they may print wrong. 748 | // Changing to fine dithering and raster graphics makes them 749 | // print properly. My HP 4L had that problem. 750 | 751 | IMAGEINFO Info; 752 | if(pGrid->GetImageList()->GetImageInfo(GetImage(), &Info)) 753 | { 754 | int nImageWidth = Info.rcImage.right-Info.rcImage.left; 755 | pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL); 756 | rect.left += nImageWidth+GetMargin(); 757 | } 758 | } 759 | 760 | // Draw without clipping so as not to lose text when printed for real 761 | // DT_NOCLIP removed 01.01.01. Slower, but who cares - we are printing! 762 | DrawText(pDC->m_hDC, GetText(), -1, rect, 763 | GetFormat() | /*DT_NOCLIP | */ DT_NOPREFIX); 764 | 765 | pDC->RestoreDC(nSavedDC); 766 | 767 | return TRUE; 768 | #endif 769 | } 770 | 771 | /***************************************************************************** 772 | Callable by derived classes, only 773 | *****************************************************************************/ 774 | LRESULT CGridCellBase::SendMessageToParent(int nRow, int nCol, int nMessage) 775 | { 776 | CGridCtrl* pGrid = GetGrid(); 777 | if( pGrid) 778 | return pGrid->SendMessageToParent(nRow, nCol, nMessage); 779 | else 780 | return 0; 781 | } -------------------------------------------------------------------------------- /GridCtrl.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // GridCtrl.h : header file 3 | // 4 | // MFC Grid Control - main header 5 | // 6 | // Written by Chris Maunder 7 | // Copyright (c) 1998-2005. All Rights Reserved. 8 | // 9 | // This code may be used in compiled form in any way you desire. This 10 | // file may be redistributed unmodified by any means PROVIDING it is 11 | // not sold for profit without the authors written consent, and 12 | // providing that this notice and the authors name and all copyright 13 | // notices remains intact. 14 | // 15 | // An email letting me know how you are using it would be nice as well. 16 | // 17 | // This file is provided "as is" with no expressed or implied warranty. 18 | // The author accepts no liability for any damage/loss of business that 19 | // this product may cause. 20 | // 21 | // For use with CGridCtrl v2.20+ 22 | // 23 | ////////////////////////////////////////////////////////////////////// 24 | 25 | #if !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) 26 | #define AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_ 27 | 28 | #if _MSC_VER >= 1000 29 | #pragma once 30 | #endif // _MSC_VER >= 1000 31 | 32 | #include "CellRange.h" 33 | #include "GridCell.h" 34 | #include 35 | #include 36 | 37 | 38 | /////////////////////////////////////////////////////////////////////////////////// 39 | // Defines - these determine the features (and the final size) of the final code 40 | /////////////////////////////////////////////////////////////////////////////////// 41 | 42 | //#define GRIDCONTROL_NO_TITLETIPS // Do not use titletips for cells with large data 43 | //#define GRIDCONTROL_NO_DRAGDROP // Do not use OLE drag and drop 44 | //#define GRIDCONTROL_NO_CLIPBOARD // Do not use clipboard routines 45 | 46 | #ifdef _WIN32_WCE 47 | # define GRIDCONTROL_NO_TITLETIPS // Do not use titletips for cells with large data 48 | # define GRIDCONTROL_NO_DRAGDROP // Do not use OLE drag and drop 49 | # define GRIDCONTROL_NO_CLIPBOARD // Do not use clipboard routines 50 | # define GRIDCONTROL_NO_PRINTING // Do not use printing routines 51 | # ifdef WCE_NO_PRINTING // Older versions of CE had different #def's 52 | # define _WIN32_WCE_NO_PRINTING 53 | # endif 54 | # ifdef WCE_NO_CURSOR 55 | # define _WIN32_WCE_NO_CURSOR 56 | # endif 57 | #endif // _WIN32_WCE 58 | 59 | // Use this as the classname when inserting this control as a custom control 60 | // in the MSVC++ dialog editor 61 | #define GRIDCTRL_CLASSNAME _T("MFCGridCtrl") // Window class name 62 | #define IDC_INPLACE_CONTROL 8 // ID of inplace edit controls 63 | 64 | 65 | /////////////////////////////////////////////////////////////////////////////////// 66 | // Conditional includes 67 | /////////////////////////////////////////////////////////////////////////////////// 68 | 69 | #ifndef GRIDCONTROL_NO_TITLETIPS 70 | # include "TitleTip.h" 71 | #endif 72 | 73 | #ifndef GRIDCONTROL_NO_DRAGDROP 74 | # include "GridDropTarget.h" 75 | # undef GRIDCONTROL_NO_CLIPBOARD // Force clipboard functions on 76 | #endif 77 | 78 | #ifndef GRIDCONTROL_NO_CLIPBOARD 79 | # include 80 | #endif 81 | 82 | 83 | /////////////////////////////////////////////////////////////////////////////////// 84 | // Helper functions 85 | /////////////////////////////////////////////////////////////////////////////////// 86 | 87 | // Handy functions 88 | #define IsSHIFTpressed() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0 ) 89 | #define IsCTRLpressed() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 ) 90 | 91 | // Backwards compatibility for pre 2.20 grid versions 92 | #define DDX_GridControl(pDX, nIDC, rControl) DDX_Control(pDX, nIDC, rControl) 93 | 94 | 95 | /////////////////////////////////////////////////////////////////////////////////// 96 | // Structures 97 | /////////////////////////////////////////////////////////////////////////////////// 98 | 99 | // This structure sent to Grid's parent in a WM_NOTIFY message 100 | typedef struct tagNM_GRIDVIEW { 101 | NMHDR hdr; 102 | int iRow; 103 | int iColumn; 104 | } NM_GRIDVIEW; 105 | 106 | // This is sent to the Grid from child in-place edit controls 107 | typedef struct tagGV_DISPINFO { 108 | NMHDR hdr; 109 | GV_ITEM item; 110 | } GV_DISPINFO; 111 | 112 | // This is sent to the Grid from child in-place edit controls 113 | typedef struct tagGV_CACHEHINT { 114 | NMHDR hdr; 115 | CCellRange range; 116 | } GV_CACHEHINT; 117 | 118 | // storage typedef for each row in the grid 119 | typedef CTypedPtrArray GRID_ROW; 120 | 121 | // For virtual mode callback 122 | typedef BOOL (CALLBACK* GRIDCALLBACK)(GV_DISPINFO *, LPARAM); 123 | 124 | /////////////////////////////////////////////////////////////////////////////////// 125 | // Defines 126 | /////////////////////////////////////////////////////////////////////////////////// 127 | 128 | // Grid line/scrollbar selection 129 | #define GVL_NONE 0L // Neither 130 | #define GVL_HORZ 1L // Horizontal line or scrollbar 131 | #define GVL_VERT 2L // Vertical line or scrollbar 132 | #define GVL_BOTH 3L // Both 133 | 134 | // Autosizing option 135 | #define GVS_DEFAULT 0 136 | #define GVS_HEADER 1 // Size using column fixed cells data only 137 | #define GVS_DATA 2 // Size using column non-fixed cells data only 138 | #define GVS_BOTH 3 // Size using column fixed and non-fixed 139 | 140 | // Cell Searching options 141 | #define GVNI_FOCUSED 0x0001 142 | #define GVNI_SELECTED 0x0002 143 | #define GVNI_DROPHILITED 0x0004 144 | #define GVNI_READONLY 0x0008 145 | #define GVNI_FIXED 0x0010 146 | #define GVNI_MODIFIED 0x0020 147 | 148 | #define GVNI_ABOVE LVNI_ABOVE 149 | #define GVNI_BELOW LVNI_BELOW 150 | #define GVNI_TOLEFT LVNI_TOLEFT 151 | #define GVNI_TORIGHT LVNI_TORIGHT 152 | #define GVNI_ALL (LVNI_BELOW|LVNI_TORIGHT|LVNI_TOLEFT) 153 | #define GVNI_AREA (LVNI_BELOW|LVNI_TORIGHT) 154 | 155 | // Hit test values (not yet implemented) 156 | #define GVHT_DATA 0x0000 157 | #define GVHT_TOPLEFT 0x0001 158 | #define GVHT_COLHDR 0x0002 159 | #define GVHT_ROWHDR 0x0004 160 | #define GVHT_COLSIZER 0x0008 161 | #define GVHT_ROWSIZER 0x0010 162 | #define GVHT_LEFT 0x0020 163 | #define GVHT_RIGHT 0x0040 164 | #define GVHT_ABOVE 0x0080 165 | #define GVHT_BELOW 0x0100 166 | 167 | // Messages sent to the grid's parent (More will be added in future) 168 | #define GVN_BEGINDRAG LVN_BEGINDRAG // LVN_FIRST-9 169 | #define GVN_BEGINLABELEDIT LVN_BEGINLABELEDIT // LVN_FIRST-5 170 | #define GVN_BEGINRDRAG LVN_BEGINRDRAG 171 | #define GVN_COLUMNCLICK LVN_COLUMNCLICK 172 | #define GVN_DELETEITEM LVN_DELETEITEM 173 | #define GVN_ENDLABELEDIT LVN_ENDLABELEDIT // LVN_FIRST-6 174 | #define GVN_SELCHANGING LVN_ITEMCHANGING 175 | #define GVN_SELCHANGED LVN_ITEMCHANGED 176 | #define GVN_GETDISPINFO LVN_GETDISPINFO 177 | #define GVN_ODCACHEHINT LVN_ODCACHEHINT 178 | 179 | class CGridCtrl; 180 | 181 | ///////////////////////////////////////////////////////////////////////////// 182 | // CGridCtrl window 183 | 184 | typedef bool (*PVIRTUALCOMPARE)(int, int); 185 | 186 | class CGridCtrl : public CWnd 187 | { 188 | DECLARE_DYNCREATE(CGridCtrl) 189 | friend class CGridCell; 190 | friend class CGridCellBase; 191 | 192 | // Construction 193 | public: 194 | CGridCtrl(int nRows = 0, int nCols = 0, int nFixedRows = 0, int nFixedCols = 0); 195 | 196 | BOOL Create(const RECT& rect, CWnd* parent, UINT nID, 197 | DWORD dwStyle = WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VISIBLE); 198 | 199 | /////////////////////////////////////////////////////////////////////////////////// 200 | // Attributes 201 | /////////////////////////////////////////////////////////////////////////////////// 202 | public: 203 | int GetRowCount() const { return m_nRows; } 204 | int GetColumnCount() const { return m_nCols; } 205 | int GetFixedRowCount() const { return m_nFixedRows; } 206 | int GetFixedColumnCount() const { return m_nFixedCols; } 207 | BOOL SetRowCount(int nRows = 10); 208 | BOOL SetColumnCount(int nCols = 10); 209 | BOOL SetFixedRowCount(int nFixedRows = 1); 210 | BOOL SetFixedColumnCount(int nFixedCols = 1); 211 | 212 | int GetRowHeight(int nRow) const; 213 | BOOL SetRowHeight(int row, int height); 214 | int GetColumnWidth(int nCol) const; 215 | BOOL SetColumnWidth(int col, int width); 216 | 217 | BOOL GetCellOrigin(int nRow, int nCol, LPPOINT p); 218 | BOOL GetCellOrigin(const CCellID& cell, LPPOINT p); 219 | BOOL GetCellRect(int nRow, int nCol, LPRECT pRect); 220 | BOOL GetCellRect(const CCellID& cell, LPRECT pRect); 221 | 222 | BOOL GetTextRect(const CCellID& cell, LPRECT pRect); 223 | BOOL GetTextRect(int nRow, int nCol, LPRECT pRect); 224 | 225 | CCellID GetCellFromPt(CPoint point, BOOL bAllowFixedCellCheck = TRUE); 226 | 227 | int GetFixedRowHeight() const; 228 | int GetFixedColumnWidth() const; 229 | long GetVirtualWidth() const; 230 | long GetVirtualHeight() const; 231 | 232 | CSize GetTextExtent(int nRow, int nCol, LPCTSTR str); 233 | // EFW - Get extent of current text in cell 234 | inline CSize GetCellTextExtent(int nRow, int nCol) { return GetTextExtent(nRow, nCol, GetItemText(nRow,nCol)); } 235 | 236 | void SetGridBkColor(COLORREF clr) { m_crGridBkColour = clr; } 237 | COLORREF GetGridBkColor() const { return m_crGridBkColour; } 238 | void SetGridLineColor(COLORREF clr) { m_crGridLineColour = clr; } 239 | COLORREF GetGridLineColor() const { return m_crGridLineColour; } 240 | 241 | void SetTitleTipBackClr(COLORREF clr = CLR_DEFAULT) { m_crTTipBackClr = clr; } 242 | COLORREF GetTitleTipBackClr() { return m_crTTipBackClr; } 243 | void SetTitleTipTextClr(COLORREF clr = CLR_DEFAULT) { m_crTTipTextClr = clr; } 244 | COLORREF GetTitleTipTextClr() { return m_crTTipTextClr; } 245 | 246 | // ***************************************************************************** // 247 | // These have been deprecated. Use GetDefaultCell and then set the colors 248 | void SetTextColor(COLORREF clr) { m_cellDefault.SetTextClr(clr); } 249 | COLORREF GetTextColor() { return m_cellDefault.GetTextClr(); } 250 | void SetTextBkColor(COLORREF clr) { m_cellDefault.SetBackClr(clr); } 251 | COLORREF GetTextBkColor() { return m_cellDefault.GetBackClr(); } 252 | void SetFixedTextColor(COLORREF clr) { m_cellFixedRowDef.SetTextClr(clr); 253 | m_cellFixedColDef.SetTextClr(clr); 254 | m_cellFixedRowColDef.SetTextClr(clr); } 255 | COLORREF GetFixedTextColor() const { return m_cellFixedRowDef.GetTextClr(); } 256 | void SetFixedBkColor(COLORREF clr) { m_cellFixedRowDef.SetBackClr(clr); 257 | m_cellFixedColDef.SetBackClr(clr); 258 | m_cellFixedRowColDef.SetBackClr(clr); } 259 | COLORREF GetFixedBkColor() const { return m_cellFixedRowDef.GetBackClr(); } 260 | void SetGridColor(COLORREF clr) { SetGridLineColor(clr); } 261 | COLORREF GetGridColor() { return GetGridLineColor(); } 262 | void SetBkColor(COLORREF clr) { SetGridBkColor(clr); } 263 | COLORREF GetBkColor() { return GetGridBkColor(); } 264 | 265 | void SetDefCellMargin( int nMargin) { m_cellDefault.SetMargin(nMargin); 266 | m_cellFixedRowDef.SetMargin(nMargin); 267 | m_cellFixedColDef.SetMargin(nMargin); 268 | m_cellFixedRowColDef.SetMargin(nMargin); } 269 | int GetDefCellMargin() const { return m_cellDefault.GetMargin(); } 270 | 271 | int GetDefCellHeight() const { return m_cellDefault.GetHeight(); } 272 | void SetDefCellHeight(int nHeight) { m_cellDefault.SetHeight(nHeight); 273 | m_cellFixedRowDef.SetHeight(nHeight); 274 | m_cellFixedColDef.SetHeight(nHeight); 275 | m_cellFixedRowColDef.SetHeight(nHeight); } 276 | int GetDefCellWidth() const { return m_cellDefault.GetWidth(); } 277 | void SetDefCellWidth(int nWidth) { m_cellDefault.SetWidth(nWidth); 278 | m_cellFixedRowDef.SetWidth(nWidth); 279 | m_cellFixedColDef.SetWidth(nWidth); 280 | m_cellFixedRowColDef.SetWidth(nWidth); } 281 | 282 | // ***************************************************************************** // 283 | 284 | int GetSelectedCount() const { return (int)m_SelectedCellMap.GetCount(); } 285 | 286 | CCellID SetFocusCell(CCellID cell); 287 | CCellID SetFocusCell(int nRow, int nCol); 288 | CCellID GetFocusCell() const { return m_idCurrentCell; } 289 | 290 | 291 | void SetVirtualMode(BOOL bVirtual); 292 | BOOL GetVirtualMode() const { return m_bVirtualMode; } 293 | void SetCallbackFunc(GRIDCALLBACK pCallback, 294 | LPARAM lParam) { m_pfnCallback = pCallback; m_lParam = lParam; } 295 | GRIDCALLBACK GetCallbackFunc() { return m_pfnCallback; } 296 | 297 | 298 | void SetImageList(CImageList* pList) { m_pImageList = pList; } 299 | CImageList* GetImageList() const { return m_pImageList; } 300 | 301 | void SetGridLines(int nWhichLines = GVL_BOTH); 302 | int GetGridLines() const { return m_nGridLines; } 303 | void SetEditable(BOOL bEditable = TRUE) { m_bEditable = bEditable; } 304 | BOOL IsEditable() const { return m_bEditable; } 305 | void SetListMode(BOOL bEnableListMode = TRUE); 306 | BOOL GetListMode() const { return m_bListMode; } 307 | void SetSingleRowSelection(BOOL bSing = TRUE) { m_bSingleRowSelection = bSing; } 308 | BOOL GetSingleRowSelection() { return m_bSingleRowSelection & m_bListMode; } 309 | void SetSingleColSelection(BOOL bSing = TRUE) { m_bSingleColSelection = bSing; } 310 | BOOL GetSingleColSelection() { return m_bSingleColSelection; } 311 | void EnableSelection(BOOL bEnable = TRUE) { ResetSelectedRange(); m_bEnableSelection = bEnable; ResetSelectedRange(); } 312 | BOOL IsSelectable() const { return m_bEnableSelection; } 313 | void SetFixedColumnSelection(BOOL bSelect) { m_bFixedColumnSelection = bSelect;} 314 | BOOL GetFixedColumnSelection() { return m_bFixedColumnSelection; } 315 | void SetFixedRowSelection(BOOL bSelect) { m_bFixedRowSelection = bSelect; } 316 | BOOL GetFixedRowSelection() { return m_bFixedRowSelection; } 317 | void EnableDragAndDrop(BOOL bAllow = TRUE) { m_bAllowDragAndDrop = bAllow; } 318 | BOOL GetDragAndDrop() const { return m_bAllowDragAndDrop; } 319 | void SetRowResize(BOOL bResize = TRUE) { m_bAllowRowResize = bResize; } 320 | BOOL GetRowResize() const { return m_bAllowRowResize; } 321 | void SetColumnResize(BOOL bResize = TRUE) { m_bAllowColumnResize = bResize; } 322 | BOOL GetColumnResize() const { return m_bAllowColumnResize; } 323 | void SetHeaderSort(BOOL bSortOnClick = TRUE) { m_bSortOnClick = bSortOnClick; } 324 | BOOL GetHeaderSort() const { return m_bSortOnClick; } 325 | void SetHandleTabKey(BOOL bHandleTab = TRUE) { m_bHandleTabKey = bHandleTab; } 326 | BOOL GetHandleTabKey() const { return m_bHandleTabKey; } 327 | void SetDoubleBuffering(BOOL bBuffer = TRUE) { m_bDoubleBuffer = bBuffer; } 328 | BOOL GetDoubleBuffering() const { return m_bDoubleBuffer; } 329 | void EnableTitleTips(BOOL bEnable = TRUE) { m_bTitleTips = bEnable; } 330 | BOOL GetTitleTips() { return m_bTitleTips; } 331 | void SetSortColumn(int nCol); 332 | int GetSortColumn() const { return m_nSortColumn; } 333 | void SetSortAscending(BOOL bAscending) { m_bAscending = bAscending; } 334 | BOOL GetSortAscending() const { return m_bAscending; } 335 | void SetTrackFocusCell(BOOL bTrack) { m_bTrackFocusCell = bTrack; } 336 | BOOL GetTrackFocusCell() { return m_bTrackFocusCell; } 337 | void SetFrameFocusCell(BOOL bFrame) { m_bFrameFocus = bFrame; } 338 | BOOL GetFrameFocusCell() { return m_bFrameFocus; } 339 | void SetAutoSizeStyle(int nStyle = GVS_BOTH) { m_nAutoSizeColumnStyle = nStyle; } 340 | int GetAutoSizeStyle() { return m_nAutoSizeColumnStyle; } 341 | 342 | void EnableHiddenColUnhide(BOOL bEnable = TRUE){ m_bHiddenColUnhide = bEnable; } 343 | BOOL GetHiddenColUnhide() { return m_bHiddenColUnhide; } 344 | void EnableHiddenRowUnhide(BOOL bEnable = TRUE){ m_bHiddenRowUnhide = bEnable; } 345 | BOOL GetHiddenRowUnhide() { return m_bHiddenRowUnhide; } 346 | 347 | void EnableColumnHide(BOOL bEnable = TRUE) { m_bAllowColHide = bEnable; } 348 | BOOL GetColumnHide() { return m_bAllowColHide; } 349 | void EnableRowHide(BOOL bEnable = TRUE) { m_bAllowRowHide = bEnable; } 350 | BOOL GetRowHide() { return m_bAllowRowHide; } 351 | 352 | /////////////////////////////////////////////////////////////////////////////////// 353 | // default Grid cells. Use these for setting default values such as colors and fonts 354 | /////////////////////////////////////////////////////////////////////////////////// 355 | public: 356 | CGridCellBase* GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const; 357 | 358 | /////////////////////////////////////////////////////////////////////////////////// 359 | // Grid cell Attributes 360 | /////////////////////////////////////////////////////////////////////////////////// 361 | public: 362 | CGridCellBase* GetCell(int nRow, int nCol) const; // Get the actual cell! 363 | 364 | void SetModified(BOOL bModified = TRUE, int nRow = -1, int nCol = -1); 365 | BOOL GetModified(int nRow = -1, int nCol = -1); 366 | BOOL IsCellFixed(int nRow, int nCol); 367 | 368 | BOOL SetItem(const GV_ITEM* pItem); 369 | BOOL GetItem(GV_ITEM* pItem); 370 | BOOL SetItemText(int nRow, int nCol, LPCTSTR str); 371 | // The following was virtual. If you want to override, use 372 | // CGridCellBase-derived class's GetText() to accomplish same thing 373 | CString GetItemText(int nRow, int nCol) const; 374 | 375 | // EFW - 06/13/99 - Added to support printf-style formatting codes. 376 | // Also supports use with a string resource ID 377 | #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 210) 378 | BOOL SetItemTextFmt(int nRow, int nCol, LPCTSTR szFmt, ...); 379 | BOOL SetItemTextFmtID(int nRow, int nCol, UINT nID, ...); 380 | #endif 381 | 382 | BOOL SetItemData(int nRow, int nCol, LPARAM lParam); 383 | LPARAM GetItemData(int nRow, int nCol) const; 384 | BOOL SetItemImage(int nRow, int nCol, int iImage); 385 | int GetItemImage(int nRow, int nCol) const; 386 | BOOL SetItemState(int nRow, int nCol, UINT state); 387 | UINT GetItemState(int nRow, int nCol) const; 388 | BOOL SetItemFormat(int nRow, int nCol, UINT nFormat); 389 | UINT GetItemFormat(int nRow, int nCol) const; 390 | BOOL SetItemBkColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT); 391 | COLORREF GetItemBkColour(int nRow, int nCol) const; 392 | BOOL SetItemFgColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT); 393 | COLORREF GetItemFgColour(int nRow, int nCol) const; 394 | BOOL SetItemFrColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT); 395 | COLORREF GetItemFrColour(int nRow, int nCol) const; 396 | BOOL SetItemFont(int nRow, int nCol, const LOGFONT* lf); 397 | const LOGFONT* GetItemFont(int nRow, int nCol); 398 | 399 | BOOL IsItemEditing(int nRow, int nCol); 400 | 401 | BOOL SetCellType(int nRow, int nCol, CRuntimeClass* pRuntimeClass); 402 | BOOL SetDefaultCellType( CRuntimeClass* pRuntimeClass); 403 | 404 | /////////////////////////////////////////////////////////////////////////////////// 405 | // Operations 406 | /////////////////////////////////////////////////////////////////////////////////// 407 | public: 408 | int InsertColumn(LPCTSTR strHeading, UINT nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE, 409 | int nColumn = -1); 410 | int InsertRow(LPCTSTR strHeading, int nRow = -1); 411 | BOOL DeleteColumn(int nColumn); 412 | BOOL DeleteRow(int nRow); 413 | BOOL DeleteNonFixedRows(); 414 | BOOL DeleteAllItems(); 415 | 416 | void ClearCells(CCellRange Selection); 417 | 418 | BOOL AutoSizeRow(int nRow, BOOL bResetScroll = TRUE); 419 | BOOL AutoSizeColumn(int nCol, UINT nAutoSizeStyle = GVS_DEFAULT, BOOL bResetScroll = TRUE); 420 | void AutoSizeRows(); 421 | void AutoSizeColumns(UINT nAutoSizeStyle = GVS_DEFAULT); 422 | void AutoSize(UINT nAutoSizeStyle = GVS_DEFAULT); 423 | void ExpandColumnsToFit(BOOL bExpandFixed = TRUE); 424 | void ExpandLastColumn(); 425 | void ExpandRowsToFit(BOOL bExpandFixed = TRUE); 426 | void ExpandToFit(BOOL bExpandFixed = TRUE); 427 | 428 | void Refresh(); 429 | void AutoFill(); // Fill grid with blank cells 430 | 431 | void EnsureVisible(CCellID &cell) { EnsureVisible(cell.row, cell.col); } 432 | void EnsureVisible(int nRow, int nCol); 433 | BOOL IsCellVisible(int nRow, int nCol); 434 | BOOL IsCellVisible(CCellID cell); 435 | BOOL IsCellEditable(int nRow, int nCol) const; 436 | BOOL IsCellEditable(CCellID &cell) const; 437 | BOOL IsCellSelected(int nRow, int nCol) const; 438 | BOOL IsCellSelected(CCellID &cell) const; 439 | 440 | // SetRedraw stops/starts redraws on things like changing the # rows/columns 441 | // and autosizing, but not for user-intervention such as resizes 442 | void SetRedraw(BOOL bAllowDraw, BOOL bResetScrollBars = FALSE); 443 | BOOL RedrawCell(int nRow, int nCol, CDC* pDC = NULL); 444 | BOOL RedrawCell(const CCellID& cell, CDC* pDC = NULL); 445 | BOOL RedrawRow(int row); 446 | BOOL RedrawColumn(int col); 447 | 448 | #ifndef _WIN32_WCE 449 | BOOL Save(LPCTSTR filename, TCHAR chSeparator = _T(',')); 450 | BOOL Load(LPCTSTR filename, TCHAR chSeparator = _T(',')); 451 | #endif 452 | 453 | /////////////////////////////////////////////////////////////////////////////////// 454 | // Cell Ranges 455 | /////////////////////////////////////////////////////////////////////////////////// 456 | public: 457 | CCellRange GetCellRange() const; 458 | CCellRange GetSelectedCellRange() const; 459 | void SetSelectedRange(const CCellRange& Range, BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE); 460 | void SetSelectedRange(int nMinRow, int nMinCol, int nMaxRow, int nMaxCol, 461 | BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE); 462 | BOOL IsValid(int nRow, int nCol) const; 463 | BOOL IsValid(const CCellID& cell) const; 464 | BOOL IsValid(const CCellRange& range) const; 465 | 466 | /////////////////////////////////////////////////////////////////////////////////// 467 | // Clipboard, drag and drop, and cut n' paste operations 468 | /////////////////////////////////////////////////////////////////////////////////// 469 | #ifndef GRIDCONTROL_NO_CLIPBOARD 470 | virtual void CutSelectedText(); 471 | virtual COleDataSource* CopyTextFromGrid(); 472 | virtual BOOL PasteTextToGrid(CCellID cell, COleDataObject* pDataObject, BOOL bSelectPastedCells=TRUE); 473 | #endif 474 | 475 | #ifndef GRIDCONTROL_NO_DRAGDROP 476 | public: 477 | virtual void OnBeginDrag(); 478 | virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 479 | virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); 480 | virtual void OnDragLeave(); 481 | virtual BOOL OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); 482 | #endif 483 | 484 | #ifndef GRIDCONTROL_NO_CLIPBOARD 485 | virtual void OnEditCut(); 486 | virtual void OnEditCopy(); 487 | virtual void OnEditPaste(); 488 | #endif 489 | virtual void OnEditSelectAll(); 490 | 491 | /////////////////////////////////////////////////////////////////////////////////// 492 | // Misc. 493 | /////////////////////////////////////////////////////////////////////////////////// 494 | public: 495 | CCellID GetNextItem(CCellID& cell, int nFlags) const; 496 | 497 | BOOL SortItems(int nCol, BOOL bAscending, LPARAM data = 0); 498 | BOOL SortTextItems(int nCol, BOOL bAscending, LPARAM data = 0); 499 | BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data = 0); 500 | 501 | void SetCompareFunction(PFNLVCOMPARE pfnCompare); 502 | 503 | // in-built sort functions 504 | static int CALLBACK pfnCellTextCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 505 | static int CALLBACK pfnCellNumericCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 506 | 507 | /////////////////////////////////////////////////////////////////////////////////// 508 | // Printing 509 | /////////////////////////////////////////////////////////////////////////////////// 510 | #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) 511 | public: 512 | void Print(CPrintDialog* pPrntDialog = NULL); 513 | 514 | // EFW - New printing support functions 515 | void EnableWysiwygPrinting(BOOL bEnable = TRUE) { m_bWysiwygPrinting = bEnable; } 516 | BOOL GetWysiwygPrinting() { return m_bWysiwygPrinting; } 517 | 518 | void SetShadedPrintOut(BOOL bEnable = TRUE) { m_bShadedPrintOut = bEnable; } 519 | BOOL GetShadedPrintOut(void) { return m_bShadedPrintOut; } 520 | 521 | // Use -1 to have it keep the existing value 522 | void SetPrintMarginInfo(int nHeaderHeight, int nFooterHeight, 523 | int nLeftMargin, int nRightMargin, int nTopMargin, 524 | int nBottomMargin, int nGap); 525 | 526 | void GetPrintMarginInfo(int &nHeaderHeight, int &nFooterHeight, 527 | int &nLeftMargin, int &nRightMargin, int &nTopMargin, 528 | int &nBottomMargin, int &nGap); 529 | 530 | /////////////////////////////////////////////////////////////////////////////////// 531 | // Printing overrides for derived classes 532 | /////////////////////////////////////////////////////////////////////////////////// 533 | public: 534 | virtual void OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo); 535 | virtual void OnPrint(CDC *pDC, CPrintInfo *pInfo); 536 | virtual void OnEndPrinting(CDC *pDC, CPrintInfo *pInfo); 537 | 538 | #endif // #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) 539 | 540 | // Implementation 541 | public: 542 | virtual ~CGridCtrl(); 543 | 544 | protected: 545 | BOOL RegisterWindowClass(); 546 | BOOL Initialise(); 547 | void SetupDefaultCells(); 548 | 549 | LRESULT SendMessageToParent(int nRow, int nCol, int nMessage) const; 550 | LRESULT SendDisplayRequestToParent(GV_DISPINFO* pDisplayInfo) const; 551 | LRESULT SendCacheHintToParent(const CCellRange& range) const; 552 | 553 | BOOL InvalidateCellRect(const int row, const int col); 554 | BOOL InvalidateCellRect(const CCellID& cell); 555 | BOOL InvalidateCellRect(const CCellRange& cellRange); 556 | void EraseBkgnd(CDC* pDC); 557 | 558 | BOOL GetCellRangeRect(const CCellRange& cellRange, LPRECT lpRect); 559 | 560 | BOOL SetCell(int nRow, int nCol, CGridCellBase* pCell); 561 | 562 | int SetMouseMode(int nMode) { int nOldMode = m_MouseMode; m_MouseMode = nMode; return nOldMode; } 563 | int GetMouseMode() const { return m_MouseMode; } 564 | 565 | BOOL MouseOverRowResizeArea(CPoint& point); 566 | BOOL MouseOverColumnResizeArea(CPoint& point); 567 | 568 | CCellID GetTopleftNonFixedCell(BOOL bForceRecalculation = FALSE); 569 | CCellRange GetUnobstructedNonFixedCellRange(BOOL bForceRecalculation = FALSE); 570 | CCellRange GetVisibleNonFixedCellRange(LPRECT pRect = NULL, BOOL bForceRecalculation = FALSE); 571 | CCellRange GetVisibleFixedCellRange(LPRECT pRect = NULL, BOOL bForceRecalculation = FALSE); 572 | 573 | BOOL IsVisibleVScroll() { return ( (m_nBarState & GVL_VERT) > 0); } 574 | BOOL IsVisibleHScroll() { return ( (m_nBarState & GVL_HORZ) > 0); } 575 | void ResetSelectedRange(); 576 | void ResetScrollBars(); 577 | void EnableScrollBars(int nBar, BOOL bEnable = TRUE); 578 | int GetScrollPos32(int nBar, BOOL bGetTrackPos = FALSE); 579 | BOOL SetScrollPos32(int nBar, int nPos, BOOL bRedraw = TRUE); 580 | 581 | BOOL SortTextItems(int nCol, BOOL bAscending, int low, int high); 582 | BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data, 583 | int low, int high); 584 | 585 | CPoint GetPointClicked(int nRow, int nCol, const CPoint& point); 586 | 587 | void ValidateAndModifyCellContents(int nRow, int nCol, LPCTSTR strText); 588 | 589 | // Overrrides 590 | // ClassWizard generated virtual function overrides 591 | //{{AFX_VIRTUAL(CGridCtrl) 592 | protected: 593 | virtual void PreSubclassWindow(); 594 | //}}AFX_VIRTUAL 595 | 596 | protected: 597 | #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) 598 | // Printing 599 | virtual void PrintFixedRowCells(int nStartColumn, int nStopColumn, int& row, CRect& rect, 600 | CDC *pDC, BOOL& bFirst); 601 | virtual void PrintColumnHeadings(CDC *pDC, CPrintInfo *pInfo); 602 | virtual void PrintHeader(CDC *pDC, CPrintInfo *pInfo); 603 | virtual void PrintFooter(CDC *pDC, CPrintInfo *pInfo); 604 | virtual void PrintRowButtons(CDC *pDC, CPrintInfo* /*pInfo*/); 605 | #endif 606 | 607 | #ifndef GRIDCONTROL_NO_DRAGDROP 608 | // Drag n' drop 609 | virtual CImageList* CreateDragImage(CPoint *pHotSpot); // no longer necessary 610 | #endif 611 | 612 | // Mouse Clicks 613 | virtual void OnFixedColumnClick(CCellID& cell); 614 | virtual void OnFixedRowClick(CCellID& cell); 615 | 616 | // Editing 617 | virtual void OnEditCell(int nRow, int nCol, CPoint point, UINT nChar); 618 | virtual void OnEndEditCell(int nRow, int nCol, CString str); 619 | virtual BOOL ValidateEdit(int nRow, int nCol, LPCTSTR str); 620 | virtual void EndEditing(); 621 | 622 | // Drawing 623 | virtual void OnDraw(CDC* pDC); 624 | 625 | // CGridCellBase Creation and Cleanup 626 | virtual CGridCellBase* CreateCell(int nRow, int nCol); 627 | virtual void DestroyCell(int nRow, int nCol); 628 | 629 | // Attributes 630 | protected: 631 | // General attributes 632 | COLORREF m_crFixedTextColour, m_crFixedBkColour; 633 | COLORREF m_crGridBkColour, m_crGridLineColour; 634 | COLORREF m_crWindowText, m_crWindowColour, m_cr3DFace, // System colours 635 | m_crShadow; 636 | COLORREF m_crTTipBackClr, m_crTTipTextClr; // Titletip colours - FNA 637 | 638 | BOOL m_bVirtualMode; 639 | LPARAM m_lParam; // lParam for callback 640 | GRIDCALLBACK m_pfnCallback; // The callback function 641 | 642 | int m_nGridLines; 643 | BOOL m_bEditable; 644 | BOOL m_bModified; 645 | BOOL m_bAllowDragAndDrop; 646 | BOOL m_bListMode; 647 | BOOL m_bSingleRowSelection; 648 | BOOL m_bSingleColSelection; 649 | BOOL m_bAllowDraw; 650 | BOOL m_bEnableSelection; 651 | BOOL m_bFixedRowSelection, m_bFixedColumnSelection; 652 | BOOL m_bSortOnClick; 653 | BOOL m_bHandleTabKey; 654 | BOOL m_bDoubleBuffer; 655 | BOOL m_bTitleTips; 656 | int m_nBarState; 657 | BOOL m_bWysiwygPrinting; 658 | BOOL m_bHiddenColUnhide, m_bHiddenRowUnhide; 659 | BOOL m_bAllowColHide, m_bAllowRowHide; 660 | BOOL m_bAutoSizeSkipColHdr; 661 | BOOL m_bTrackFocusCell; 662 | BOOL m_bFrameFocus; 663 | UINT m_nAutoSizeColumnStyle; 664 | 665 | // Cell size details 666 | int m_nRows, m_nFixedRows, m_nCols, m_nFixedCols; 667 | CUIntArray m_arRowHeights, m_arColWidths; 668 | int m_nVScrollMax, m_nHScrollMax; 669 | 670 | // Fonts and images 671 | CRuntimeClass* m_pRtcDefault; // determines kind of Grid Cell created by default 672 | CGridDefaultCell m_cellDefault; // "default" cell. Contains default colours, font etc. 673 | CGridDefaultCell m_cellFixedColDef, m_cellFixedRowDef, m_cellFixedRowColDef; 674 | CFont m_PrinterFont; // for the printer 675 | CImageList* m_pImageList; 676 | 677 | // Cell data 678 | CTypedPtrArray m_RowData; 679 | 680 | // Mouse operations such as cell selection 681 | int m_MouseMode; 682 | BOOL m_bLMouseButtonDown, m_bRMouseButtonDown; 683 | CPoint m_LeftClickDownPoint, m_LastMousePoint; 684 | CCellID m_LeftClickDownCell, m_SelectionStartCell; 685 | CCellID m_idCurrentCell, m_idTopLeftCell; 686 | INT_PTR m_nTimerID; 687 | int m_nTimerInterval; 688 | int m_nResizeCaptureRange; 689 | BOOL m_bAllowRowResize, m_bAllowColumnResize; 690 | int m_nRowsPerWheelNotch; 691 | CMap m_SelectedCellMap, m_PrevSelectedCellMap; 692 | 693 | #ifndef GRIDCONTROL_NO_TITLETIPS 694 | CTitleTip m_TitleTip; // Title tips for cells 695 | #endif 696 | 697 | // Drag and drop 698 | CCellID m_LastDragOverCell; 699 | #ifndef GRIDCONTROL_NO_DRAGDROP 700 | CGridDropTarget m_DropTarget; // OLE Drop target for the grid 701 | #endif 702 | 703 | // Printing information 704 | CSize m_CharSize; 705 | int m_nPageHeight; 706 | CSize m_LogicalPageSize, // Page size in gridctrl units. 707 | m_PaperSize; // Page size in device units. 708 | // additional properties to support Wysiwyg printing 709 | int m_nPageWidth; 710 | int m_nPrintColumn; 711 | int m_nCurrPrintRow; 712 | int m_nNumPages; 713 | int m_nPageMultiplier; 714 | 715 | // sorting 716 | int m_bAscending; 717 | int m_nSortColumn; 718 | PFNLVCOMPARE m_pfnCompare; 719 | 720 | // EFW - Added to support shaded/unshaded printout. If true, colored 721 | // cells will print as-is. If false, all text prints as black on white. 722 | BOOL m_bShadedPrintOut; 723 | 724 | // EFW - Added support for user-definable margins. Top and bottom are in 725 | // lines. Left, right, and gap are in characters (avg width is used). 726 | int m_nHeaderHeight, m_nFooterHeight, m_nLeftMargin, 727 | m_nRightMargin, m_nTopMargin, m_nBottomMargin, m_nGap; 728 | 729 | protected: 730 | void SelectAllCells(); 731 | void SelectColumns(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE); 732 | void SelectRows(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE); 733 | void SelectCells(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE); 734 | void OnSelecting(const CCellID& currentCell); 735 | 736 | // Generated message map functions 737 | //{{AFX_MSG(CGridCtrl) 738 | afx_msg void OnPaint(); 739 | afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); 740 | afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); 741 | afx_msg void OnSize(UINT nType, int cx, int cy); 742 | afx_msg void OnLButtonUp(UINT nFlags, CPoint point); 743 | afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 744 | afx_msg void OnMouseMove(UINT nFlags, CPoint point); 745 | afx_msg void OnTimer(UINT_PTR nIDEvent); 746 | afx_msg UINT OnGetDlgCode(); 747 | afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 748 | afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); 749 | afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); 750 | afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); 751 | afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); 752 | afx_msg BOOL OnEraseBkgnd(CDC* pDC); 753 | afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); 754 | afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI); 755 | //}}AFX_MSG 756 | #ifndef _WIN32_WCE_NO_CURSOR 757 | afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); 758 | #endif 759 | #ifndef _WIN32_WCE 760 | afx_msg void OnRButtonDown(UINT nFlags, CPoint point); 761 | afx_msg void OnRButtonUp(UINT nFlags, CPoint point); // EFW - Added 762 | afx_msg void OnSysColorChange(); 763 | #endif 764 | #ifndef _WIN32_WCE_NO_CURSOR 765 | afx_msg void OnCaptureChanged(CWnd *pWnd); 766 | #endif 767 | #ifndef GRIDCONTROL_NO_CLIPBOARD 768 | afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI); 769 | afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI); 770 | afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI); 771 | #endif 772 | #if (_MFC_VER >= 0x0421) || (_WIN32_WCE >= 210) 773 | afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection); 774 | #endif 775 | #if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421) 776 | afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); 777 | #endif 778 | afx_msg LRESULT OnSetFont(WPARAM hFont, LPARAM lParam); 779 | afx_msg LRESULT OnGetFont(WPARAM hFont, LPARAM lParam); 780 | afx_msg LRESULT OnImeChar(WPARAM wCharCode, LPARAM lParam); 781 | afx_msg void OnEndInPlaceEdit(NMHDR* pNMHDR, LRESULT* pResult); 782 | DECLARE_MESSAGE_MAP() 783 | 784 | enum eMouseModes { MOUSE_NOTHING, MOUSE_SELECT_ALL, MOUSE_SELECT_COL, MOUSE_SELECT_ROW, 785 | MOUSE_SELECT_CELLS, MOUSE_SCROLLING_CELLS, 786 | MOUSE_OVER_ROW_DIVIDE, MOUSE_SIZING_ROW, 787 | MOUSE_OVER_COL_DIVIDE, MOUSE_SIZING_COL, 788 | MOUSE_PREPARE_EDIT, 789 | #ifndef GRIDCONTROL_NO_DRAGDROP 790 | MOUSE_PREPARE_DRAG, MOUSE_DRAGGING 791 | #endif 792 | }; 793 | // for sort in virtual mode, and column order, save and load layer 794 | public: 795 | typedef std::vector intlist; 796 | void Reorder(int From, int To); 797 | void SetVirtualCompare(PVIRTUALCOMPARE VirtualCompare) { m_pfnVirtualCompare = VirtualCompare;} 798 | int m_CurCol; 799 | void AllowReorderColumn(bool b=true) { m_AllowReorderColumn = b;} 800 | void EnableDragRowMode(bool b=true) { m_bDragRowMode = b; if(b) EnableDragAndDrop(); } // to change row order 801 | int GetLayer(int** pLayer); // gives back the number of ints of the area (do not forget to delete *pLayer) 802 | void SetLayer(int* pLayer); // coming from a previous GetLayer (ignored if not same number of column, or the same revision number) 803 | void ForceQuitFocusOnTab(bool b=true) { m_QuitFocusOnTab = b;} // use only if GetParent() is a CDialog 804 | void AllowSelectRowInFixedCol(bool b=true) { m_AllowSelectRowInFixedCol = b;} // 805 | // allow acces? 806 | intlist m_arRowOrder, m_arColOrder; 807 | static CGridCtrl* m_This; 808 | protected: 809 | virtual void AddSubVirtualRow(int Num, int Nb); 810 | bool m_bDragRowMode; 811 | int m_CurRow; 812 | private: 813 | void ResetVirtualOrder(); 814 | PVIRTUALCOMPARE m_pfnVirtualCompare; 815 | static bool NotVirtualCompare(int c1, int c2); 816 | bool m_InDestructor; 817 | bool m_AllowReorderColumn; 818 | bool m_QuitFocusOnTab; 819 | bool m_AllowSelectRowInFixedCol; 820 | 821 | }; 822 | 823 | // Returns the default cell implementation for the given grid region 824 | inline CGridCellBase* CGridCtrl::GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const 825 | { 826 | if (bFixedRow && bFixedCol) return (CGridCellBase*) &m_cellFixedRowColDef; 827 | if (bFixedRow) return (CGridCellBase*) &m_cellFixedRowDef; 828 | if (bFixedCol) return (CGridCellBase*) &m_cellFixedColDef; 829 | return (CGridCellBase*) &m_cellDefault; 830 | } 831 | 832 | inline CGridCellBase* CGridCtrl::GetCell(int nRow, int nCol) const 833 | { 834 | if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols) 835 | return NULL; 836 | 837 | if (GetVirtualMode()) 838 | { 839 | CGridCellBase* pCell = GetDefaultCell(nRow < m_nFixedRows, nCol < m_nFixedCols); 840 | static GV_DISPINFO gvdi; 841 | gvdi.item.row = nRow; 842 | gvdi.item.col = nCol; 843 | gvdi.item.mask = 0xFFFFFFFF; 844 | gvdi.item.nState = 0; 845 | gvdi.item.nFormat = pCell->GetFormat(); 846 | gvdi.item.iImage = pCell->GetImage(); 847 | gvdi.item.crBkClr = pCell->GetBackClr(); 848 | gvdi.item.crFgClr = pCell->GetTextClr(); 849 | gvdi.item.lParam = pCell->GetData(); 850 | memcpy(&gvdi.item.lfFont, pCell->GetFont(), sizeof(LOGFONT)); 851 | gvdi.item.nMargin = pCell->GetMargin(); 852 | gvdi.item.strText.Empty(); 853 | 854 | // Fix the state bits 855 | if (IsCellSelected(nRow, nCol)) gvdi.item.nState |= GVIS_SELECTED; 856 | if (nRow < GetFixedRowCount()) gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDROW); 857 | if (nCol < GetFixedColumnCount()) gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDCOL); 858 | if (GetFocusCell() == CCellID(nRow, nCol)) gvdi.item.nState |= GVIS_FOCUSED; 859 | if(!m_InDestructor) 860 | { 861 | gvdi.item.row = m_arRowOrder[nRow]; 862 | gvdi.item.col = m_arColOrder[nCol]; 863 | 864 | if (m_pfnCallback) 865 | m_pfnCallback(&gvdi, m_lParam); 866 | else 867 | SendDisplayRequestToParent(&gvdi); 868 | gvdi.item.row = nRow; 869 | gvdi.item.col = nCol; 870 | } 871 | static CGridCell cell; 872 | cell.SetState(gvdi.item.nState); 873 | cell.SetFormat(gvdi.item.nFormat); 874 | cell.SetImage(gvdi.item.iImage); 875 | cell.SetBackClr(gvdi.item.crBkClr); 876 | cell.SetTextClr(gvdi.item.crFgClr); 877 | cell.SetData(gvdi.item.lParam); 878 | cell.SetFont(&(gvdi.item.lfFont)); 879 | cell.SetMargin(gvdi.item.nMargin); 880 | cell.SetText(gvdi.item.strText); 881 | cell.SetGrid((CGridCtrl*)this); 882 | 883 | return (CGridCellBase*) &cell; 884 | } 885 | 886 | GRID_ROW* pRow = m_RowData[nRow]; 887 | if (!pRow) return NULL; 888 | return pRow->GetAt(m_arColOrder[nCol]); 889 | } 890 | 891 | inline BOOL CGridCtrl::SetCell(int nRow, int nCol, CGridCellBase* pCell) 892 | { 893 | if (GetVirtualMode()) 894 | return FALSE; 895 | 896 | if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols) 897 | return FALSE; 898 | 899 | GRID_ROW* pRow = m_RowData[nRow]; 900 | if (!pRow) return FALSE; 901 | 902 | pCell->SetCoords( nRow, nCol); 903 | pRow->SetAt(nCol, pCell); 904 | 905 | return TRUE; 906 | } 907 | 908 | ///////////////////////////////////////////////////////////////////////////// 909 | 910 | //{{AFX_INSERT_LOCATION}} 911 | // Microsoft Developer Studio will insert additional declarations immediately before the previous line. 912 | 913 | #endif // !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) 914 | --------------------------------------------------------------------------------