Update of /cvsroot/perl-win32-gui/Win32-GUI-Grid/MFCGrid In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15861/MFCGrid
Added Files: CellRange.h GridCell.cpp GridCell.h GridCellBase.cpp GridCellBase.h GridCellCheck.cpp GridCellCheck.h GridCellCombo.cpp GridCellCombo.h GridCellDateTime.cpp GridCellDateTime.h GridCellNumeric.cpp GridCellNumeric.h GridCellURL.cpp GridCellURL.h GridCtrl.cpp GridCtrl.h GridDropTarget.cpp GridDropTarget.h InPlaceEdit.cpp InPlaceEdit.h Makefile MemDC.h StdAfx.cpp StdAfx.h TitleTip.cpp TitleTip.h Log Message: Added to repository --- NEW FILE: InPlaceEdit.h --- ////////////////////////////////////////////////////////////////////// // InPlaceEdit.h : header file // // MFC Grid Control - inplace editing class // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.10+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_) #define AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 class CInPlaceEdit : public CEdit { // Construction public: CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, int nRow, int nColumn, CString sInitText, UINT nFirstChar); // Attributes public: // Operations public: void EndEdit(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CInPlaceEdit) public: virtual BOOL PreTranslateMessage(MSG* pMsg); protected: virtual void PostNcDestroy(); //}}AFX_VIRTUAL // Implementation public: virtual ~CInPlaceEdit(); // Generated message map functions protected: //{{AFX_MSG(CInPlaceEdit) afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg UINT OnGetDlgCode(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: int m_nRow; int m_nColumn; CString m_sInitText; UINT m_nLastChar; BOOL m_bExitOnArrows; CRect m_Rect; }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_) --- NEW FILE: GridCellCheck.cpp --- // GridCellCheck.cpp : implementation file // // MFC Grid Control - Main grid cell class // // Provides the implementation for a combobox cell type of the // grid control. // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // Parts of the code contained in this file are based on the original // CInPlaceList from http://www.codeguru.com/listview // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.22+ // // History: // 23 Jul 2001 - Complete rewrite // ///////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "GridCell.h" #include "GridCtrl.h" #include "GridCellCheck.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CGridCellCheck, CGridCell) CGridCellCheck::CGridCellCheck() : CGridCell() { m_bChecked = FALSE; //m_Rect.IsRectNull(); } CSize CGridCellCheck::GetCellExtent(CDC* pDC) { // Using SM_CXHSCROLL as a guide to the size of the checkbox int nWidth = GetSystemMetrics(SM_CXHSCROLL) + 2*GetMargin(); // Yogurt $$LR$$ CSize cellSize = CGridCell::GetCellExtent(pDC); cellSize.cx += nWidth; cellSize.cy = max (cellSize.cy, nWidth); return cellSize; } // i/o: i=dims of cell rect; o=dims of text rect BOOL CGridCellCheck::GetTextRect( LPRECT pRect) { BOOL bResult = CGridCell::GetTextRect(pRect); if (bResult) { int nWidth = GetSystemMetrics(SM_CXHSCROLL) + 2*GetMargin(); pRect->left += nWidth; if (pRect->left > pRect->right) pRect->left = pRect->right; } return bResult; } // Override draw so that when the cell is selected, a drop arrow is shown in the RHS. BOOL CGridCellCheck::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/) { BOOL bResult = CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd); #ifndef _WIN32_WCE // Store the cell's dimensions for later m_Rect = rect; CRect CheckRect = GetCheckPlacement(); rect.left = CheckRect.right; // enough room to draw? // if (CheckRect.Width() < rect.Width() && CheckRect.Height() < rect.Height()) { // Do the draw pDC->DrawFrameControl(GetCheckPlacement(), DFC_BUTTON, (m_bChecked)? DFCS_BUTTONCHECK | DFCS_CHECKED : DFCS_BUTTONCHECK); // } #endif return bResult; } void CGridCellCheck::OnClick(CPoint PointCellRelative) { // PointCellRelative is relative to the topleft of the cell. Convert to client coords PointCellRelative += m_Rect.TopLeft(); CCellID cell = GetGrid()->GetCellFromPt (PointCellRelative); if (!GetGrid()->IsCellEditable (cell)) return; // GetCheckPlacement returns the checkbox dimensions in client coords. Only check/ // uncheck if the user clicked in the box if (GetCheckPlacement().PtInRect(PointCellRelative)) { m_bChecked = !m_bChecked; GetGrid()->InvalidateRect(m_Rect); } } ////////////////////////////////////////////////////////////////////// // Operations ////////////////////////////////////////////////////////////////////// BOOL CGridCellCheck::SetCheck(BOOL bChecked /*=TRUE*/) { BOOL bTemp = m_bChecked; m_bChecked = bChecked; if (!m_Rect.IsRectEmpty()) GetGrid()->InvalidateRect(m_Rect); return bTemp; } BOOL CGridCellCheck::GetCheck() { return m_bChecked; } ////////////////////////////////////////////////////////////////////// // Protected implementation ////////////////////////////////////////////////////////////////////// // Returns the dimensions and placement of the checkbox in client coords. CRect CGridCellCheck::GetCheckPlacement() { int nWidth = GetSystemMetrics(SM_CXHSCROLL); CRect place = m_Rect + CSize(GetMargin(), GetMargin()); place.right = place.left + nWidth; place.bottom = place.top + nWidth; /* for centering int nDiff = (place.Width() - nWidth)/2; if (nDiff > 0) { place.left += nDiff; place.right = place.left + nWidth; } nDiff = (place.Height() - nWidth)/2; if (nDiff > 0) { place.top += nDiff; place.bottom = place.top + nWidth; } */ // Yogurt $$LR$$ if (m_Rect.Height() < nWidth + 2 * (int)GetMargin() ) { place.top = m_Rect.top + (m_Rect.Height() - nWidth) / 2; place.bottom = place.top + nWidth; } return place; } --- NEW FILE: GridCell.cpp --- // GridCell.cpp : implementation file // // MFC Grid Control - Main grid cell class // // Provides the implementation for the "default" cell type of the // grid control. Adds in cell editing. // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.20+ // // History: // Eric Woodruff - 20 Feb 2000 - Added PrintCell() plus other minor changes // Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase // <[EMAIL PROTECTED]> // C Maunder - 17 Jun 2000 - Font handling optimsed, Added CGridDefaultCell // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GridCell.h" #include "InPlaceEdit.h" #include "GridCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CGridCell, CGridCellBase) IMPLEMENT_DYNCREATE(CGridDefaultCell, CGridCell) ///////////////////////////////////////////////////////////////////////////// // GridCell CGridCell::CGridCell() { m_plfFont = NULL; CGridCell::Reset(); } CGridCell::~CGridCell() { delete m_plfFont; } ///////////////////////////////////////////////////////////////////////////// // GridCell Attributes void CGridCell::operator=(const CGridCell& cell) { if (this != &cell) CGridCellBase::operator=(cell); } void CGridCell::Reset() { CGridCellBase::Reset(); m_strText.Empty(); m_nImage = -1; m_lParam = NULL; // BUG FIX J. Bloggs 20/10/03 m_pGrid = NULL; m_bEditing = FALSE; m_pEditWnd = NULL; m_nFormat = (DWORD)-1; // Use default from CGridDefaultCell m_crBkClr = CLR_DEFAULT; // Background colour (or CLR_DEFAULT) m_crFgClr = CLR_DEFAULT; // Forground colour (or CLR_DEFAULT) m_nMargin = (UINT)-1; // Use default from CGridDefaultCell delete m_plfFont; m_plfFont = NULL; // Cell font } void CGridCell::SetFont(const LOGFONT* plf) { if (plf == NULL) { delete m_plfFont; m_plfFont = NULL; } else { if (!m_plfFont) m_plfFont = new LOGFONT; if (m_plfFont) memcpy(m_plfFont, plf, sizeof(LOGFONT)); } } LOGFONT* CGridCell::GetFont() const { if (m_plfFont == NULL) { CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); if (!pDefaultCell) return NULL; return pDefaultCell->GetFont(); } return m_plfFont; } CFont* CGridCell::GetFontObject() const { // If the default font is specified, use the default cell implementation if (m_plfFont == NULL) { CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); if (!pDefaultCell) return NULL; return pDefaultCell->GetFontObject(); } else { static CFont Font; Font.DeleteObject(); Font.CreateFontIndirect(m_plfFont); return &Font; } } DWORD CGridCell::GetFormat() const { if (m_nFormat == (DWORD)-1) { CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); if (!pDefaultCell) return 0; return pDefaultCell->GetFormat(); } return m_nFormat; } UINT CGridCell::GetMargin() const { if (m_nMargin == (UINT)-1) { CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); if (!pDefaultCell) return 0; return pDefaultCell->GetMargin(); } return m_nMargin; } ///////////////////////////////////////////////////////////////////////////// // GridCell Operations BOOL CGridCell::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar) { if ( m_bEditing ) { if (m_pEditWnd) m_pEditWnd->SendMessage ( WM_CHAR, nChar ); } else { DWORD dwStyle = ES_LEFT; if (GetFormat() & DT_RIGHT) dwStyle = ES_RIGHT; else if (GetFormat() & DT_CENTER) dwStyle = ES_CENTER; m_bEditing = TRUE; // InPlaceEdit auto-deletes itself CGridCtrl* pGrid = GetGrid(); m_pEditWnd = new CInPlaceEdit(pGrid, rect, dwStyle, nID, nRow, nCol, GetText(), nChar); } return TRUE; } void CGridCell::EndEdit() { if (m_pEditWnd) ((CInPlaceEdit*)m_pEditWnd)->EndEdit(); } void CGridCell::OnEndEdit() { m_bEditing = FALSE; m_pEditWnd = NULL; } ///////////////////////////////////////////////////////////////////////////// // CGridDefaultCell CGridDefaultCell::CGridDefaultCell() { #ifdef _WIN32_WCE m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX; #else m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX | DT_END_ELLIPSIS; #endif m_crFgClr = CLR_DEFAULT; m_crBkClr = CLR_DEFAULT; m_Size = CSize(30,10); m_dwStyle = 0; #ifdef _WIN32_WCE LOGFONT lf; GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &lf); SetFont(&lf); #else // not CE NONCLIENTMETRICS ncm; ncm.cbSize = sizeof(NONCLIENTMETRICS); VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)); SetFont(&(ncm.lfMessageFont)); #endif } CGridDefaultCell::~CGridDefaultCell() { m_Font.DeleteObject(); } void CGridDefaultCell::SetFont(const LOGFONT* plf) { ASSERT(plf); if (!plf) return; m_Font.DeleteObject(); m_Font.CreateFontIndirect(plf); CGridCell::SetFont(plf); // Get the font size and hence the default cell size CDC* pDC = CDC::FromHandle(::GetDC(NULL)); if (pDC) { CFont* pOldFont = pDC->SelectObject(&m_Font); SetMargin(pDC->GetTextExtent(_T(" "), 1).cx); m_Size = pDC->GetTextExtent(_T(" XXXXXXXXXXXX "), 14); m_Size.cy = (m_Size.cy * 3) / 2; pDC->SelectObject(pOldFont); ReleaseDC(NULL, pDC->GetSafeHdc()); } else { SetMargin(3); m_Size = CSize(40,16); } } LOGFONT* CGridDefaultCell::GetFont() const { ASSERT(m_plfFont); // This is the default - it CAN'T be NULL! return m_plfFont; } CFont* CGridDefaultCell::GetFontObject() const { ASSERT(m_Font.GetSafeHandle()); return (CFont*) &m_Font; } --- NEW FILE: Makefile --- # Microsoft Developer Studio Generated NMAKE File, Based on MFCGrid.dsp !IF "$(OS)" == "Windows_NT" NULL= !ELSE NULL=nul !ENDIF CPP=cl.exe RSC=rc.exe OUTDIR=.\Lib INTDIR=.\Build # Begin Custom Macros OutDir=.\Lib # End Custom Macros ALL : "$(OUTDIR)\MFCGrid.lib" CLEAN : [EMAIL PROTECTED] "$(INTDIR)\GridCellUrl.obj" [EMAIL PROTECTED] "$(INTDIR)\GridCellNumeric.obj" [EMAIL PROTECTED] "$(INTDIR)\GridCellDateTime.obj" [EMAIL PROTECTED] "$(INTDIR)\GridCellCheck.obj" [EMAIL PROTECTED] "$(INTDIR)\GridCellCombo.obj" [EMAIL PROTECTED] "$(INTDIR)\GridCell.obj" [EMAIL PROTECTED] "$(INTDIR)\GridCellBase.obj" [EMAIL PROTECTED] "$(INTDIR)\GridCtrl.obj" [EMAIL PROTECTED] "$(INTDIR)\GridDropTarget.obj" [EMAIL PROTECTED] "$(INTDIR)\InPlaceEdit.obj" [EMAIL PROTECTED] "$(INTDIR)\StdAfx.obj" [EMAIL PROTECTED] "$(INTDIR)\TitleTip.obj" [EMAIL PROTECTED] "$(INTDIR)\vc60.idb" [EMAIL PROTECTED] "$(INTDIR)\MFCGrid.pch" [EMAIL PROTECTED] "$(OUTDIR)\MFCGrid.lib" "$(OUTDIR)" : mkdir "$(OUTDIR)" "$(INTDIR)" : mkdir "$(INTDIR)" CPP=cl.exe CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D"_WINDLL" /D"_USRDLL" /D "_AFXDLL" /D "_AFX_NOFORCE_LIBS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c BSC32=bscmake.exe BSC32_FLAGS=/nologo /o"$(OUTDIR)\MFCGrid.bsc" BSC32_SBRS= \ LIB32=link.exe -lib LIB32_FLAGS=/nologo /out:"$(OUTDIR)\MFCGrid.lib" LIB32_OBJS= \ "$(INTDIR)\TitleTip.obj" \ "$(INTDIR)\InPlaceEdit.obj" \ "$(INTDIR)\GridDropTarget.obj" \ "$(INTDIR)\GridCtrl.obj" \ "$(INTDIR)\GridCellBase.obj" \ "$(INTDIR)\GridCell.obj" \ "$(INTDIR)\GridCellNumeric.obj" \ "$(INTDIR)\GridCellUrl.obj" \ "$(INTDIR)\GridCellDateTime.obj" \ "$(INTDIR)\GridCellCheck.obj" \ "$(INTDIR)\GridCellCombo.obj" \ "$(INTDIR)\StdAfx.obj" "$(OUTDIR)\MFCGrid.lib" : "$(OUTDIR)" "$(INTDIR)" $(DEF_FILE) $(LIB32_OBJS) $(LIB32) @<< $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) << .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << GridCell.cpp : \ "CellRange.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "GridDropTarget.h"\ "InPlaceEdit.h"\ "StdAfx.h"\ "TitleTip.h" GridCellBase.cpp : \ "CellRange.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "GridDropTarget.h"\ "StdAfx.h"\ "TitleTip.h" GridCtrl.cpp : \ "CellRange.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "GridDropTarget.h"\ "MemDC.h"\ "StdAfx.h"\ "TitleTip.h" GridDropTarget.cpp : \ "CellRange.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "GridDropTarget.h"\ "StdAfx.h"\ "TitleTip.h" InPlaceEdit.cpp : \ "CellRange.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "GridDropTarget.h"\ "InPlaceEdit.h"\ "StdAfx.h"\ "TitleTip.h" StdAfx.cpp : \ "StdAfx.h" TitleTip.cpp : \ "CellRange.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "GridDropTarget.h"\ "StdAfx.h"\ "TitleTip.h" GridCellNumeric.cpp : \ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "InPlaceEdit.h"\ "StdAfx.h" GridCellDateTime.cpp : \ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "StdAfx.h" GridCellCheck.cpp : \ "GridCellCheck.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "StdAfx.h" GridCellCombo.cpp : \ "GridCellCombo.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "StdAfx.h" GridCellUrl.cpp : \ "GridCellUrl.h"\ "GridCell.h"\ "GridCellBase.h"\ "GridCtrl.h"\ "StdAfx.h" SOURCE=GridCell.cpp "$(INTDIR)\GridCell.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridCellBase.cpp "$(INTDIR)\GridCellBase.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridCtrl.cpp "$(INTDIR)\GridCtrl.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridDropTarget.cpp "$(INTDIR)\GridDropTarget.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=InPlaceEdit.cpp "$(INTDIR)\InPlaceEdit.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=StdAfx.cpp "$(INTDIR)\StdAfx.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=TitleTip.cpp "$(INTDIR)\TitleTip.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridCellNumeric.cpp "$(INTDIR)\GridCellNumeric.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridCellDateTime.cpp "$(INTDIR)\GridCellDateTime.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridCellCheck.cpp "$(INTDIR)\GridCellCheck.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridCellCombo.cpp "$(INTDIR)\GridCellCombo.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) SOURCE=GridCellUrl.cpp "$(INTDIR)\GridCellUrl.obj" : $(SOURCE) "$(INTDIR)" $(CPP) $(CPP_PROJ) $(SOURCE) --- NEW FILE: GridCellCombo.h --- #if !defined(AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_) #define AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 ///////////////////////////////////////////////////////////////////////////// // GridCellCombo.h : header file // // MFC Grid Control - Grid combo cell class header file // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.10 // ////////////////////////////////////////////////////////////////////// #include "GridCell.h" class CGridCellCombo : public CGridCell { friend class CGridCtrl; DECLARE_DYNCREATE(CGridCellCombo) public: CGridCellCombo(); // editing cells public: virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar); virtual CWnd* GetEditWnd() const; virtual void EndEdit(); // Operations public: virtual CSize GetCellExtent(CDC* pDC); // CGridCellCombo specific calls public: void SetOptions(const CStringArray& ar); void SetStyle(DWORD dwStyle) { m_dwStyle = dwStyle; } DWORD GetStyle() { return m_dwStyle; } protected: virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE); CStringArray m_Strings; DWORD m_dwStyle; }; class CGridCellList : public CGridCellCombo { DECLARE_DYNCREATE(CGridCellList) public: CGridCellList(); }; ///////////////////////////////////////////////////////////////////////////// // CComboEdit window #define IDC_COMBOEDIT 1001 class CComboEdit : public CEdit { // Construction public: CComboEdit(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CComboEdit) virtual BOOL PreTranslateMessage(MSG* pMsg); //}}AFX_VIRTUAL // Implementation public: virtual ~CComboEdit(); // Generated message map functions protected: //{{AFX_MSG(CComboEdit) afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// // CInPlaceList window class CInPlaceList : public CComboBox { friend class CComboEdit; // Construction public: CInPlaceList(CWnd* pParent, // parent CRect& rect, // dimensions & location DWORD dwStyle, // window/combobox style UINT nID, // control ID int nRow, int nColumn, // row and column COLORREF crFore, COLORREF crBack, // Foreground, background colour CStringArray& Items, // Items in list CString sInitText, // initial selection UINT nFirstChar); // first character to pass to control // Attributes public: CComboEdit m_edit; // subclassed edit control // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CInPlaceList) protected: virtual void PostNcDestroy(); //}}AFX_VIRTUAL // Implementation public: virtual ~CInPlaceList(); void EndEdit(); protected: int GetCorrectDropWidth(); // Generated message map functions protected: //{{AFX_MSG(CInPlaceList) afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnDropdown(); afx_msg void OnSelChange(); afx_msg UINT OnGetDlgCode(); afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor); //}}AFX_MSG //afx_msg void OnSelendOK(); DECLARE_MESSAGE_MAP() private: int m_nNumLines; CString m_sInitText; int m_nRow; int m_nCol; UINT m_nLastChar; BOOL m_bExitOnArrows; COLORREF m_crForeClr, m_crBackClr; }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_) --- NEW FILE: GridCellURL.h --- // GridCellURL.h: interface for the CGridCellURL class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GridCellURL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_) #define AFX_GridCellURL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "GridCell.h" typedef struct { LPCTSTR szURLPrefix; int nLength; } URLStruct; class CGridCellURL : public CGridCell { DECLARE_DYNCREATE(CGridCellURL) public: CGridCellURL(); virtual ~CGridCellURL(); virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE); // virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar); virtual LPCTSTR GetTipText() { return NULL; } void SetAutoLaunchUrl(BOOL bLaunch = TRUE) { m_bLaunchUrl = bLaunch; } BOOL GetAutoLaunchUrl() { return m_bLaunchUrl && !m_bEditing; } protected: virtual BOOL OnSetCursor(); virtual void OnClick(CPoint PointCellRelative); BOOL HasUrl(CString str); BOOL OverURL(CPoint& pt, CString& strURL); protected: #ifndef _WIN32_WCE static HCURSOR g_hLinkCursor; // Hyperlink mouse cursor HCURSOR GetHandCursor(); #endif static URLStruct g_szURIprefixes[]; protected: COLORREF m_clrUrl; COLORREF m_clrOld; BOOL m_bLaunchUrl; CRect m_Rect; }; #endif // !defined(AFX_GridCellURL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_) --- NEW FILE: GridCellDateTime.h --- // GridCellDateTime.h: interface for the CGridCellDateTime class. // // Provides the implementation for a datetime picker cell type of the // grid control. // // For use with CGridCtrl v2.22+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_) #define AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "GridCell.h" #include "afxdtctl.h" // for CDateTimeCtrl class CGridCellDateTime : public CGridCell { friend class CGridCtrl; DECLARE_DYNCREATE(CGridCellDateTime) CTime m_cTime; DWORD m_dwStyle; public: CGridCellDateTime(); CGridCellDateTime(DWORD dwStyle); virtual ~CGridCellDateTime(); // editing cells public: void Init(DWORD dwStyle); virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar); virtual CWnd* GetEditWnd() const; virtual void EndEdit(); virtual CSize GetCellExtent(CDC* pDC); CTime* GetTime() {return &m_cTime;}; void SetTime(CTime time); }; class CInPlaceDateTime : public CDateTimeCtrl { // Construction public: CInPlaceDateTime(CWnd* pParent, // parent CRect& rect, // dimensions & location DWORD dwStyle, // window/combobox style UINT nID, // control ID int nRow, int nColumn, // row and column COLORREF crFore, COLORREF crBack, // Foreground, background colour CTime* pcTime, UINT nFirstChar); // first character to pass to control // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CInPlaceList) protected: virtual void PostNcDestroy(); //}}AFX_VIRTUAL // Implementation public: virtual ~CInPlaceDateTime(); void EndEdit(); // Generated message map functions protected: //{{AFX_MSG(CInPlaceList) afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg UINT OnGetDlgCode(); afx_msg void OnCloseUp ( NMHDR * pNotifyStruct, LRESULT* result ); //}}AFX_MSG //afx_msg void OnSelendOK(); DECLARE_MESSAGE_MAP() private: CTime* m_pcTime; int m_nRow; int m_nCol; UINT m_nLastChar; BOOL m_bExitOnArrows; COLORREF m_crForeClr, m_crBackClr; }; class CGridCellTime : public CGridCellDateTime { CGridCellTime():CGridCellDateTime(DTS_TIMEFORMAT) {} DECLARE_DYNCREATE(CGridCellTime) }; class CGridCellDateCal : public CGridCellDateTime { CGridCellDateCal():CGridCellDateTime() {} virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar); DECLARE_DYNCREATE(CGridCellDateCal) }; #endif // !defined(AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_) --- NEW FILE: GridCell.h --- ///////////////////////////////////////////////////////////////////////////// // GridCell.h : header file // // MFC Grid Control - Grid cell class header file // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.20+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) #define AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 class CGridCtrl; #include "GridCellBase.h" // Each cell contains one of these. Fields "row" and "column" are not stored since we // will usually have acces to them in other ways, and they are an extra 8 bytes per // cell that is probably unnecessary. class CGridCell : public CGridCellBase { friend class CGridCtrl; DECLARE_DYNCREATE(CGridCell) // Construction/Destruction public: CGridCell(); virtual ~CGridCell(); // Attributes public: void operator=(const CGridCell& cell); virtual void SetText(LPCTSTR szText) { m_strText = szText; } virtual void SetImage(int nImage) { m_nImage = nImage; } virtual void SetData(LPARAM lParam) { m_lParam = lParam; } virtual void SetGrid(CGridCtrl* pGrid) { m_pGrid = pGrid; } // virtual void SetState(const DWORD nState); - use base class version virtual void SetFormat(DWORD nFormat) { m_nFormat = nFormat; } virtual void SetTextClr(COLORREF clr) { m_crFgClr = clr; } virtual void SetBackClr(COLORREF clr) { m_crBkClr = clr; } virtual void SetFont(const LOGFONT* plf); virtual void SetMargin(UINT nMargin) { m_nMargin = nMargin; } virtual CWnd* GetEditWnd() const { return m_pEditWnd; } virtual void SetCoords(int /*nRow*/, int /*nCol*/) {} // don't need to know the row and // column for base implementation virtual LPCTSTR GetText() const { return (m_strText.IsEmpty())? _T("") : LPCTSTR(m_strText); } virtual int GetImage() const { return m_nImage; } virtual LPARAM GetData() const { return m_lParam; } virtual CGridCtrl* GetGrid() const { return m_pGrid; } // virtual DWORD GetState() const - use base class virtual DWORD GetFormat() const; virtual COLORREF GetTextClr() const { return m_crFgClr; } // TODO: change to use default cell virtual COLORREF GetBackClr() const { return m_crBkClr; } virtual LOGFONT* GetFont() const; virtual CFont* GetFontObject() const; virtual UINT GetMargin() const; virtual BOOL IsEditing() const { return m_bEditing; } virtual BOOL IsDefaultFont() const { return (m_plfFont == NULL); } virtual void Reset(); // editing cells public: virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar); virtual void EndEdit(); protected: virtual void OnEndEdit(); protected: CString m_strText; // Cell text (or binary data if you wish...) LPARAM m_lParam; // 32-bit value to associate with item int m_nImage; // Index of the list view items icon DWORD m_nFormat; COLORREF m_crFgClr; COLORREF m_crBkClr; LOGFONT* m_plfFont; UINT m_nMargin; BOOL m_bEditing; // Cell being edited? CGridCtrl* m_pGrid; // Parent grid control CWnd* m_pEditWnd; }; // This class is for storing grid default values. It's a little heavy weight, so // don't use it in bulk class CGridDefaultCell : public CGridCell { DECLARE_DYNCREATE(CGridDefaultCell) // Construction/Destruction public: CGridDefaultCell(); virtual ~CGridDefaultCell(); public: virtual DWORD GetStyle() const { return m_dwStyle; } virtual void SetStyle(DWORD dwStyle) { m_dwStyle = dwStyle; } virtual int GetWidth() const { return m_Size.cx; } virtual int GetHeight() const { return m_Size.cy; } virtual void SetWidth(int nWidth) { m_Size.cx = nWidth; } virtual void SetHeight(int nHeight) { m_Size.cy = nHeight; } // Disable these properties virtual void SetData(LPARAM /*lParam*/) { ASSERT(FALSE); } virtual void SetState(DWORD /*nState*/) { ASSERT(FALSE); } virtual DWORD GetState() const { return CGridCell::GetState()|GVIS_READONLY; } virtual void SetCoords( int /*row*/, int /*col*/) { ASSERT(FALSE); } virtual void SetFont(const LOGFONT* /*plf*/); virtual LOGFONT* GetFont() const; virtual CFont* GetFontObject() const; protected: CSize m_Size; // Default Size CFont m_Font; // Cached font DWORD m_dwStyle; // Cell Style - unused }; //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) --- NEW FILE: GridCellNumeric.h --- // GridCellNumeric.h: interface for the CGridCellNumeric class. // // Written by Andrew Truckle [EMAIL PROTECTED] // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_) #define AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "GridCell.h" class CGridCellNumeric : public CGridCell { DECLARE_DYNCREATE(CGridCellNumeric) public: virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar); virtual void EndEdit(); }; #endif // !defined(AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_) --- NEW FILE: CellRange.h --- /////////////////////////////////////////////////////////////////////// // CellRange.h: header file // // MFC Grid Control - interface for the CCellRange class. // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.20+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_) #define AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // The code contained in this file is based on the original // WorldCom Grid control written by Joe Willcoxson, // mailto:[EMAIL PROTECTED] // http://users.aol.com/chinajoe class CCellID { // Attributes public: int row, col; // Operations public: explicit CCellID(int nRow = -1, int nCol = -1) : row(nRow), col(nCol) {} int IsValid() const { return (row >= 0 && col >= 0); } int operator==(const CCellID& rhs) const { return (row == rhs.row && col == rhs.col); } int operator!=(const CCellID& rhs) const { return !operator==(rhs); } }; class CCellRange { public: CCellRange(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1) { Set(nMinRow, nMinCol, nMaxRow, nMaxCol); } void Set(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1); int IsValid() const; int InRange(int row, int col) const; int InRange(const CCellID& cellID) const; int Count() { return (m_nMaxRow - m_nMinRow + 1) * (m_nMaxCol - m_nMinCol + 1); } CCellID GetTopLeft() const; CCellRange Intersect(const CCellRange& rhs) const; int GetMinRow() const {return m_nMinRow;} void SetMinRow(int minRow) {m_nMinRow = minRow;} int GetMinCol() const {return m_nMinCol;} void SetMinCol(int minCol) {m_nMinCol = minCol;} int GetMaxRow() const {return m_nMaxRow;} void SetMaxRow(int maxRow) {m_nMaxRow = maxRow;} int GetMaxCol() const {return m_nMaxCol;} void SetMaxCol(int maxCol) {m_nMaxCol = maxCol;} int GetRowSpan() const {return m_nMaxRow - m_nMinRow + 1;} int GetColSpan() const {return m_nMaxCol - m_nMinCol + 1;} void operator=(const CCellRange& rhs); int operator==(const CCellRange& rhs); int operator!=(const CCellRange& rhs); protected: int m_nMinRow; int m_nMinCol; int m_nMaxRow; int m_nMaxCol; }; inline void CCellRange::Set(int minRow, int minCol, int maxRow, int maxCol) { m_nMinRow = minRow; m_nMinCol = minCol; m_nMaxRow = maxRow; m_nMaxCol = maxCol; } inline void CCellRange::operator=(const CCellRange& rhs) { if (this != &rhs) Set(rhs.m_nMinRow, rhs.m_nMinCol, rhs.m_nMaxRow, rhs.m_nMaxCol); } inline int CCellRange::operator==(const CCellRange& rhs) { return ((m_nMinRow == rhs.m_nMinRow) && (m_nMinCol == rhs.m_nMinCol) && (m_nMaxRow == rhs.m_nMaxRow) && (m_nMaxCol == rhs.m_nMaxCol)); } inline int CCellRange::operator!=(const CCellRange& rhs) { return !operator==(rhs); } inline int CCellRange::IsValid() const { return (m_nMinRow >= 0 && m_nMinCol >= 0 && m_nMaxRow >= 0 && m_nMaxCol >= 0 && m_nMinRow <= m_nMaxRow && m_nMinCol <= m_nMaxCol); } inline int CCellRange::InRange(int row, int col) const { return (row >= m_nMinRow && row <= m_nMaxRow && col >= m_nMinCol && col <= m_nMaxCol); } inline int CCellRange::InRange(const CCellID& cellID) const { return InRange(cellID.row, cellID.col); } inline CCellID CCellRange::GetTopLeft() const { return CCellID(m_nMinRow, m_nMinCol); } inline CCellRange CCellRange::Intersect(const CCellRange& rhs) const { return CCellRange(max(m_nMinRow,rhs.m_nMinRow), max(m_nMinCol,rhs.m_nMinCol), min(m_nMaxRow,rhs.m_nMaxRow), min(m_nMaxCol,rhs.m_nMaxCol)); } #endif // !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_) --- NEW FILE: GridCellBase.cpp --- // GridCellBase.cpp : implementation file // // MFC Grid Control - Main grid cell base class // // Provides the implementation for the base cell type of the // grid control. No data is stored (except for state) but default // implementations of drawing, printingetc provided. MUST be derived // from to be used. // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.22+ // // History: // Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase // C Maunder - 19 May 2000 - Fixed sort arrow drawing (Ivan Ilinov) // C Maunder - 29 Aug 2000 - operator= checks for NULL font before setting (Martin Richter) // C Maunder - 15 Oct 2000 - GetTextExtent fixed (Martin Richter) // C Maunder - 1 Jan 2001 - Added ValidateEdit // Yogurt - 13 Mar 2004 - GetCellExtent fixed // // NOTES: Each grid cell should take care of it's own drawing, though the Draw() // method takes an "erase background" paramter that is called if the grid // decides to draw the entire grid background in on hit. Certain ambient // properties such as the default font to use, and hints on how to draw // fixed cells should be fetched from the parent grid. The grid trusts the // cells will behave in a certain way, and the cells trust the grid will // supply accurate information. // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GridCtrl.h" #include "GridCellBase.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC(CGridCellBase, CObject) ///////////////////////////////////////////////////////////////////////////// // GridCellBase CGridCellBase::CGridCellBase() { Reset(); } CGridCellBase::~CGridCellBase() { } ///////////////////////////////////////////////////////////////////////////// // GridCellBase Operations void CGridCellBase::Reset() { m_nState = 0; } void CGridCellBase::operator=(const CGridCellBase& cell) { if (this == &cell) return; SetGrid(cell.GetGrid()); // do first in case of dependencies SetText(cell.GetText()); SetImage(cell.GetImage()); SetData(cell.GetData()); SetState(cell.GetState()); SetFormat(cell.GetFormat()); SetTextClr(cell.GetTextClr()); SetBackClr(cell.GetBackClr()); SetFont(cell.IsDefaultFont()? NULL : cell.GetFont()); SetMargin(cell.GetMargin()); } ///////////////////////////////////////////////////////////////////////////// // CGridCellBase Attributes // Returns a pointer to a cell that holds default values for this particular type of cell CGridCellBase* CGridCellBase::GetDefaultCell() const { if (GetGrid()) return GetGrid()->GetDefaultCell(IsFixedRow(), IsFixedCol()); return NULL; } ///////////////////////////////////////////////////////////////////////////// // CGridCellBase Operations // EFW - Various changes to make it draw cells better when using alternate // color schemes. Also removed printing references as that's now done // by PrintCell() and fixed the sort marker so that it doesn't draw out // of bounds. BOOL CGridCellBase::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/) { // Note - all through this function we totally brutalise 'rect'. Do not // depend on it's value being that which was passed in. CGridCtrl* pGrid = GetGrid(); ASSERT(pGrid); if (!pGrid || !pDC) return FALSE; if( rect.Width() <= 0 || rect.Height() <= 0) // prevents imagelist item from drawing even return FALSE; // though cell is hidden //TRACE3("Drawing %scell %d, %d\n", IsFixed()? _T("Fixed ") : _T(""), nRow, nCol); int nSavedDC = pDC->SaveDC(); pDC->SetBkMode(TRANSPARENT); // Get the default cell implementation for this kind of cell. We use it if this cell // has anything marked as "default" CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); if (!pDefaultCell) return FALSE; // Set up text and background colours COLORREF TextClr, TextBkClr; TextClr = (GetTextClr() == CLR_DEFAULT)? pDefaultCell->GetTextClr() : GetTextClr(); if (GetBackClr() == CLR_DEFAULT) TextBkClr = pDefaultCell->GetBackClr(); else { bEraseBkgnd = TRUE; TextBkClr = GetBackClr(); } // Draw cell background and highlighting (if necessary) if ( IsFocused() || IsDropHighlighted() ) { // Always draw even in list mode so that we can tell where the // cursor is at. Use the highlight colors though. if(GetState() & GVIS_SELECTED) { TextBkClr = ::GetSysColor(COLOR_HIGHLIGHT); TextClr = ::GetSysColor(COLOR_HIGHLIGHTTEXT); bEraseBkgnd = TRUE; } rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom if (bEraseBkgnd) { TRY { CBrush brush(TextBkClr); pDC->FillRect(rect, &brush); } CATCH(CResourceException, e) { //e->ReportError(); } END_CATCH } // Don't adjust frame rect if no grid lines so that the // whole cell is enclosed. if(pGrid->GetGridLines() != GVL_NONE) { rect.right--; rect.bottom--; } if (pGrid->GetFrameFocusCell()) { // Use same color as text to outline the cell so that it shows // up if the background is black. TRY { CBrush brush(TextClr); pDC->FrameRect(rect, &brush); } CATCH(CResourceException, e) { //e->ReportError(); } END_CATCH } pDC->SetTextColor(TextClr); // Adjust rect after frame draw if no grid lines if(pGrid->GetGridLines() == GVL_NONE) { rect.right--; rect.bottom--; } //rect.DeflateRect(0,1,1,1); - Removed by Yogurt } else if ((GetState() & GVIS_SELECTED)) { rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom pDC->FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT)); rect.right--; rect.bottom--; pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); } else { if (bEraseBkgnd) { rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom CBrush brush(TextBkClr); pDC->FillRect(rect, &brush); rect.right--; rect.bottom--; } pDC->SetTextColor(TextClr); } // Draw lines only when wanted if (IsFixed() && pGrid->GetGridLines() != GVL_NONE) { CCellID FocusCell = pGrid->GetFocusCell(); // As above, always show current location even in list mode so // that we know where the cursor is at. BOOL bHiliteFixed = pGrid->GetTrackFocusCell() && pGrid->IsValid(FocusCell) && (FocusCell.row == nRow || FocusCell.col == nCol); // If this fixed cell is on the same row/col as the focus cell, // highlight it. if (bHiliteFixed) { rect.right++; rect.bottom++; pDC->DrawEdge(rect, BDR_SUNKENINNER /*EDGE_RAISED*/, BF_RECT); rect.DeflateRect(1,1); } else { CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)), darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)), *pOldPen = pDC->GetCurrentPen(); pDC->SelectObject(&lightpen); pDC->MoveTo(rect.right, rect.top); pDC->LineTo(rect.left, rect.top); pDC->LineTo(rect.left, rect.bottom); pDC->SelectObject(&darkpen); pDC->MoveTo(rect.right, rect.top); pDC->LineTo(rect.right, rect.bottom); pDC->LineTo(rect.left, rect.bottom); pDC->SelectObject(pOldPen); rect.DeflateRect(1,1); } } // Draw Text and image #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) if (!pDC->m_bPrinting) #endif { CFont *pFont = GetFontObject(); ASSERT(pFont); if (pFont) pDC->SelectObject(pFont); } //rect.DeflateRect(GetMargin(), 0); - changed by Yogurt rect.DeflateRect(GetMargin(), GetMargin()); rect.right++; rect.bottom++; if (pGrid->GetImageList() && GetImage() >= 0) { IMAGEINFO Info; if (pGrid->GetImageList()->GetImageInfo(GetImage(), &Info)) { // would like to use a clipping region but seems to have issue // working with CMemDC directly. Instead, don't display image // if any part of it cut-off // // CRgn rgn; // rgn.CreateRectRgnIndirect(rect); // pDC->SelectClipRgn(&rgn); // rgn.DeleteObject(); /* // removed by Yogurt int nImageWidth = Info.rcImage.right-Info.rcImage.left+1; int nImageHeight = Info.rcImage.bottom-Info.rcImage.top+1; if( nImageWidth + rect.left <= rect.right + (int)(2*GetMargin()) && nImageHeight + rect.top <= rect.bottom + (int)(2*GetMargin()) ) { pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL); } */ // Added by Yogurt int nImageWidth = Info.rcImage.right-Info.rcImage.left; int nImageHeight = Info.rcImage.bottom-Info.rcImage.top; if ((nImageWidth + rect.left <= rect.right) && (nImageHeight + rect.top <= rect.bottom)) pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL); //rect.left += nImageWidth+GetMargin(); } } // Draw sort arrow if (pGrid->GetSortColumn() == nCol && nRow == 0) { CSize size = pDC->GetTextExtent(_T("M")); int nOffset = 2; // Base the size of the triangle on the smaller of the column // height or text height with a slight offset top and bottom. // Otherwise, it can get drawn outside the bounds of the cell. size.cy -= (nOffset * 2); if (size.cy >= rect.Height()) size.cy = rect.Height() - (nOffset * 2); size.cx = size.cy; // Make the dimensions square // Kludge for vertical text BOOL bVertical = (GetFont()->lfEscapement == 900); // Only draw if it'll fit! //if (size.cx + rect.left < rect.right + (int)(2*GetMargin())) - changed / Yogurt if (size.cx + rect.left < rect.right) { int nTriangleBase = rect.bottom - nOffset - size.cy; // Triangle bottom right //int nTriangleBase = (rect.top + rect.bottom - size.cy)/2; // Triangle middle right //int nTriangleBase = rect.top + nOffset; // Triangle top right //int nTriangleLeft = rect.right - size.cx; // Triangle RHS //int nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle //int nTriangleLeft = rect.left; // Triangle LHS int nTriangleLeft; if (bVertical) nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle else nTriangleLeft = rect.right - size.cx; // Triangle RHS CPen penShadow(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW)); CPen penLight(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT)); if (pGrid->GetSortAscending()) { // Draw triangle pointing upwards CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight); pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1); pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + 1 ); pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + size.cy + 1); pDC->LineTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1); pDC->SelectObject(&penShadow); pDC->MoveTo( nTriangleLeft, nTriangleBase + size.cy ); pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase ); pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase + size.cy ); pDC->LineTo( nTriangleLeft, nTriangleBase + size.cy ); pDC->SelectObject(pOldPen); } else { // Draw triangle pointing downwards CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight); pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + 1 ); pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + size.cy + 1 ); pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + 1 ); pDC->LineTo( nTriangleLeft + 1, nTriangleBase + 1 ); pDC->SelectObject(&penShadow); pDC->MoveTo( nTriangleLeft, nTriangleBase ); pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase + size.cy ); pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase ); pDC->LineTo( nTriangleLeft, nTriangleBase ); pDC->SelectObject(pOldPen); } if (!bVertical) rect.right -= size.cy; } } // We want to see '&' characters so use DT_NOPREFIX GetTextRect(rect); rect.right++; rect.bottom++; DrawText(pDC->m_hDC, GetText(), -1, rect, GetFormat() | DT_NOPREFIX); pDC->RestoreDC(nSavedDC); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CGridCellBase Mouse and Cursor events // Not yet implemented void CGridCellBase::OnMouseEnter() { TRACE0("Mouse entered cell\n"); } void CGridCellBase::OnMouseOver() { //TRACE0("Mouse over cell\n"); } // Not Yet Implemented void CGridCellBase::OnMouseLeave() { TRACE0("Mouse left cell\n"); } void CGridCellBase::OnClick( CPoint PointCellRelative) { UNUSED_ALWAYS(PointCellRelative); TRACE2("Mouse Left btn up in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); } void CGridCellBase::OnClickDown( CPoint PointCellRelative) { UNUSED_ALWAYS(PointCellRelative); TRACE2("Mouse Left btn down in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); } void CGridCellBase::OnRClick( CPoint PointCellRelative) { UNUSED_ALWAYS(PointCellRelative); TRACE2("Mouse right-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); } void CGridCellBase::OnDblClick( CPoint PointCellRelative) { UNUSED_ALWAYS(PointCellRelative); TRACE2("Mouse double-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y); } // Return TRUE if you set the cursor BOOL CGridCellBase::OnSetCursor() { #ifndef _WIN32_WCE_NO_CURSOR SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); #endif return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CGridCellBase editing void CGridCellBase::OnEndEdit() { ASSERT( FALSE); } BOOL CGridCellBase::ValidateEdit(LPCTSTR str) { UNUSED_ALWAYS(str); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CGridCellBase Sizing BOOL CGridCellBase::GetTextRect( LPRECT pRect) // i/o: i=dims of cell rect; o=dims of text rect { if (GetImage() >= 0) { IMAGEINFO Info; CGridCtrl* pGrid = GetGrid(); CImageList* pImageList = pGrid->GetImageList(); if (pImageList && pImageList->GetImageInfo( GetImage(), &Info)) { int nImageWidth = Info.rcImage.right-Info.rcImage.left; //+1; pRect->left += nImageWidth + GetMargin(); } } return TRUE; } // By default this uses the selected font (which is a bigger font) CSize CGridCellBase::GetTextExtent(LPCTSTR szText, CDC* pDC /*= NULL*/) { CGridCtrl* pGrid = GetGrid(); ASSERT(pGrid); BOOL bReleaseDC = FALSE; if (pDC == NULL || szText == NULL) { if (szText) pDC = pGrid->GetDC(); if (pDC == NULL || szText == NULL) { CGridDefaultCell* pDefCell = (CGridDefaultCell*) GetDefaultCell(); ASSERT(pDefCell); return CSize(pDefCell->GetWidth(), pDefCell->GetHeight()); } bReleaseDC = TRUE; } CFont *pOldFont = NULL, *pFont = GetFontObject(); if (pFont) pOldFont = pDC->SelectObject(pFont); CSize size; int nFormat = GetFormat(); // If the cell is a multiline cell, then use the width of the cell // to get the height if ((nFormat & DT_WORDBREAK) && !(nFormat & DT_SINGLELINE)) { CString str = szText; int nMaxWidth = 0; while (TRUE) { int nPos = str.Find(_T('\n')); CString TempStr = (nPos < 0)? str : str.Left(nPos); int nTempWidth = pDC->GetTextExtent(TempStr).cx; if (nTempWidth > nMaxWidth) nMaxWidth = nTempWidth; if (nPos < 0) break; str = str.Mid(nPos + 1); // Bug fix by Thomas Steinborn } CRect rect; rect.SetRect(0,0, nMaxWidth+1, 0); pDC->DrawText(szText, -1, rect, nFormat | DT_CALCRECT); size = rect.Size(); } else size = pDC->GetTextExtent(szText, _tcslen(szText)); // Removed by Yogurt //TEXTMETRIC tm; //pDC->GetTextMetrics(&tm); //size.cx += (tm.tmOverhang); if (pOldFont) pDC->SelectObject(pOldFont); size += CSize(2*GetMargin(), 2*GetMargin()); // Kludge for vertical text LOGFONT *pLF = GetFont(); if (pLF->lfEscapement == 900 || pLF->lfEscapement == -900) { int nTemp = size.cx; size.cx = size.cy; size.cy = nTemp; size += CSize(0, 4*GetMargin()); } if (bReleaseDC) pGrid->ReleaseDC(pDC); return size; } CSize CGridCellBase::GetCellExtent(CDC* pDC) { CSize size = GetTextExtent(GetText(), pDC); CSize ImageSize(0,0); int nImage = GetImage(); if (nImage >= 0) { CGridCtrl* pGrid = GetGrid(); ASSERT(pGrid); IMAGEINFO Info; if (pGrid->GetImageList() && pGrid->GetImageList()->GetImageInfo(nImage, &Info)) { ImageSize = CSize(Info.rcImage.right-Info.rcImage.left, Info.rcImage.bottom-Info.rcImage.top); if (size.cx > 2*(int)GetMargin ()) ImageSize.cx += GetMargin(); ImageSize.cy += 2*(int)GetMargin (); } } size.cx += ImageSize.cx + 1; size.cy = max(size.cy, ImageSize.cy) + 1; if (IsFixed()) { size.cx++; size.cy++; } return size; } // EFW - Added to print cells so that grids that use different colors are // printed correctly. BOOL CGridCellBase::PrintCell(CDC* pDC, int /*nRow*/, int /*nCol*/, CRect rect) { #if defined(_WIN32_WCE_NO_PRINTING) || defined(GRIDCONTROL_NO_PRINTING) return FALSE; #else COLORREF crFG, crBG; GV_ITEM Item; CGridCtrl* pGrid = GetGrid(); if (!pGrid || !pDC) return FALSE; if( rect.Width() <= 0 || rect.Height() <= 0) // prevents imagelist item from drawing even return FALSE; // though cell is hidden int nSavedDC = pDC->SaveDC(); pDC->SetBkMode(TRANSPARENT); if (pGrid->GetShadedPrintOut()) { // Get the default cell implementation for this kind of cell. We use it if this cell // has anything marked as "default" CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell(); if (!pDefaultCell) return FALSE; // Use custom color if it doesn't match the default color and the // default grid background color. If not, leave it alone. if(IsFixed()) crBG = (GetBackClr() != CLR_DEFAULT) ? GetBackClr() : pDefaultCell->GetBackClr(); else crBG = (GetBackClr() != CLR_DEFAULT && GetBackClr() != pDefaultCell->GetBackClr()) ? GetBackClr() : CLR_DEFAULT; // Use custom color if the background is different or if it doesn't // match the default color and the default grid text color. if(IsFixed()) crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr(); else crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr(); // If not printing on a color printer, adjust the foreground color // to a gray scale if the background color isn't used so that all // colors will be visible. If not, some colors turn to solid black // or white when printed and may not show up. This may be caused by // coarse dithering by the printer driver too (see image note below). if(pDC->GetDeviceCaps(NUMCOLORS) == 2 && crBG == CLR_DEFAULT) crFG = RGB(GetRValue(crFG) * 0.30, GetGValue(crFG) * 0.59, GetBValue(crFG) * 0.11); // Only erase the background if the color is not the default // grid background color. if(crBG != CLR_DEFAULT) { CBrush brush(crBG); rect.right++; rect.bottom++; pDC->FillRect(rect, &brush); rect.right--; rect.bottom--; } } else { crBG = CLR_DEFAULT; crFG = RGB(0, 0, 0); } pDC->SetTextColor(crFG); CFont *pFont = GetFontObject(); if (pFont) pDC->SelectObject(pFont); /* // *************************************************** // Disabled - if you need this functionality then you'll need to rewrite. // Create the appropriate font and select into DC. CFont Font; // Bold the fixed cells if not shading the print out. Use italic // font it it is enabled. const LOGFONT* plfFont = GetFont(); if(IsFixed() && !pGrid->GetShadedPrintOut()) { Font.CreateFont(plfFont->lfHeight, 0, 0, 0, FW_BOLD, plfFont->lfItalic, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, #ifndef _WIN32_WCE PROOF_QUALITY, #else DEFAULT_QUALITY, #endif VARIABLE_PITCH | FF_SWISS, plfFont->lfFaceName); } else Font.CreateFontIndirect(plfFont); pDC->SelectObject(&Font); // *************************************************** */ // Draw lines only when wanted on fixed cells. Normal cell grid lines // are handled in OnPrint. if(pGrid->GetGridLines() != GVL_NONE && IsFixed()) { CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)), darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)), *pOldPen = pDC->GetCurrentPen(); pDC->SelectObject(&lightpen); pDC->MoveTo(rect.right, rect.top); pDC->LineTo(rect.left, rect.top); pDC->LineTo(rect.left, rect.bottom); pDC->SelectObject(&darkpen); pDC->MoveTo(rect.right, rect.top); pDC->LineTo(rect.right, rect.bottom); pDC->LineTo(rect.left, rect.bottom); rect.DeflateRect(1,1); pDC->SelectObject(pOldPen); } rect.DeflateRect(GetMargin(), 0); if(pGrid->GetImageList() && GetImage() >= 0) { // NOTE: If your printed images look like fuzzy garbage, check the // settings on your printer driver. If it's using coarse // dithering and/or vector graphics, they may print wrong. // Changing to fine dithering and raster graphics makes them // print properly. My HP 4L had that problem. IMAGEINFO Info; if(pGrid->GetImageList()->GetImageInfo(GetImage(), &Info)) { int nImageWidth = Info.rcImage.right-Info.rcImage.left; pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL); rect.left += nImageWidth+GetMargin(); } } // Draw without clipping so as not to lose text when printed for real // DT_NOCLIP removed 01.01.01. Slower, but who cares - we are printing! DrawText(pDC->m_hDC, GetText(), -1, rect, GetFormat() | /*DT_NOCLIP | */ DT_NOPREFIX); pDC->RestoreDC(nSavedDC); return TRUE; #endif } /***************************************************************************** Callable by derived classes, only *****************************************************************************/ LRESULT CGridCellBase::SendMessageToParent(int nRow, int nCol, int nMessage) { CGridCtrl* pGrid = GetGrid(); if( pGrid) return pGrid->SendMessageToParent(nRow, nCol, nMessage); else return 0; } --- NEW FILE: GridCellCheck.h --- #if !defined(AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_) #define AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 ///////////////////////////////////////////////////////////////////////////// // GridCellCheck.h : header file // // MFC Grid Control - Grid combo cell class header file // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.22+ // ////////////////////////////////////////////////////////////////////// #include "GridCell.h" class CGridCellCheck : public CGridCell { friend class CGridCtrl; DECLARE_DYNCREATE(CGridCellCheck) public: CGridCellCheck(); public: BOOL SetCheck(BOOL bChecked = TRUE); BOOL GetCheck(); // Operations virtual CSize GetCellExtent(CDC* pDC); virtual void OnClick( CPoint PointCellRelative); virtual BOOL GetTextRect( LPRECT pRect); protected: CRect GetCheckPlacement(); virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE); protected: BOOL m_bChecked; CRect m_Rect; }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_) --- NEW FILE: GridCellURL.cpp --- // GridCellURL.cpp: implementation of the CGridCellURL class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GridCellURL.h" #include "GridCtrl.h" IMPLEMENT_DYNCREATE(CGridCellURL, CGridCell) #ifndef _WIN32_WCE HCURSOR CGridCellURL::g_hLinkCursor = NULL; #endif // Possible prefixes that indicate a hyperlink URLStruct CGridCellURL::g_szURIprefixes[] = { { _T("www."), _tcslen(_T("www.")) }, { _T("http:"), _tcslen(_T("http:")) }, { _T("mailto:"), _tcslen(_T("mailto:")) }, { _T("ftp:"), _tcslen(_T("ftp:")) }, { _T("https:"), _tcslen(_T("https:")) }, { _T("news:"), _tcslen(_T("news:")) }, { _T("gopher:"), _tcslen(_T("gopher:")) }, { _T("telnet:"), _tcslen(_T("telnet:")) }, { _T("url:"), _tcslen(_T("url:")) }, { _T("file:"), _tcslen(_T("file:")) }, { _T("ftp."), _tcslen(_T("ftp.")) } }; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CGridCellURL::CGridCellURL() { #ifndef _WIN32_WCE g_hLinkCursor = GetHandCursor(); #endif m_bLaunchUrl = TRUE; m_clrUrl = GetSysColor(COLOR_HIGHLIGHT); m_clrOld = CLR_NONE; } CGridCellURL::~CGridCellURL() { } BOOL CGridCellURL::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd) { // If url is present then change text color if (HasUrl(GetText())) { if (m_clrOld == CLR_NONE) { LOGFONT lf; GetFontObject()->GetLogFont(&lf); lf.lfUnderline = TRUE; SetFont(&lf); m_clrOld = GetTextClr(); SetTextClr(m_clrUrl); } } else if (m_clrOld != CLR_NONE) { LOGFONT lf; GetFontObject()->GetLogFont(&lf); lf.lfUnderline = FALSE; SetFont(&lf); SetTextClr(m_clrOld); m_clrOld = CLR_NONE; } // Good a place as any to store the bounds of the rect m_Rect = rect; return CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd); } void CGridCellURL::OnClick(CPoint PointCellRelative) { #ifndef _WIN32_WCE CString strURL; if (GetAutoLaunchUrl() && OverURL(PointCellRelative, strURL)) ShellExecute(NULL, _T("open"), strURL, NULL,NULL, SW_SHOW); #endif } // Return TRUE if you set the cursor BOOL CGridCellURL::OnSetCursor() { #ifndef _WIN32_WCE CString strURL; CPoint pt(GetMessagePos()); GetGrid()->ScreenToClient(&pt); pt = pt - m_Rect.TopLeft(); if (!m_bEditing && OverURL(pt, strURL)) { SetCursor(g_hLinkCursor); return TRUE; } else #endif return CGridCell::OnSetCursor(); } #ifndef _WIN32_WCE HCURSOR CGridCellURL::GetHandCursor() { if (g_hLinkCursor == NULL) // No cursor handle - load our own { // Get the windows directory CString strWndDir; GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH); strWndDir.ReleaseBuffer(); strWndDir += _T("\\winhlp32.exe"); // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer HMODULE hModule = LoadLibrary(strWndDir); if( hModule ) { HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106)); if( hHandCursor ) { g_hLinkCursor = CopyCursor(hHandCursor); } } FreeLibrary(hModule); } return g_hLinkCursor; } #endif //////////////////////////////////////////////////////////////////////////////////////////// // Helper functions BOOL CGridCellURL::HasUrl(CString str) { int nNumPrefixes = sizeof(g_szURIprefixes) / sizeof(g_szURIprefixes[0]); for (int i = 0; i < nNumPrefixes; i++) //if (str.Left(g_szURIprefixes[i].nLength) == g_szURIprefixes[i].szURLPrefix) if (str.Find(g_szURIprefixes[i].szURLPrefix) >= 0) return TRUE; return FALSE; } // here we figure out if we are over a URL or not BOOL CGridCellURL::OverURL(CPoint& pt, CString& strURL) { //TRACE2("Checking point %d,%d\n",pt.x,pt.y); BOOL bOverURL = FALSE; CSize size = GetTextExtent(GetText()); // Add left of cell so we know if we clicked on text or not pt.x += m_Rect.left; CPoint center = m_Rect.CenterPoint(); if ((m_nFormat & DT_RIGHT) && pt.x >= (m_Rect.right - size.cx)) { bOverURL = TRUE; } else if ((m_nFormat & DT_CENTER) && ((center.x - (size.cx/2)) <= pt.x) && (pt.x <= (center.x + (size.cx/2))) ) { bOverURL = TRUE; } else if (pt.x <= (size.cx + m_Rect.left)) { bOverURL = TRUE; } if (!bOverURL) return FALSE; // We are over text - but are we over a URL? bOverURL = FALSE; strURL = GetText(); // Use float, otherwise we get an incorrect letter from the point float width = (float)size.cx/(float)strURL.GetLength(); // remove left of cell so we have original point again pt.x -= m_Rect.left; if (m_nFormat & DT_RIGHT) { int wide = m_Rect.Width() - size.cx; pt.x -= wide; if (pt.x <= 0) return FALSE; } if (m_nFormat & DT_CENTER) { int wide = m_Rect.Width() - size.cx; pt.x -= (wide/2); if (pt.x <= 0 || pt.x > (size.cx + (wide/2))) return FALSE; } // Turn point into a letter int ltrs = (int)((float)pt.x/width); #if !defined(_WIN32_WCE) || (_WIN32_WCE > 210) // Find spaces before and after letter, process text between int endSpace = strURL.Find(_T(' '), ltrs); if (endSpace != -1) strURL.Delete(endSpace, strURL.GetLength()-endSpace); int beginSpace = strURL.ReverseFind(_T(' ')); if (beginSpace != -1) strURL.Delete(0, ++beginSpace); #endif // Does text have url return HasUrl(strURL); } --- NEW FILE: GridCellNumeric.cpp --- // GridCellNumeric.cpp: implementation of the CGridCellNumeric class. // // Written by Andrew Truckle [EMAIL PROTECTED] // ////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "GridCellNumeric.h" #include "InPlaceEdit.h" #include "GridCtrl.h" IMPLEMENT_DYNCREATE(CGridCellNumeric, CGridCell) #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// // Create a control to do the editing BOOL CGridCellNumeric::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar) { m_bEditing = TRUE; // CInPlaceEdit auto-deletes itself m_pEditWnd = new CInPlaceEdit(GetGrid(), rect, /*GetStyle() |*/ ES_NUMBER, nID, nRow, nCol, GetText(), nChar); return TRUE; } // Cancel the editing. void CGridCellNumeric::EndEdit() { if (m_pEditWnd) ((CInPlaceEdit*)m_pEditWnd)->EndEdit(); } --- NEW FILE: GridCtrl.cpp --- // GridCtrl.cpp : implementation file // // MFC Grid Control v2.25 // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // The code contained in this file was based on the original // WorldCom Grid control written by Joe Willcoxson, // mailto:[EMAIL PROTECTED] // http://users.aol.com/chinajoe // (These addresses may be out of date) The code has gone through // so many modifications that I'm not sure if there is even a single // original line of code. In any case Joe's code was a great // framework on which to build. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and [...7269 lines suppressed...] ASSERT(pCell); if (!pCell) return TRUE; return pCell->ValidateEdit(str); } // virtual CString CGridCtrl::GetItemText(int nRow, int nCol) const { if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols) return _T(""); CGridCellBase* pCell = GetCell(nRow, nCol); ASSERT(pCell); if (!pCell) return _T(""); return pCell->GetText(); } --- NEW FILE: InPlaceEdit.cpp --- // InPlaceEdit.cpp : implementation file // // Adapted by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // The code contained in this file is based on the original // CInPlaceEdit from http://www.codeguru.com/listview/edit_subitems.shtml // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.10+ // // History: // 10 May 1998 Uses GVN_ notifications instead of LVN_, // Sends notification messages to the parent, // instead of the parent's parent. // 15 May 1998 There was a problem when editing with the in-place editor, // there arises a general protection fault in user.exe, with a // few qualifications: // (1) This only happens with owner-drawn buttons; // (2) This only happens in Win95 // (3) This only happens if the handler for the button does not // create a new window (even an AfxMessageBox will avoid the // crash) // (4) This will not happen if Spy++ is running. // PreTranslateMessage was added to route messages correctly. // (Matt Weagle found and fixed this problem) // 26 Jul 1998 Removed the ES_MULTILINE style - that fixed a few probs! // 6 Aug 1998 Added nID to the constructor param list // 6 Sep 1998 Space no longer clears selection when starting edit (Franco Bez) // 10 Apr 1999 Enter, Tab and Esc key prob fixed (Koay Kah Hoe) // Workaround for bizzare "shrinking window" problem in CE // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "TCHAR.h" #include "InPlaceEdit.h" #include "GridCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CInPlaceEdit CInPlaceEdit::CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, int nRow, int nColumn, CString sInitText, UINT nFirstChar) { m_sInitText = sInitText; m_nRow = nRow; m_nColumn = nColumn; m_nLastChar = 0; m_bExitOnArrows = (nFirstChar != VK_LBUTTON); // If mouse click brought us here, // then no exit on arrows m_Rect = rect; // For bizarre CE bug. DWORD dwEditStyle = WS_BORDER|WS_CHILD|WS_VISIBLE| ES_AUTOHSCROLL //|ES_MULTILINE | dwStyle; if (!Create(dwEditStyle, rect, pParent, nID)) return; SetFont(pParent->GetFont()); SetWindowText(sInitText); SetFocus(); switch (nFirstChar){ case VK_LBUTTON: case VK_RETURN: SetSel((int)_tcslen(m_sInitText), -1); return; case VK_BACK: SetSel((int)_tcslen(m_sInitText), -1); break; case VK_TAB: case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT: case VK_NEXT: case VK_PRIOR: case VK_HOME: case VK_SPACE: case VK_END: SetSel(0,-1); return; default: SetSel(0,-1); } // Added by KiteFly. When entering DBCS chars into cells the first char was being lost // SenMessage changed to PostMessage (John Lagerquist) if( nFirstChar < 0x80) PostMessage(WM_CHAR, nFirstChar); else PostMessage(WM_IME_CHAR, nFirstChar); } CInPlaceEdit::~CInPlaceEdit() { } BEGIN_MESSAGE_MAP(CInPlaceEdit, CEdit) //{{AFX_MSG_MAP(CInPlaceEdit) ON_WM_KILLFOCUS() ON_WM_CHAR() ON_WM_KEYDOWN() ON_WM_GETDLGCODE() ON_WM_CREATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() //////////////////////////////////////////////////////////////////////////// // CInPlaceEdit message handlers // If an arrow key (or associated) is pressed, then exit if // a) The Ctrl key was down, or // b) m_bExitOnArrows == TRUE void CInPlaceEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if ((nChar == VK_PRIOR || nChar == VK_NEXT || nChar == VK_DOWN || nChar == VK_UP || nChar == VK_RIGHT || nChar == VK_LEFT) && (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0)) { m_nLastChar = nChar; GetParent()->SetFocus(); return; } CEdit::OnKeyDown(nChar, nRepCnt, nFlags); } // As soon as this edit loses focus, kill it. void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd) { CEdit::OnKillFocus(pNewWnd); EndEdit(); } void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar == VK_TAB || nChar == VK_RETURN) { m_nLastChar = nChar; GetParent()->SetFocus(); // This will destroy this window return; } if (nChar == VK_ESCAPE) { SetWindowText(m_sInitText); // restore previous text m_nLastChar = nChar; GetParent()->SetFocus(); return; } CEdit::OnChar(nChar, nRepCnt, nFlags); // Resize edit control if needed // Get text extent CString str; GetWindowText( str ); // add some extra buffer str += _T(" "); CWindowDC dc(this); CFont *pFontDC = dc.SelectObject(GetFont()); CSize size = dc.GetTextExtent( str ); dc.SelectObject( pFontDC ); // Get client rect CRect ParentRect; GetParent()->GetClientRect( &ParentRect ); // Check whether control needs to be resized // and whether there is space to grow if (size.cx > m_Rect.Width()) { if( size.cx + m_Rect.left < ParentRect.right ) m_Rect.right = m_Rect.left + size.cx; else m_Rect.right = ParentRect.right; MoveWindow( &m_Rect ); } } UINT CInPlaceEdit::OnGetDlgCode() { return DLGC_WANTALLKEYS; } //////////////////////////////////////////////////////////////////////////// // CInPlaceEdit overrides // Stoopid win95 accelerator key problem workaround - Matt Weagle. BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg) { // Catch the Alt key so we don't choke if focus is going to an owner drawn button if (pMsg->message == WM_SYSCHAR) return TRUE; return CWnd::PreTranslateMessage(pMsg); } // Auto delete void CInPlaceEdit::PostNcDestroy() { CEdit::PostNcDestroy(); delete this; } //////////////////////////////////////////////////////////////////////////// // CInPlaceEdit implementation void CInPlaceEdit::EndEdit() { CString str; // EFW - BUG FIX - Clicking on a grid scroll bar in a derived class // that validates input can cause this to get called multiple times // causing assertions because the edit control goes away the first time. static BOOL bAlreadyEnding = FALSE; if(bAlreadyEnding) return; bAlreadyEnding = TRUE; GetWindowText(str); // Send Notification to parent GV_DISPINFO dispinfo; dispinfo.hdr.hwndFrom = GetSafeHwnd(); dispinfo.hdr.idFrom = GetDlgCtrlID(); dispinfo.hdr.code = GVN_ENDLABELEDIT; dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM; dispinfo.item.row = m_nRow; dispinfo.item.col = m_nColumn; dispinfo.item.strText = str; dispinfo.item.lParam = (LPARAM) m_nLastChar; CWnd* pOwner = GetOwner(); if (pOwner) pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo ); // Close this window (PostNcDestroy will delete this) if (IsWindow(GetSafeHwnd())) SendMessage(WM_CLOSE, 0, 0); bAlreadyEnding = FALSE; } --- NEW FILE: GridDropTarget.h --- ////////////////////////////////////////////////////////////////////// // GridDropTarget.h : header file // // MFC Grid Control - Drag/Drop target implementation // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.10+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_) #define AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include <afxole.h> class CGridCtrl; ///////////////////////////////////////////////////////////////////////////// // CGridDropTarget command target class CGridDropTarget : public COleDropTarget { public: CGridDropTarget(); virtual ~CGridDropTarget(); // Attributes public: CGridCtrl* m_pGridCtrl; BOOL m_bRegistered; // Operations public: BOOL Register(CGridCtrl *pGridCtrl); virtual void Revoke(); BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); void OnDragLeave(CWnd* pWnd); DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); DROPEFFECT OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CGridDropTarget) //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CGridDropTarget) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_) --- NEW FILE: GridCellBase.h --- ///////////////////////////////////////////////////////////////////////////// // GridCellBase.h : header file // // MFC Grid Control - Grid cell base class header file // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.22+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) #define AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 class CGridCtrl; // Cell states #define GVIS_FOCUSED 0x0001 #define GVIS_SELECTED 0x0002 #define GVIS_DROPHILITED 0x0004 #define GVIS_READONLY 0x0008 #define GVIS_FIXED 0x0010 #define GVIS_FIXEDROW 0x0020 #define GVIS_FIXEDCOL 0x0040 #define GVIS_MODIFIED 0x0080 // Cell data mask #define GVIF_TEXT LVIF_TEXT #define GVIF_IMAGE LVIF_IMAGE #define GVIF_PARAM LVIF_PARAM #define GVIF_STATE LVIF_STATE #define GVIF_BKCLR (GVIF_STATE<<1) #define GVIF_FGCLR (GVIF_STATE<<2) #define GVIF_FORMAT (GVIF_STATE<<3) #define GVIF_FONT (GVIF_STATE<<4) #define GVIF_MARGIN (GVIF_STATE<<5) #define GVIF_ALL (GVIF_TEXT|GVIF_IMAGE|GVIF_PARAM|GVIF_STATE|GVIF_BKCLR|GVIF_FGCLR| \ GVIF_FORMAT|GVIF_FONT|GVIF_MARGIN) // Used for Get/SetItem calls. typedef struct _GV_ITEM { int row,col; // Row and Column of item UINT mask; // Mask for use in getting/setting cell data UINT nState; // cell state (focus/hilighted etc) DWORD nFormat; // Format of cell int iImage; // index of the list view items icon COLORREF crBkClr; // Background colour (or CLR_DEFAULT) COLORREF crFgClr; // Forground colour (or CLR_DEFAULT) LPARAM lParam; // 32-bit value to associate with item LOGFONT lfFont; // Cell font UINT nMargin; // Internal cell margin CString strText; // Text in cell } GV_ITEM; // Each cell contains one of these. Fields "row" and "column" are not stored since we // will usually have acces to them in other ways, and they are an extra 8 bytes per // cell that is probably unnecessary. class CGridCellBase : public CObject { friend class CGridCtrl; DECLARE_DYNAMIC(CGridCellBase) // Construction/Destruction public: CGridCellBase(); virtual ~CGridCellBase(); // Attributes public: virtual void SetText(LPCTSTR /* szText */) = 0 ; virtual void SetImage(int /* nImage */) = 0 ; virtual void SetData(LPARAM /* lParam */) = 0 ; virtual void SetState(DWORD nState) { m_nState = nState; } virtual void SetFormat(DWORD /* nFormat */) = 0 ; virtual void SetTextClr(COLORREF /* clr */) = 0 ; virtual void SetBackClr(COLORREF /* clr */) = 0 ; virtual void SetFont(const LOGFONT* /* plf */) = 0 ; virtual void SetMargin( UINT /* nMargin */) = 0 ; virtual void SetGrid(CGridCtrl* /* pGrid */) = 0 ; virtual void SetCoords( int /* nRow */, int /* nCol */) = 0 ; virtual LPCTSTR GetText() const = 0 ; virtual LPCTSTR GetTipText() const { return GetText(); } // may override TitleTip return virtual int GetImage() const = 0 ; virtual LPARAM GetData() const = 0 ; virtual DWORD GetState() const { return m_nState; } virtual DWORD GetFormat() const = 0 ; virtual COLORREF GetTextClr() const = 0 ; virtual COLORREF GetBackClr() const = 0 ; virtual LOGFONT * GetFont() const = 0 ; virtual CFont * GetFontObject() const = 0 ; virtual CGridCtrl* GetGrid() const = 0 ; virtual CWnd * GetEditWnd() const = 0 ; virtual UINT GetMargin() const = 0 ; virtual CGridCellBase* GetDefaultCell() const; virtual BOOL IsDefaultFont() const = 0 ; virtual BOOL IsEditing() const = 0 ; virtual BOOL IsFocused() const { return (m_nState & GVIS_FOCUSED); } virtual BOOL IsFixed() const { return (m_nState & GVIS_FIXED); } virtual BOOL IsFixedCol() const { return (m_nState & GVIS_FIXEDCOL); } virtual BOOL IsFixedRow() const { return (m_nState & GVIS_FIXEDROW); } virtual BOOL IsSelected() const { return (m_nState & GVIS_SELECTED); } virtual BOOL IsReadOnly() const { return (m_nState & GVIS_READONLY); } virtual BOOL IsModified() const { return (m_nState & GVIS_MODIFIED); } virtual BOOL IsDropHighlighted() const { return (m_nState & GVIS_DROPHILITED); } // Operators public: virtual void operator=(const CGridCellBase& cell); // Operations public: virtual void Reset(); virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE); virtual BOOL GetTextRect( LPRECT pRect); // i/o: i=dims of cell rect; o=dims of text rect virtual BOOL GetTipTextRect( LPRECT pRect) { return GetTextRect( pRect); } // may override for btns, etc. virtual CSize GetTextExtent(LPCTSTR str, CDC* pDC = NULL); virtual CSize GetCellExtent(CDC* pDC); // Editing virtual BOOL Edit( int /* nRow */, int /* nCol */, CRect /* rect */, CPoint /* point */, UINT /* nID */, UINT /* nChar */) { ASSERT( FALSE); return FALSE;} virtual BOOL ValidateEdit(LPCTSTR str); virtual void EndEdit() {} // EFW - Added to print cells properly virtual BOOL PrintCell(CDC* pDC, int nRow, int nCol, CRect rect); // add additional protected grid members required of cells LRESULT SendMessageToParent(int nRow, int nCol, int nMessage); protected: virtual void OnEndEdit(); virtual void OnMouseEnter(); virtual void OnMouseOver(); virtual void OnMouseLeave(); virtual void OnClick( CPoint PointCellRelative); virtual void OnClickDown( CPoint PointCellRelative); virtual void OnRClick( CPoint PointCellRelative); virtual void OnDblClick( CPoint PointCellRelative); virtual BOOL OnSetCursor(); protected: DWORD m_nState; // Cell state (selected/focus etc) }; //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) --- NEW FILE: StdAfx.h --- // stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #if !defined(AFX_STDAFX_H__19E18FB7_DFF6_11D1_8CE7_000000000000__INCLUDED_) #define AFX_STDAFX_H__19E18FB7_DFF6_11D1_8CE7_000000000000__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #include <afxwin.h> // MFC core and standard components #include <afxext.h> // MFC extensions #include <afxdisp.h> // MFC OLE automation classes #ifndef _AFX_NO_AFXCMN_SUPPORT #include <afxcmn.h> // MFC support for Windows Common Controls #endif // _AFX_NO_AFXCMN_SUPPORT //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__19E18FB7_DFF6_11D1_8CE7_000000000000__INCLUDED_) --- NEW FILE: StdAfx.cpp --- // stdafx.cpp : source file that includes just the standard includes // GridViewDemo.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" --- NEW FILE: TitleTip.h --- ///////////////////////////////////////////////////////////////////////////// // Titletip.h : header file // // MFC Grid Control - cell titletips // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2001. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.10+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_) #define AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #define TITLETIP_CLASSNAME _T("ZTitleTip") ///////////////////////////////////////////////////////////////////////////// // CTitleTip window class CTitleTip : public CWnd { // Construction public: CTitleTip(); virtual ~CTitleTip(); virtual BOOL Create( CWnd *pParentWnd); // Attributes public: void SetParentWnd(CWnd* pParentWnd) { m_pParentWnd = pParentWnd; } CWnd* GetParentWnd() { return m_pParentWnd; } // Operations public: void Show(CRect rectTitle, LPCTSTR lpszTitleText, int xoffset = 0, LPRECT lpHoverRect = NULL, const LOGFONT* lpLogFont = NULL, COLORREF crTextClr = CLR_DEFAULT, COLORREF crBackClr = CLR_DEFAULT); void Hide(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CTitleTip) public: virtual BOOL PreTranslateMessage(MSG* pMsg); virtual BOOL DestroyWindow(); //}}AFX_VIRTUAL // Implementation protected: CWnd *m_pParentWnd; CRect m_rectTitle; CRect m_rectHover; DWORD m_dwLastLButtonDown; DWORD m_dwDblClickMsecs; BOOL m_bCreated; // Generated message map functions protected: //{{AFX_MSG(CTitleTip) afx_msg void OnMouseMove(UINT nFlags, CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_) --- NEW FILE: GridDropTarget.cpp --- // GridDropTarget.cpp : implementation file // // MFC Grid Control - Drag/Drop target implementation // // CGridDropTarget is an OLE drop target for CGridCtrl. All it does // is handle the drag and drop windows messages and pass them // directly onto the grid control. // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.10+ // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GridCtrl.h" #ifndef GRIDCONTROL_NO_DRAGDROP #include "GridDropTarget.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CGridDropTarget CGridDropTarget::CGridDropTarget() { m_pGridCtrl = NULL; m_bRegistered = FALSE; } CGridDropTarget::~CGridDropTarget() { } // Overloaded Register() function performs the normal COleDropTarget::Register // but also serves to connect this COleDropTarget with the parent grid control, // where all drop messages will ultimately be forwarded. BOOL CGridDropTarget::Register(CGridCtrl *pGridCtrl) { if (m_bRegistered) return FALSE; // Stop re-entry problems static BOOL bInProcedure = FALSE; if (bInProcedure) return FALSE; bInProcedure = TRUE; ASSERT(pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl))); ASSERT(pGridCtrl); if (!pGridCtrl || !pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl))) { bInProcedure = FALSE; return FALSE; } m_pGridCtrl = pGridCtrl; m_bRegistered = COleDropTarget::Register(pGridCtrl); bInProcedure = FALSE; return m_bRegistered; } void CGridDropTarget::Revoke() { m_bRegistered = FALSE; COleDropTarget::Revoke(); } BEGIN_MESSAGE_MAP(CGridDropTarget, COleDropTarget) //{{AFX_MSG_MAP(CGridDropTarget) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CGridDropTarget message handlers DROPEFFECT CGridDropTarget::OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint /*point*/) { // TRACE("In CGridDropTarget::OnDragScroll\n"); if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) { if (dwKeyState & MK_CONTROL) return DROPEFFECT_COPY; else return DROPEFFECT_MOVE; } else return DROPEFFECT_NONE; } DROPEFFECT CGridDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { TRACE(_T("In CGridDropTarget::OnDragEnter\n")); ASSERT(m_pGridCtrl); if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) return m_pGridCtrl->OnDragEnter(pDataObject, dwKeyState, point); else return DROPEFFECT_NONE; } void CGridDropTarget::OnDragLeave(CWnd* pWnd) { TRACE(_T("In CGridDropTarget::OnDragLeave\n")); ASSERT(m_pGridCtrl); if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) m_pGridCtrl->OnDragLeave(); } DROPEFFECT CGridDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { // TRACE("In CGridDropTarget::OnDragOver\n"); ASSERT(m_pGridCtrl); if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) return m_pGridCtrl->OnDragOver(pDataObject, dwKeyState, point); else return DROPEFFECT_NONE; } BOOL CGridDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) { TRACE(_T("In CGridDropTarget::OnDrop\n")); ASSERT(m_pGridCtrl); if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd()) return m_pGridCtrl->OnDrop(pDataObject, dropEffect, point); else return FALSE; } #endif // GRIDCONTROL_NO_DRAGDROP --- NEW FILE: GridCtrl.h --- ///////////////////////////////////////////////////////////////////////////// // GridCtrl.h : header file // // MFC Grid Control - main header // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2004. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.20+ // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) #define AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #include "CellRange.h" #include "GridCell.h" #include <afxtempl.h> /////////////////////////////////////////////////////////////////////////////////// // Defines - these determine the features (and the final size) of the final code /////////////////////////////////////////////////////////////////////////////////// //#define GRIDCONTROL_NO_TITLETIPS // Do not use titletips for cells with large data //#define GRIDCONTROL_NO_DRAGDROP // Do not use OLE drag and drop //#define GRIDCONTROL_NO_CLIPBOARD // Do not use clipboard routines #ifdef _WIN32_WCE # define GRIDCONTROL_NO_TITLETIPS // Do not use titletips for cells with large data # define GRIDCONTROL_NO_DRAGDROP // Do not use OLE drag and drop # define GRIDCONTROL_NO_CLIPBOARD // Do not use clipboard routines # define GRIDCONTROL_NO_PRINTING // Do not use printing routines # ifdef WCE_NO_PRINTING // Older versions of CE had different #def's # define _WIN32_WCE_NO_PRINTING # endif # ifdef WCE_NO_CURSOR # define _WIN32_WCE_NO_CURSOR # endif #endif // _WIN32_WCE // Use this as the classname when inserting this control as a custom control // in the MSVC++ dialog editor #define GRIDCTRL_CLASSNAME _T("MFCGridCtrl") // Window class name #define IDC_INPLACE_CONTROL 8 // ID of inplace edit controls /////////////////////////////////////////////////////////////////////////////////// // Conditional includes /////////////////////////////////////////////////////////////////////////////////// #ifndef GRIDCONTROL_NO_TITLETIPS # include "TitleTip.h" #endif #ifndef GRIDCONTROL_NO_DRAGDROP # include "GridDropTarget.h" # undef GRIDCONTROL_NO_CLIPBOARD // Force clipboard functions on #endif #ifndef GRIDCONTROL_NO_CLIPBOARD # include <afxole.h> #endif /////////////////////////////////////////////////////////////////////////////////// // Helper functions /////////////////////////////////////////////////////////////////////////////////// // Handy functions #define IsSHIFTpressed() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0 ) #define IsCTRLpressed() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 ) // Backwards compatibility for pre 2.20 grid versions #define DDX_GridControl(pDX, nIDC, rControl) DDX_Control(pDX, nIDC, rControl) /////////////////////////////////////////////////////////////////////////////////// // Structures /////////////////////////////////////////////////////////////////////////////////// // This structure sent to Grid's parent in a WM_NOTIFY message typedef struct tagNM_GRIDVIEW { NMHDR hdr; int iRow; int iColumn; } NM_GRIDVIEW; // This is sent to the Grid from child in-place edit controls typedef struct tagGV_DISPINFO { NMHDR hdr; GV_ITEM item; } GV_DISPINFO; // This is sent to the Grid from child in-place edit controls typedef struct tagGV_CACHEHINT { NMHDR hdr; CCellRange range; } GV_CACHEHINT; // storage typedef for each row in the grid typedef CTypedPtrArray<CObArray, CGridCellBase*> GRID_ROW; // For virtual mode callback typedef BOOL (CALLBACK* GRIDCALLBACK)(GV_DISPINFO *, LPARAM); /////////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////////// // Grid line/scrollbar selection #define GVL_NONE 0L // Neither #define GVL_HORZ 1L // Horizontal line or scrollbar #define GVL_VERT 2L // Vertical line or scrollbar #define GVL_BOTH 3L // Both // Autosizing option #define GVS_DEFAULT 0 #define GVS_HEADER 1 // Size using column fixed cells data only #define GVS_DATA 2 // Size using column non-fixed cells data only #define GVS_BOTH 3 // Size using column fixed and non-fixed // Cell Searching options #define GVNI_FOCUSED 0x0001 #define GVNI_SELECTED 0x0002 #define GVNI_DROPHILITED 0x0004 #define GVNI_READONLY 0x0008 #define GVNI_FIXED 0x0010 #define GVNI_MODIFIED 0x0020 #define GVNI_ABOVE LVNI_ABOVE #define GVNI_BELOW LVNI_BELOW #define GVNI_TOLEFT LVNI_TOLEFT #define GVNI_TORIGHT LVNI_TORIGHT #define GVNI_ALL (LVNI_BELOW|LVNI_TORIGHT|LVNI_TOLEFT) #define GVNI_AREA (LVNI_BELOW|LVNI_TORIGHT) // Hit test values (not yet implemented) #define GVHT_DATA 0x0000 #define GVHT_TOPLEFT 0x0001 #define GVHT_COLHDR 0x0002 #define GVHT_ROWHDR 0x0004 #define GVHT_COLSIZER 0x0008 #define GVHT_ROWSIZER 0x0010 #define GVHT_LEFT 0x0020 #define GVHT_RIGHT 0x0040 #define GVHT_ABOVE 0x0080 #define GVHT_BELOW 0x0100 // Messages sent to the grid's parent (More will be added in future) #define GVN_BEGINDRAG LVN_BEGINDRAG // LVN_FIRST-9 #define GVN_BEGINLABELEDIT LVN_BEGINLABELEDIT // LVN_FIRST-5 #define GVN_BEGINRDRAG LVN_BEGINRDRAG #define GVN_COLUMNCLICK LVN_COLUMNCLICK #define GVN_DELETEITEM LVN_DELETEITEM #define GVN_ENDLABELEDIT LVN_ENDLABELEDIT // LVN_FIRST-6 #define GVN_SELCHANGING LVN_ITEMCHANGING #define GVN_SELCHANGED LVN_ITEMCHANGED #define GVN_GETDISPINFO LVN_GETDISPINFO #define GVN_ODCACHEHINT LVN_ODCACHEHINT #define GVN_CHANGEDLABELEDIT (LVN_FIRST+1) class CGridCtrl; ///////////////////////////////////////////////////////////////////////////// // CGridCtrl window class CGridCtrl : public CWnd { DECLARE_DYNCREATE(CGridCtrl) friend class CGridCell; friend class CGridCellBase; // Construction public: CGridCtrl(int nRows = 0, int nCols = 0, int nFixedRows = 0, int nFixedCols = 0); BOOL Create(const RECT& rect, CWnd* parent, UINT nID, DWORD dwStyle = WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VISIBLE); /////////////////////////////////////////////////////////////////////////////////// // Attributes /////////////////////////////////////////////////////////////////////////////////// public: int GetRowCount() const { return m_nRows; } int GetColumnCount() const { return m_nCols; } int GetFixedRowCount() const { return m_nFixedRows; } int GetFixedColumnCount() const { return m_nFixedCols; } BOOL SetRowCount(int nRows = 10); BOOL SetColumnCount(int nCols = 10); BOOL SetFixedRowCount(int nFixedRows = 1); BOOL SetFixedColumnCount(int nFixedCols = 1); int GetRowHeight(int nRow) const; BOOL SetRowHeight(int row, int height); int GetColumnWidth(int nCol) const; BOOL SetColumnWidth(int col, int width); BOOL GetCellOrigin(int nRow, int nCol, LPPOINT p); BOOL GetCellOrigin(const CCellID& cell, LPPOINT p); BOOL GetCellRect(int nRow, int nCol, LPRECT pRect); BOOL GetCellRect(const CCellID& cell, LPRECT pRect); BOOL GetTextRect(const CCellID& cell, LPRECT pRect); BOOL GetTextRect(int nRow, int nCol, LPRECT pRect); CCellID GetCellFromPt(CPoint point, BOOL bAllowFixedCellCheck = TRUE); int GetFixedRowHeight() const; int GetFixedColumnWidth() const; long GetVirtualWidth() const; long GetVirtualHeight() const; CSize GetTextExtent(int nRow, int nCol, LPCTSTR str); // EFW - Get extent of current text in cell inline CSize GetCellTextExtent(int nRow, int nCol) { return GetTextExtent(nRow, nCol, GetItemText(nRow,nCol)); } void SetGridBkColor(COLORREF clr) { m_crGridBkColour = clr; } COLORREF GetGridBkColor() const { return m_crGridBkColour; } void SetGridLineColor(COLORREF clr) { m_crGridLineColour = clr; } COLORREF GetGridLineColor() const { return m_crGridLineColour; } void SetTitleTipBackClr(COLORREF clr = CLR_DEFAULT) { m_crTTipBackClr = clr; } COLORREF GetTitleTipBackClr() { return m_crTTipBackClr; } void SetTitleTipTextClr(COLORREF clr = CLR_DEFAULT) { m_crTTipTextClr = clr; } COLORREF GetTitleTipTextClr() { return m_crTTipTextClr; } // ***************************************************************************** // // These have been deprecated. Use GetDefaultCell and then set the colors void SetTextColor(COLORREF clr) { m_cellDefault.SetTextClr(clr); } COLORREF GetTextColor() { return m_cellDefault.GetTextClr(); } void SetTextBkColor(COLORREF clr) { m_cellDefault.SetBackClr(clr); } COLORREF GetTextBkColor() { return m_cellDefault.GetBackClr(); } void SetFixedTextColor(COLORREF clr) { m_cellFixedRowDef.SetTextClr(clr); m_cellFixedColDef.SetTextClr(clr); m_cellFixedRowColDef.SetTextClr(clr); } COLORREF GetFixedTextColor() const { return m_cellFixedRowDef.GetTextClr(); } void SetFixedBkColor(COLORREF clr) { m_cellFixedRowDef.SetBackClr(clr); m_cellFixedColDef.SetBackClr(clr); m_cellFixedRowColDef.SetBackClr(clr); } COLORREF GetFixedBkColor() const { return m_cellFixedRowDef.GetBackClr(); } void SetGridColor(COLORREF clr) { SetGridLineColor(clr); } COLORREF GetGridColor() { return GetGridLineColor(); } void SetBkColor(COLORREF clr) { SetGridBkColor(clr); } COLORREF GetBkColor() { return GetGridBkColor(); } void SetDefCellMargin( int nMargin) { m_cellDefault.SetMargin(nMargin); m_cellFixedRowDef.SetMargin(nMargin); m_cellFixedColDef.SetMargin(nMargin); m_cellFixedRowColDef.SetMargin(nMargin); } int GetDefCellMargin() const { return m_cellDefault.GetMargin(); } int GetDefCellHeight() const { return m_cellDefault.GetHeight(); } void SetDefCellHeight(int nHeight) { m_cellDefault.SetHeight(nHeight); m_cellFixedRowDef.SetHeight(nHeight); m_cellFixedColDef.SetHeight(nHeight); m_cellFixedRowColDef.SetHeight(nHeight); } int GetDefCellWidth() const { return m_cellDefault.GetWidth(); } void SetDefCellWidth(int nWidth) { m_cellDefault.SetWidth(nWidth); m_cellFixedRowDef.SetWidth(nWidth); m_cellFixedColDef.SetWidth(nWidth); m_cellFixedRowColDef.SetWidth(nWidth); } // ***************************************************************************** // int GetSelectedCount() const { return (int)m_SelectedCellMap.GetCount(); } CCellID SetFocusCell(CCellID cell); CCellID SetFocusCell(int nRow, int nCol); CCellID GetFocusCell() const { return m_idCurrentCell; } void SetVirtualMode(BOOL bVirtual); BOOL GetVirtualMode() const { return m_bVirtualMode; } void SetCallbackFunc(GRIDCALLBACK pCallback, LPARAM lParam) { m_pfnCallback = pCallback; m_lParam = lParam; } GRIDCALLBACK GetCallbackFunc() { return m_pfnCallback; } void SetImageList(CImageList* pList) { m_pImageList = pList; } CImageList* GetImageList() const { return m_pImageList; } void SetGridLines(int nWhichLines = GVL_BOTH); int GetGridLines() const { return m_nGridLines; } void SetEditable(BOOL bEditable = TRUE) { m_bEditable = bEditable; } BOOL IsEditable() const { return m_bEditable; } void SetListMode(BOOL bEnableListMode = TRUE); BOOL GetListMode() const { return m_bListMode; } void SetSingleRowSelection(BOOL bSing = TRUE) { m_bSingleRowSelection = bSing; } BOOL GetSingleRowSelection() { return m_bSingleRowSelection & m_bListMode; } void SetSingleColSelection(BOOL bSing = TRUE) { m_bSingleColSelection = bSing; } BOOL GetSingleColSelection() { return m_bSingleColSelection; } void EnableSelection(BOOL bEnable = TRUE) { ResetSelectedRange(); m_bEnableSelection = bEnable; ResetSelectedRange(); } BOOL IsSelectable() const { return m_bEnableSelection; } void SetFixedColumnSelection(BOOL bSelect) { m_bFixedColumnSelection = bSelect;} BOOL GetFixedColumnSelection() { return m_bFixedColumnSelection; } void SetFixedRowSelection(BOOL bSelect) { m_bFixedRowSelection = bSelect; } BOOL GetFixedRowSelection() { return m_bFixedRowSelection; } void EnableDragAndDrop(BOOL bAllow = TRUE) { m_bAllowDragAndDrop = bAllow; } BOOL GetDragAndDrop() const { return m_bAllowDragAndDrop; } void SetRowResize(BOOL bResize = TRUE) { m_bAllowRowResize = bResize; } BOOL GetRowResize() const { return m_bAllowRowResize; } void SetColumnResize(BOOL bResize = TRUE) { m_bAllowColumnResize = bResize; } BOOL GetColumnResize() const { return m_bAllowColumnResize; } void SetHeaderSort(BOOL bSortOnClick = TRUE) { m_bSortOnClick = bSortOnClick; } BOOL GetHeaderSort() const { return m_bSortOnClick; } void SetHandleTabKey(BOOL bHandleTab = TRUE) { m_bHandleTabKey = bHandleTab; } BOOL GetHandleTabKey() const { return m_bHandleTabKey; } void SetDoubleBuffering(BOOL bBuffer = TRUE) { m_bDoubleBuffer = bBuffer; } BOOL GetDoubleBuffering() const { return m_bDoubleBuffer; } void EnableTitleTips(BOOL bEnable = TRUE) { m_bTitleTips = bEnable; } BOOL GetTitleTips() { return m_bTitleTips; } void SetSortColumn(int nCol); int GetSortColumn() const { return m_nSortColumn; } void SetSortAscending(BOOL bAscending) { m_bAscending = bAscending; } BOOL GetSortAscending() const { return m_bAscending; } void SetTrackFocusCell(BOOL bTrack) { m_bTrackFocusCell = bTrack; } BOOL GetTrackFocusCell() { return m_bTrackFocusCell; } void SetFrameFocusCell(BOOL bFrame) { m_bFrameFocus = bFrame; } BOOL GetFrameFocusCell() { return m_bFrameFocus; } void SetAutoSizeStyle(int nStyle = GVS_BOTH) { m_nAutoSizeColumnStyle = nStyle; } int GetAutoSizeStyle() { return m_nAutoSizeColumnStyle; } void EnableHiddenColUnhide(BOOL bEnable = TRUE){ m_bHiddenColUnhide = bEnable; } BOOL GetHiddenColUnhide() { return m_bHiddenColUnhide; } void EnableHiddenRowUnhide(BOOL bEnable = TRUE){ m_bHiddenRowUnhide = bEnable; } BOOL GetHiddenRowUnhide() { return m_bHiddenRowUnhide; } void EnableColumnHide(BOOL bEnable = TRUE) { m_bAllowColHide = bEnable; } BOOL GetColumnHide() { return m_bAllowColHide; } void EnableRowHide(BOOL bEnable = TRUE) { m_bAllowRowHide = bEnable; } BOOL GetRowHide() { return m_bAllowRowHide; } /////////////////////////////////////////////////////////////////////////////////// // default Grid cells. Use these for setting default values such as colors and fonts /////////////////////////////////////////////////////////////////////////////////// public: CGridCellBase* GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const; /////////////////////////////////////////////////////////////////////////////////// // Grid cell Attributes /////////////////////////////////////////////////////////////////////////////////// public: CGridCellBase* GetCell(int nRow, int nCol) const; // Get the actual cell! void SetModified(BOOL bModified = TRUE, int nRow = -1, int nCol = -1); BOOL GetModified(int nRow = -1, int nCol = -1); BOOL IsCellFixed(int nRow, int nCol); BOOL SetItem(const GV_ITEM* pItem); BOOL GetItem(GV_ITEM* pItem); BOOL SetItemText(int nRow, int nCol, LPCTSTR str); // The following was virtual. If you want to override, use // CGridCellBase-derived class's GetText() to accomplish same thing CString GetItemText(int nRow, int nCol) const; // EFW - 06/13/99 - Added to support printf-style formatting codes. // Also supports use with a string resource ID #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 210) BOOL SetItemTextFmt(int nRow, int nCol, LPCTSTR szFmt, ...); BOOL SetItemTextFmtID(int nRow, int nCol, UINT nID, ...); #endif BOOL SetItemData(int nRow, int nCol, LPARAM lParam); LPARAM GetItemData(int nRow, int nCol) const; BOOL SetItemImage(int nRow, int nCol, int iImage); int GetItemImage(int nRow, int nCol) const; BOOL SetItemState(int nRow, int nCol, UINT state); UINT GetItemState(int nRow, int nCol) const; BOOL SetItemFormat(int nRow, int nCol, UINT nFormat); UINT GetItemFormat(int nRow, int nCol) const; BOOL SetItemBkColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT); COLORREF GetItemBkColour(int nRow, int nCol) const; BOOL SetItemFgColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT); COLORREF GetItemFgColour(int nRow, int nCol) const; BOOL SetItemFont(int nRow, int nCol, const LOGFONT* lf); const LOGFONT* GetItemFont(int nRow, int nCol); BOOL IsItemEditing(int nRow, int nCol); BOOL SetCellType(int nRow, int nCol, CRuntimeClass* pRuntimeClass); BOOL SetDefaultCellType( CRuntimeClass* pRuntimeClass); /////////////////////////////////////////////////////////////////////////////////// // Operations /////////////////////////////////////////////////////////////////////////////////// public: int InsertColumn(LPCTSTR strHeading, UINT nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE, int nColumn = -1); int InsertRow(LPCTSTR strHeading, int nRow = -1); BOOL DeleteColumn(int nColumn); BOOL DeleteRow(int nRow); BOOL DeleteNonFixedRows(); BOOL DeleteAllItems(); void ClearCells(CCellRange Selection); BOOL AutoSizeRow(int nRow, BOOL bResetScroll = TRUE); BOOL AutoSizeColumn(int nCol, UINT nAutoSizeStyle = GVS_DEFAULT, BOOL bResetScroll = TRUE); void AutoSizeRows(); void AutoSizeColumns(UINT nAutoSizeStyle = GVS_DEFAULT); void AutoSize(UINT nAutoSizeStyle = GVS_DEFAULT); void ExpandColumnsToFit(BOOL bExpandFixed = TRUE); void ExpandLastColumn(); void ExpandRowsToFit(BOOL bExpandFixed = TRUE); void ExpandToFit(BOOL bExpandFixed = TRUE); void Refresh(); void AutoFill(); // Fill grid with blank cells void EnsureVisible(CCellID &cell) { EnsureVisible(cell.row, cell.col); } void EnsureVisible(int nRow, int nCol); BOOL IsCellVisible(int nRow, int nCol); BOOL IsCellVisible(CCellID cell); BOOL IsCellEditable(int nRow, int nCol) const; BOOL IsCellEditable(CCellID &cell) const; BOOL IsCellSelected(int nRow, int nCol) const; BOOL IsCellSelected(CCellID &cell) const; // SetRedraw stops/starts redraws on things like changing the # rows/columns // and autosizing, but not for user-intervention such as resizes void SetRedraw(BOOL bAllowDraw, BOOL bResetScrollBars = FALSE); BOOL RedrawCell(int nRow, int nCol, CDC* pDC = NULL); BOOL RedrawCell(const CCellID& cell, CDC* pDC = NULL); BOOL RedrawRow(int row); BOOL RedrawColumn(int col); #ifndef _WIN32_WCE BOOL Save(LPCTSTR filename, TCHAR chSeparator = _T(',')); BOOL Load(LPCTSTR filename, TCHAR chSeparator = _T(',')); #endif /////////////////////////////////////////////////////////////////////////////////// // Cell Ranges /////////////////////////////////////////////////////////////////////////////////// public: CCellRange GetCellRange() const; CCellRange GetSelectedCellRange() const; void SetSelectedRange(const CCellRange& Range, BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE); void SetSelectedRange(int nMinRow, int nMinCol, int nMaxRow, int nMaxCol, BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE); BOOL IsValid(int nRow, int nCol) const; BOOL IsValid(const CCellID& cell) const; BOOL IsValid(const CCellRange& range) const; /////////////////////////////////////////////////////////////////////////////////// // Clipboard, drag and drop, and cut n' paste operations /////////////////////////////////////////////////////////////////////////////////// #ifndef GRIDCONTROL_NO_CLIPBOARD virtual void CutSelectedText(); virtual COleDataSource* CopyTextFromGrid(); virtual BOOL PasteTextToGrid(CCellID cell, COleDataObject* pDataObject, BOOL bSelectPastedCells=TRUE); #endif #ifndef GRIDCONTROL_NO_DRAGDROP public: virtual void OnBeginDrag(); virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point); virtual void OnDragLeave(); virtual BOOL OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point); #endif #ifndef GRIDCONTROL_NO_CLIPBOARD virtual void OnEditCut(); virtual void OnEditCopy(); virtual void OnEditPaste(); #endif virtual void OnEditSelectAll(); /////////////////////////////////////////////////////////////////////////////////// // Misc. /////////////////////////////////////////////////////////////////////////////////// public: CCellID GetNextItem(CCellID& cell, int nFlags) const; /* $$LR$$ : Force virtual */ virtual BOOL SortItems(int nCol, BOOL bAscending, LPARAM data = 0); BOOL SortTextItems(int nCol, BOOL bAscending, LPARAM data = 0); BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data = 0); void SetCompareFunction(PFNLVCOMPARE pfnCompare); // in-built sort functions static int CALLBACK pfnCellTextCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); static int CALLBACK pfnCellNumericCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); /////////////////////////////////////////////////////////////////////////////////// // Printing /////////////////////////////////////////////////////////////////////////////////// #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) public: void Print(CPrintDialog* pPrntDialog = NULL); // EFW - New printing support functions void EnableWysiwygPrinting(BOOL bEnable = TRUE) { m_bWysiwygPrinting = bEnable; } BOOL GetWysiwygPrinting() { return m_bWysiwygPrinting; } void SetShadedPrintOut(BOOL bEnable = TRUE) { m_bShadedPrintOut = bEnable; } BOOL GetShadedPrintOut(void) { return m_bShadedPrintOut; } // Use -1 to have it keep the existing value void SetPrintMarginInfo(int nHeaderHeight, int nFooterHeight, int nLeftMargin, int nRightMargin, int nTopMargin, int nBottomMargin, int nGap); void GetPrintMarginInfo(int &nHeaderHeight, int &nFooterHeight, int &nLeftMargin, int &nRightMargin, int &nTopMargin, int &nBottomMargin, int &nGap); /////////////////////////////////////////////////////////////////////////////////// // Printing overrides for derived classes /////////////////////////////////////////////////////////////////////////////////// public: virtual void OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo); virtual void OnPrint(CDC *pDC, CPrintInfo *pInfo); virtual void OnEndPrinting(CDC *pDC, CPrintInfo *pInfo); #endif // #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) // Implementation public: virtual ~CGridCtrl(); protected: BOOL RegisterWindowClass(); BOOL Initialise(); void SetupDefaultCells(); LRESULT SendMessageToParent(int nRow, int nCol, int nMessage) const; LRESULT SendDisplayRequestToParent(GV_DISPINFO* pDisplayInfo) const; LRESULT SendCacheHintToParent(const CCellRange& range) const; BOOL InvalidateCellRect(const int row, const int col); BOOL InvalidateCellRect(const CCellID& cell); BOOL InvalidateCellRect(const CCellRange& cellRange); void EraseBkgnd(CDC* pDC); BOOL GetCellRangeRect(const CCellRange& cellRange, LPRECT lpRect); BOOL SetCell(int nRow, int nCol, CGridCellBase* pCell); int SetMouseMode(int nMode) { int nOldMode = m_MouseMode; m_MouseMode = nMode; return nOldMode; } int GetMouseMode() const { return m_MouseMode; } BOOL MouseOverRowResizeArea(CPoint& point); BOOL MouseOverColumnResizeArea(CPoint& point); CCellID GetTopleftNonFixedCell(BOOL bForceRecalculation = FALSE); CCellRange GetUnobstructedNonFixedCellRange(BOOL bForceRecalculation = FALSE); CCellRange GetVisibleNonFixedCellRange(LPRECT pRect = NULL, BOOL bForceRecalculation = FALSE); BOOL IsVisibleVScroll() { return ( (m_nBarState & GVL_VERT) > 0); } BOOL IsVisibleHScroll() { return ( (m_nBarState & GVL_HORZ) > 0); } void ResetSelectedRange(); void ResetScrollBars(); void EnableScrollBars(int nBar, BOOL bEnable = TRUE); int GetScrollPos32(int nBar, BOOL bGetTrackPos = FALSE); BOOL SetScrollPos32(int nBar, int nPos, BOOL bRedraw = TRUE); BOOL SortTextItems(int nCol, BOOL bAscending, int low, int high); BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data, int low, int high); CPoint GetPointClicked(int nRow, int nCol, const CPoint& point); void ValidateAndModifyCellContents(int nRow, int nCol, LPCTSTR strText); // Overrrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CGridCtrl) protected: virtual void PreSubclassWindow(); //}}AFX_VIRTUAL protected: #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING) // Printing virtual void PrintFixedRowCells(int nStartColumn, int nStopColumn, int& row, CRect& rect, CDC *pDC, BOOL& bFirst); virtual void PrintColumnHeadings(CDC *pDC, CPrintInfo *pInfo); virtual void PrintHeader(CDC *pDC, CPrintInfo *pInfo); virtual void PrintFooter(CDC *pDC, CPrintInfo *pInfo); virtual void PrintRowButtons(CDC *pDC, CPrintInfo* /*pInfo*/); #endif #ifndef GRIDCONTROL_NO_DRAGDROP // Drag n' drop virtual CImageList* CreateDragImage(CPoint *pHotSpot); // no longer necessary #endif // Mouse Clicks virtual void OnFixedColumnClick(CCellID& cell); virtual void OnFixedRowClick(CCellID& cell); // Editing virtual void OnEditCell(int nRow, int nCol, CPoint point, UINT nChar); virtual void OnEndEditCell(int nRow, int nCol, CString str); virtual BOOL ValidateEdit(int nRow, int nCol, LPCTSTR str); virtual void EndEditing(); // Drawing virtual void OnDraw(CDC* pDC); // CGridCellBase Creation and Cleanup virtual CGridCellBase* CreateCell(int nRow, int nCol); virtual void DestroyCell(int nRow, int nCol); // Attributes protected: // General attributes COLORREF m_crFixedTextColour, m_crFixedBkColour; COLORREF m_crGridBkColour, m_crGridLineColour; COLORREF m_crWindowText, m_crWindowColour, m_cr3DFace, // System colours m_crShadow; COLORREF m_crTTipBackClr, m_crTTipTextClr; // Titletip colours - FNA BOOL m_bVirtualMode; LPARAM m_lParam; // lParam for callback GRIDCALLBACK m_pfnCallback; // The callback function int m_nGridLines; BOOL m_bEditable; BOOL m_bModified; BOOL m_bAllowDragAndDrop; BOOL m_bListMode; BOOL m_bSingleRowSelection; BOOL m_bSingleColSelection; BOOL m_bAllowDraw; BOOL m_bEnableSelection; BOOL m_bFixedRowSelection, m_bFixedColumnSelection; BOOL m_bSortOnClick; BOOL m_bHandleTabKey; BOOL m_bDoubleBuffer; BOOL m_bTitleTips; int m_nBarState; BOOL m_bWysiwygPrinting; BOOL m_bHiddenColUnhide, m_bHiddenRowUnhide; BOOL m_bAllowColHide, m_bAllowRowHide; BOOL m_bAutoSizeSkipColHdr; BOOL m_bTrackFocusCell; BOOL m_bFrameFocus; UINT m_nAutoSizeColumnStyle; // Cell size details int m_nRows, m_nFixedRows, m_nCols, m_nFixedCols; CUIntArray m_arRowHeights, m_arColWidths; int m_nVScrollMax, m_nHScrollMax; // Fonts and images CRuntimeClass* m_pRtcDefault; // determines kind of Grid Cell created by default CGridDefaultCell m_cellDefault; // "default" cell. Contains default colours, font etc. CGridDefaultCell m_cellFixedColDef, m_cellFixedRowDef, m_cellFixedRowColDef; CFont m_PrinterFont; // for the printer CImageList* m_pImageList; // Cell data CTypedPtrArray<CObArray, GRID_ROW*> m_RowData; // Mouse operations such as cell selection int m_MouseMode; BOOL m_bLMouseButtonDown, m_bRMouseButtonDown; CPoint m_LeftClickDownPoint, m_LastMousePoint; CCellID m_LeftClickDownCell, m_SelectionStartCell; CCellID m_idCurrentCell, m_idTopLeftCell; int m_nTimerID; int m_nTimerInterval; int m_nResizeCaptureRange; BOOL m_bAllowRowResize, m_bAllowColumnResize; int m_nRowsPerWheelNotch; CMap<DWORD,DWORD, CCellID, CCellID&> m_SelectedCellMap, m_PrevSelectedCellMap; #ifndef GRIDCONTROL_NO_TITLETIPS CTitleTip m_TitleTip; // Title tips for cells #endif // Drag and drop CCellID m_LastDragOverCell; #ifndef GRIDCONTROL_NO_DRAGDROP CGridDropTarget m_DropTarget; // OLE Drop target for the grid #endif // Printing information CSize m_CharSize; int m_nPageHeight; CSize m_LogicalPageSize, // Page size in gridctrl units. m_PaperSize; // Page size in device units. // additional properties to support Wysiwyg printing int m_nPageWidth; int m_nPrintColumn; int m_nCurrPrintRow; int m_nNumPages; int m_nPageMultiplier; // sorting int m_bAscending; int m_nSortColumn; PFNLVCOMPARE m_pfnCompare; // EFW - Added to support shaded/unshaded printout. If true, colored // cells will print as-is. If false, all text prints as black on white. BOOL m_bShadedPrintOut; // EFW - Added support for user-definable margins. Top and bottom are in // lines. Left, right, and gap are in characters (avg width is used). int m_nHeaderHeight, m_nFooterHeight, m_nLeftMargin, m_nRightMargin, m_nTopMargin, m_nBottomMargin, m_nGap; protected: void SelectAllCells(); void SelectColumns(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE); void SelectRows(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE); void SelectCells(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE); void OnSelecting(const CCellID& currentCell); // Generated message map functions //{{AFX_MSG(CGridCtrl) afx_msg void OnPaint(); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnTimer(UINT nIDEvent); afx_msg UINT OnGetDlgCode(); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI); //}}AFX_MSG #ifndef _WIN32_WCE_NO_CURSOR afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); #endif #ifndef _WIN32_WCE afx_msg void OnRButtonDown(UINT nFlags, CPoint point); afx_msg void OnRButtonUp(UINT nFlags, CPoint point); // EFW - Added afx_msg void OnSysColorChange(); #endif #ifndef _WIN32_WCE_NO_CURSOR afx_msg void OnCaptureChanged(CWnd *pWnd); #endif #ifndef GRIDCONTROL_NO_CLIPBOARD afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI); afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI); afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI); #endif #if (_MFC_VER >= 0x0421) || (_WIN32_WCE >= 210) afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection); #endif #if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421) afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); #endif afx_msg LRESULT OnSetFont(WPARAM hFont, LPARAM lParam); afx_msg LRESULT OnGetFont(WPARAM hFont, LPARAM lParam); afx_msg LRESULT OnImeChar(WPARAM wCharCode, LPARAM lParam); afx_msg void OnEndInPlaceEdit(NMHDR* pNMHDR, LRESULT* pResult); afx_msg LRESULT OnCustomPrint(WPARAM, LPARAM); DECLARE_MESSAGE_MAP() enum eMouseModes { MOUSE_NOTHING, MOUSE_SELECT_ALL, MOUSE_SELECT_COL, MOUSE_SELECT_ROW, MOUSE_SELECT_CELLS, MOUSE_SCROLLING_CELLS, MOUSE_OVER_ROW_DIVIDE, MOUSE_SIZING_ROW, MOUSE_OVER_COL_DIVIDE, MOUSE_SIZING_COL, MOUSE_PREPARE_EDIT, #ifndef GRIDCONTROL_NO_DRAGDROP MOUSE_PREPARE_DRAG, MOUSE_DRAGGING #endif }; }; // Returns the default cell implementation for the given grid region inline CGridCellBase* CGridCtrl::GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const { if (bFixedRow && bFixedCol) return (CGridCellBase*) &m_cellFixedRowColDef; if (bFixedRow) return (CGridCellBase*) &m_cellFixedRowDef; if (bFixedCol) return (CGridCellBase*) &m_cellFixedColDef; return (CGridCellBase*) &m_cellDefault; } inline CGridCellBase* CGridCtrl::GetCell(int nRow, int nCol) const { if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols) return NULL; if (GetVirtualMode()) { CGridCellBase* pCell = GetDefaultCell(nRow < m_nFixedRows, nCol < m_nFixedCols); static GV_DISPINFO gvdi; gvdi.item.row = nRow; gvdi.item.col = nCol; gvdi.item.mask = 0xFFFFFFFF; gvdi.item.nState = 0; gvdi.item.nFormat = pCell->GetFormat(); gvdi.item.iImage = pCell->GetImage(); gvdi.item.crBkClr = pCell->GetBackClr(); gvdi.item.crFgClr = pCell->GetTextClr(); gvdi.item.lParam = pCell->GetData(); memcpy(&gvdi.item.lfFont, pCell->GetFont(), sizeof(LOGFONT)); gvdi.item.nMargin = pCell->GetMargin(); gvdi.item.strText.Empty(); // Fix the state bits if (IsCellSelected(nRow, nCol)) gvdi.item.nState |= GVIS_SELECTED; if (nRow < GetFixedRowCount()) gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDROW); if (nCol < GetFixedColumnCount()) gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDCOL); if (GetFocusCell() == CCellID(nRow, nCol)) gvdi.item.nState |= GVIS_FOCUSED; if (m_pfnCallback) m_pfnCallback(&gvdi, m_lParam); else SendDisplayRequestToParent(&gvdi); static CGridCell cell; cell.SetState(gvdi.item.nState); cell.SetFormat(gvdi.item.nFormat); cell.SetImage(gvdi.item.iImage); cell.SetBackClr(gvdi.item.crBkClr); cell.SetTextClr(gvdi.item.crFgClr); cell.SetData(gvdi.item.lParam); cell.SetFont(&(gvdi.item.lfFont)); cell.SetMargin(gvdi.item.nMargin); cell.SetText(gvdi.item.strText); cell.SetGrid((CGridCtrl*)this); return (CGridCellBase*) &cell; } GRID_ROW* pRow = m_RowData[nRow]; if (!pRow) return NULL; return pRow->GetAt(nCol); } inline BOOL CGridCtrl::SetCell(int nRow, int nCol, CGridCellBase* pCell) { if (GetVirtualMode()) return FALSE; if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols) return FALSE; GRID_ROW* pRow = m_RowData[nRow]; if (!pRow) return FALSE; pCell->SetCoords( nRow, nCol); pRow->SetAt(nCol, pCell); return TRUE; } ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_) --- NEW FILE: GridCellDateTime.cpp --- /////////////////////////////////////////////////////////////////////////// // // GridCellDateTime.cpp: implementation of the CGridCellDateTime class. // // Provides the implementation for a datetime picker cell type of the // grid control. // // Written by Podsypalnikov Eugen 15 Mar 2001 // Modified: // 31 May 2001 Fixed m_cTime bug (Chris Maunder) // // For use with CGridCtrl v2.22+ // /////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "GridCtrl.h" #include "GridCell.h" #include "GridCellDateTime.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // CGridCellDateTime IMPLEMENT_DYNCREATE(CGridCellDateTime, CGridCell) IMPLEMENT_DYNCREATE(CGridCellTime, CGridCellDateTime) IMPLEMENT_DYNCREATE(CGridCellDateCal, CGridCellDateTime) ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CGridCellDateTime::CGridCellDateTime() : CGridCell() { m_dwStyle = 0; m_cTime = CTime::GetCurrentTime(); } CGridCellDateTime::CGridCellDateTime(DWORD dwStyle) : CGridCell() { Init(dwStyle); } CGridCellDateTime::~CGridCellDateTime() { } BOOL CGridCellDateTime::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar) { m_bEditing = TRUE; // CInPlaceDateTime auto-deletes itself m_pEditWnd = new CInPlaceDateTime(GetGrid(), rect, m_dwStyle|DTS_UPDOWN, nID, nRow, nCol, GetTextClr(), GetBackClr(), GetTime(), nChar); return TRUE; } CWnd* CGridCellDateTime::GetEditWnd() const { return m_pEditWnd; } void CGridCellDateTime::EndEdit() { if (m_pEditWnd) ((CInPlaceDateTime*)m_pEditWnd)->EndEdit(); } void CGridCellDateTime::Init(DWORD dwStyle) { m_dwStyle = dwStyle; SetTime(CTime::GetCurrentTime()); SetFormat(DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX #ifndef _WIN32_WCE |DT_END_ELLIPSIS #endif ); } // Should be changed to use locale settings void CGridCellDateTime::SetTime(CTime time) { m_cTime = time; if (DTS_TIMEFORMAT == m_dwStyle) { #ifdef _WIN32_WCE CString strTemp; strTemp.Format(_T("%02d:%02d:%02d"), m_cTime.GetHour(), m_cTime.GetMinute(), m_cTime.GetSecond()); SetText(strTemp); #else SetText(m_cTime.Format(_T("%X"))); // Yogurt $$LR$$ (_T("%H:%M:%S"))); #endif } else if (DTS_SHORTDATEFORMAT == m_dwStyle) { #ifdef _WIN32_WCE CString strTemp; strTemp.Format(_T("%02d/%02d/%02d"), m_cTime.GetMonth(), m_cTime.GetDay(), m_cTime.GetYear()); SetText(strTemp); #else SetText(m_cTime.Format(_T("%x"))); // Yogurt $$LR$$ (("%d/%m/%Y"))); #endif } } // Yogurt $$LR$$ CSize CGridCellDateTime::GetCellExtent(CDC* pDC) { CSize sizeScroll (GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL)); CSize sizeCell (CGridCell::GetCellExtent(pDC)); sizeCell.cx += sizeScroll.cx; sizeCell.cy = max(sizeCell.cy,sizeScroll.cy); return sizeCell; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// BOOL CGridCellDateCal::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar) { m_bEditing = TRUE; // CInPlaceDateTime auto-deletes itself m_pEditWnd = new CInPlaceDateTime(GetGrid(), rect, m_dwStyle, nID, nRow, nCol, GetTextClr(), GetBackClr(), GetTime(), nChar); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CInPlaceDateTime CInPlaceDateTime::CInPlaceDateTime(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, int nRow, int nColumn, COLORREF crFore, COLORREF crBack, CTime* pcTime, UINT nFirstChar) { m_crForeClr = crFore; m_crBackClr = crBack; m_nRow = nRow; m_nCol = nColumn; m_nLastChar = 0; m_bExitOnArrows = FALSE; m_pcTime = pcTime; DWORD dwStl = WS_BORDER|WS_VISIBLE|WS_CHILD|dwStyle; if (!Create(dwStl, rect, pParent, nID)) { return; } SetTime(m_pcTime); SetFont(pParent->GetFont()); SetFocus(); switch (nFirstChar) { case VK_LBUTTON: case VK_RETURN: return; case VK_BACK: break; case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT: case VK_NEXT: case VK_PRIOR: case VK_HOME: case VK_END: return; default: break; } SendMessage(WM_CHAR, nFirstChar); } CInPlaceDateTime::~CInPlaceDateTime() { } void CInPlaceDateTime::EndEdit() { CString str; if (::IsWindow(m_hWnd)) { GetWindowText(str); GetTime(*m_pcTime); } // Send Notification to parent GV_DISPINFO dispinfo; dispinfo.hdr.hwndFrom = GetSafeHwnd(); dispinfo.hdr.idFrom = GetDlgCtrlID(); dispinfo.hdr.code = GVN_ENDLABELEDIT; dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM; dispinfo.item.row = m_nRow; dispinfo.item.col = m_nCol; dispinfo.item.strText = str; dispinfo.item.lParam = (LPARAM) m_nLastChar; CWnd* pOwner = GetOwner(); if (IsWindow(pOwner->GetSafeHwnd())) { pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo); } // Close this window (PostNcDestroy will delete this) if (::IsWindow(m_hWnd)) { PostMessage(WM_CLOSE, 0, 0); } } void CInPlaceDateTime::PostNcDestroy() { CDateTimeCtrl::PostNcDestroy(); delete this; } BEGIN_MESSAGE_MAP(CInPlaceDateTime, CDateTimeCtrl) //{{AFX_MSG_MAP(CInPlaceDateTime) ON_WM_KILLFOCUS() ON_WM_KEYDOWN() ON_WM_KEYUP() ON_WM_GETDLGCODE() ON_NOTIFY_REFLECT(DTN_CLOSEUP, OnCloseUp) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CInPlaceDateTime message handlers void CInPlaceDateTime::OnCloseUp (NMHDR * pNotifyStruct, LRESULT* result) { EndEdit(); *result = 0; } void CInPlaceDateTime::OnKillFocus(CWnd* pNewWnd) { HWND pCalWnd; // if focus goes to CMonthCalCtrl from inside ... // just ignore it pCalWnd = (HWND)SendMessage( DTM_GETMONTHCAL ); if( pNewWnd->GetSafeHwnd() == pCalWnd ) return; CDateTimeCtrl::OnKillFocus(pNewWnd); if (GetSafeHwnd() == pNewWnd->GetSafeHwnd()) return; EndEdit(); } UINT CInPlaceDateTime::OnGetDlgCode() { return DLGC_WANTALLKEYS; } void CInPlaceDateTime::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if (( nChar == VK_PRIOR || nChar == VK_NEXT || nChar == VK_DOWN || nChar == VK_UP || nChar == VK_RIGHT || nChar == VK_LEFT) && (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0)) { m_nLastChar = nChar; GetParent()->SetFocus(); return; } CDateTimeCtrl::OnKeyDown(nChar, nRepCnt, nFlags); } void CInPlaceDateTime::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) { m_nLastChar = nChar; GetParent()->SetFocus(); // This will destroy this window return; } CDateTimeCtrl::OnKeyUp(nChar, nRepCnt, nFlags); } --- NEW FILE: MemDC.h --- #if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_) #define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // MemDC.h : header file // ////////////////////////////////////////////////// // CMemDC - memory DC // // Author: Keith Rule // Email: [EMAIL PROTECTED] // Copyright 1996-1997, Keith Rule // // You may freely use or modify this code provided this // Copyright is included in all derived versions. // // History - 10/3/97 Fixed scrolling bug. // Added print support. // 25 feb 98 - fixed minor assertion bug // // This class implements a memory Device Context class CMemDC : public CDC { public: // constructor sets up the memory DC CMemDC(CDC* pDC) : CDC() { ASSERT(pDC != NULL); m_pDC = pDC; m_pOldBitmap = NULL; #ifndef _WIN32_WCE_NO_PRINTING m_bMemDC = !pDC->IsPrinting(); #else m_bMemDC = FALSE; #endif if (m_bMemDC) // Create a Memory DC { pDC->GetClipBox(&m_rect); CreateCompatibleDC(pDC); m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); m_pOldBitmap = SelectObject(&m_bitmap); #ifndef _WIN32_WCE SetWindowOrg(m_rect.left, m_rect.top); #endif // EFW - Bug fix - Fill background in case the user has overridden // WM_ERASEBKGND. We end up with garbage otherwise. // CJM - moved to fix a bug in the fix. FillSolidRect(m_rect, pDC->GetBkColor()); } else // Make a copy of the relevent parts of the current DC for printing { #if !defined(_WIN32_WCE) || ((_WIN32_WCE > 201) && !defined(_WIN32_WCE_NO_PRINTING)) m_bPrinting = pDC->m_bPrinting; #endif m_hDC = pDC->m_hDC; m_hAttribDC = pDC->m_hAttribDC; } } // Destructor copies the contents of the mem DC to the original DC ~CMemDC() { if (m_bMemDC) { // Copy the offscreen bitmap onto the screen. m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), this, m_rect.left, m_rect.top, SRCCOPY); //Swap back the original bitmap. SelectObject(m_pOldBitmap); } else { // All we need to do is replace the DC with an illegal value, // this keeps us from accidently deleting the handles associated with // the CDC that was passed to the constructor. m_hDC = m_hAttribDC = NULL; } } // Allow usage as a pointer CMemDC* operator->() {return this;} // Allow usage as a pointer operator CMemDC*() {return this;} private: CBitmap m_bitmap; // Offscreen bitmap CBitmap* m_pOldBitmap; // bitmap originally found in CMemDC CDC* m_pDC; // Saves CDC passed in constructor CRect m_rect; // Rectangle of drawing area. BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_) --- NEW FILE: TitleTip.cpp --- //////////////////////////////////////////////////////////////////////////// // TitleTip.cpp : implementation file // // Based on code by Zafir Anjum // // Adapted by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2002. All Rights Reserved. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.20+ // // History // 10 Apr 1999 Now accepts a LOGFONT pointer and // a tracking rect in Show(...) (Chris Maunder) // 18 Apr 1999 Resource leak in Show fixed by Daniel Gehriger // 8 Mar 2000 Added double-click fix found on codeguru // web site but forgot / can't find who contributed it // 28 Mar 2000 Aqiruse (marked with //FNA) // Titletips now use cell color // 18 Jun 2000 Delayed window creation added // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "gridctrl.h" #ifndef GRIDCONTROL_NO_TITLETIPS #include "TitleTip.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CTitleTip CTitleTip::CTitleTip() { // Register the window class if it has not already been registered. WNDCLASS wndcls; HINSTANCE hInst = AfxGetInstanceHandle(); if(!(::GetClassInfo(hInst, TITLETIP_CLASSNAME, &wndcls))) { // otherwise we need to register a new class wndcls.style = CS_SAVEBITS; wndcls.lpfnWndProc = ::DefWindowProc; wndcls.cbClsExtra = wndcls.cbWndExtra = 0; wndcls.hInstance = hInst; wndcls.hIcon = NULL; wndcls.hCursor = LoadCursor( hInst, IDC_ARROW ); wndcls.hbrBackground = (HBRUSH)(COLOR_INFOBK +1); wndcls.lpszMenuName = NULL; wndcls.lpszClassName = TITLETIP_CLASSNAME; if (!AfxRegisterClass(&wndcls)) AfxThrowResourceException(); } m_dwLastLButtonDown = ULONG_MAX; m_dwDblClickMsecs = GetDoubleClickTime(); m_bCreated = FALSE; m_pParentWnd = NULL; } CTitleTip::~CTitleTip() { } BEGIN_MESSAGE_MAP(CTitleTip, CWnd) //{{AFX_MSG_MAP(CTitleTip) ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTitleTip message handlers BOOL CTitleTip::Create(CWnd * pParentWnd) { ASSERT_VALID(pParentWnd); // Already created? if (m_bCreated) return TRUE; DWORD dwStyle = WS_BORDER | WS_POPUP; DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST; m_pParentWnd = pParentWnd; m_bCreated = CreateEx(dwExStyle, TITLETIP_CLASSNAME, NULL, dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL ); return m_bCreated; } BOOL CTitleTip::DestroyWindow() { m_bCreated = FALSE; return CWnd::DestroyWindow(); } // Show - Show the titletip if needed // rectTitle - The rectangle within which the original // title is constrained - in client coordinates // lpszTitleText - The text to be displayed // xoffset - Number of pixel that the text is offset from // left border of the cell void CTitleTip::Show(CRect rectTitle, LPCTSTR lpszTitleText, int xoffset /*=0*/, LPRECT lpHoverRect /*=NULL*/, const LOGFONT* lpLogFont /*=NULL*/, COLORREF crTextClr /* CLR_DEFAULT */, COLORREF crBackClr /* CLR_DEFAULT */) { if (!IsWindow(m_hWnd)) Create(m_pParentWnd); ASSERT( ::IsWindow( GetSafeHwnd() ) ); if (rectTitle.IsRectEmpty()) return; // If titletip is already displayed, don't do anything. if( IsWindowVisible() ) return; m_rectHover = (lpHoverRect != NULL)? lpHoverRect : rectTitle; m_rectHover.right++; m_rectHover.bottom++; m_pParentWnd->ClientToScreen( m_rectHover ); ScreenToClient( m_rectHover ); // Do not display the titletip is app does not have focus if( GetFocus() == NULL ) return; // Define the rectangle outside which the titletip will be hidden. // We add a buffer of one pixel around the rectangle m_rectTitle.top = -1; m_rectTitle.left = -xoffset-1; m_rectTitle.right = rectTitle.Width()-xoffset; m_rectTitle.bottom = rectTitle.Height()+1; // Determine the width of the text m_pParentWnd->ClientToScreen( rectTitle ); CClientDC dc(this); CString strTitle = _T(""); strTitle += _T(" "); strTitle += lpszTitleText; strTitle += _T(" "); CFont font, *pOldFont = NULL; if (lpLogFont) { font.CreateFontIndirect(lpLogFont); pOldFont = dc.SelectObject( &font ); } else { // use same font as ctrl pOldFont = dc.SelectObject( m_pParentWnd->GetFont() ); } CSize size = dc.GetTextExtent( strTitle ); TEXTMETRIC tm; dc.GetTextMetrics(&tm); size.cx += tm.tmOverhang; CRect rectDisplay = rectTitle; rectDisplay.left += xoffset; rectDisplay.right = rectDisplay.left + size.cx + xoffset; // Do not display if the text fits within available space if ( rectDisplay.right > rectTitle.right-xoffset ) { // Show the titletip SetWindowPos( &wndTop, rectDisplay.left, rectDisplay.top, rectDisplay.Width(), rectDisplay.Height(), SWP_SHOWWINDOW|SWP_NOACTIVATE ); // FNA - handle colors correctly if (crBackClr != CLR_DEFAULT) { CBrush backBrush(crBackClr); CBrush* pOldBrush = dc.SelectObject(&backBrush); CRect rect; dc.GetClipBox(&rect); // Erase the area needed dc.PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); dc.SelectObject(pOldBrush); } // Set color if (crTextClr != CLR_DEFAULT)//FNA dc.SetTextColor(crTextClr);//FA dc.SetBkMode( TRANSPARENT ); dc.TextOut( 0, 0, strTitle ); SetCapture(); } dc.SelectObject( pOldFont ); } void CTitleTip::Hide() { if (!::IsWindow(GetSafeHwnd())) return; if (GetCapture()->GetSafeHwnd() == GetSafeHwnd()) ReleaseCapture(); ShowWindow( SW_HIDE ); } void CTitleTip::OnMouseMove(UINT nFlags, CPoint point) { if (!m_rectHover.PtInRect(point)) { Hide(); // Forward the message ClientToScreen( &point ); CWnd *pWnd = WindowFromPoint( point ); if ( pWnd == this ) pWnd = m_pParentWnd; int hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); if (hittest == HTCLIENT) { pWnd->ScreenToClient( &point ); pWnd->PostMessage( WM_MOUSEMOVE, nFlags, MAKELONG(point.x,point.y) ); } else { pWnd->PostMessage( WM_NCMOUSEMOVE, hittest, MAKELONG(point.x,point.y) ); } } } BOOL CTitleTip::PreTranslateMessage(MSG* pMsg) { // Used to qualify WM_LBUTTONDOWN messages as double-clicks DWORD dwTick=0; BOOL bDoubleClick=FALSE; CWnd *pWnd; int hittest; switch (pMsg->message) { case WM_LBUTTONDOWN: // Get tick count since last LButtonDown dwTick = GetTickCount(); bDoubleClick = ((dwTick - m_dwLastLButtonDown) <= m_dwDblClickMsecs); m_dwLastLButtonDown = dwTick; // NOTE: DO NOT ADD break; STATEMENT HERE! Let code fall through case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: { POINTS pts = MAKEPOINTS( pMsg->lParam ); POINT point; point.x = pts.x; point.y = pts.y; ClientToScreen( &point ); Hide(); pWnd = WindowFromPoint( point ); if (!pWnd) return CWnd::PreTranslateMessage(pMsg); if( pWnd->GetSafeHwnd() == GetSafeHwnd()) pWnd = m_pParentWnd; hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y)); if (hittest == HTCLIENT) { pWnd->ScreenToClient( &point ); pMsg->lParam = MAKELONG(point.x,point.y); } else { switch (pMsg->message) { case WM_LBUTTONDOWN: pMsg->message = WM_NCLBUTTONDOWN; break; case WM_RBUTTONDOWN: pMsg->message = WM_NCRBUTTONDOWN; break; case WM_MBUTTONDOWN: pMsg->message = WM_NCMBUTTONDOWN; break; } pMsg->wParam = hittest; pMsg->lParam = MAKELONG(point.x,point.y); } // If this is the 2nd WM_LBUTTONDOWN in x milliseconds, // post a WM_LBUTTONDBLCLK message instead of a single click. pWnd->PostMessage( bDoubleClick ? WM_LBUTTONDBLCLK : pMsg->message, pMsg->wParam, pMsg->lParam); return TRUE; } case WM_KEYDOWN: case WM_SYSKEYDOWN: Hide(); m_pParentWnd->PostMessage( pMsg->message, pMsg->wParam, pMsg->lParam ); return TRUE; } if( GetFocus() == NULL ) { Hide(); return TRUE; } return CWnd::PreTranslateMessage(pMsg); } #endif // GRIDCONTROL_NO_TITLETIPS --- NEW FILE: GridCellCombo.cpp --- // GridCellCombo.cpp : implementation file // // MFC Grid Control - Main grid cell class // // Provides the implementation for a combobox cell type of the // grid control. // // Written by Chris Maunder <[EMAIL PROTECTED]> // Copyright (c) 1998-2001. All Rights Reserved. // // Parts of the code contained in this file are based on the original // CInPlaceList from http://www.codeguru.com/listview // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. // // An email letting me know how you are using it would be nice as well. // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability for any damage/loss of business that // this product may cause. // // For use with CGridCtrl v2.22+ // // History: // 6 Aug 1998 - Added CComboEdit to subclass the edit control - code // provided by Roelf Werkman <[EMAIL PROTECTED]>. Added nID to // the constructor param list. // 29 Nov 1998 - bug fix in onkeydown (Markus Irtenkauf) // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "GridCell.h" #include "GridCtrl.h" #include "GridCellCombo.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CComboEdit CComboEdit::CComboEdit() { } CComboEdit::~CComboEdit() { } // Stoopid win95 accelerator key problem workaround - Matt Weagle. BOOL CComboEdit::PreTranslateMessage(MSG* pMsg) { // Make sure that the keystrokes continue to the appropriate handlers if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) { ::TranslateMessage(pMsg); ::DispatchMessage(pMsg); return TRUE; } // Catch the Alt key so we don't choke if focus is going to an owner drawn button if (pMsg->message == WM_SYSCHAR) return TRUE; return CEdit::PreTranslateMessage(pMsg); } BEGIN_MESSAGE_MAP(CComboEdit, CEdit) //{{AFX_MSG_MAP(CComboEdit) ON_WM_KILLFOCUS() ON_WM_KEYDOWN() ON_WM_KEYUP() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CComboEdit message handlers void CComboEdit::OnKillFocus(CWnd* pNewWnd) { CEdit::OnKillFocus(pNewWnd); CInPlaceList* pOwner = (CInPlaceList*) GetOwner(); // This MUST be a CInPlaceList if (pOwner) pOwner->EndEdit(); } void CComboEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if ((nChar == VK_PRIOR || nChar == VK_NEXT || nChar == VK_DOWN || nChar == VK_UP || nChar == VK_RIGHT || nChar == VK_LEFT) && (GetKeyState(VK_CONTROL) < 0 && GetDlgCtrlID() == IDC_COMBOEDIT)) { CWnd* pOwner = GetOwner(); if (pOwner) pOwner->SendMessage(WM_KEYDOWN, nChar, nRepCnt+ (((DWORD)nFlags)<<16)); return; } CEdit::OnKeyDown(nChar, nRepCnt, nFlags); } void CComboEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar == VK_ESCAPE) { CWnd* pOwner = GetOwner(); if (pOwner) pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16)); return; } if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) { CWnd* pOwner = GetOwner(); if (pOwner) pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16)); return; } CEdit::OnKeyUp(nChar, nRepCnt, nFlags); } ///////////////////////////////////////////////////////////////////////////// // CInPlaceList CInPlaceList::CInPlaceList(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, int nRow, int nColumn, COLORREF crFore, COLORREF crBack, CStringArray& Items, CString sInitText, UINT nFirstChar) { m_crForeClr = crFore; m_crBackClr = crBack; m_nNumLines = 4; m_sInitText = sInitText; m_nRow = nRow; m_nCol = nColumn; m_nLastChar = 0; m_bExitOnArrows = FALSE; //(nFirstChar != VK_LBUTTON); // If mouse click brought us here, // Create the combobox DWORD dwComboStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL| CBS_AUTOHSCROLL | dwStyle; int nHeight = rect.Height(); rect.bottom = rect.bottom + m_nNumLines*nHeight + ::GetSystemMetrics(SM_CYHSCROLL); if (!Create(dwComboStyle, rect, pParent, nID)) return; // Add the strings for (int i = 0; i < Items.GetSize(); i++) AddString(Items[i]); SetFont(pParent->GetFont()); SetItemHeight(-1, nHeight); int nMaxLength = GetCorrectDropWidth(); /* if (nMaxLength > rect.Width()) rect.right = rect.left + nMaxLength; // Resize the edit window and the drop down window MoveWindow(rect); */ SetDroppedWidth(nMaxLength); SetHorizontalExtent(0); // no horz scrolling // Set the initial text to m_sInitText if (::IsWindow(m_hWnd) && SelectString(-1, m_sInitText) == CB_ERR) SetWindowText(m_sInitText); // No text selected, so restore what was there before ShowDropDown(); // Subclass the combobox edit control if style includes CBS_DROPDOWN if ((dwStyle & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST) { m_edit.SubclassDlgItem(IDC_COMBOEDIT, this); SetFocus(); switch (nFirstChar) { case VK_LBUTTON: case VK_RETURN: m_edit.SetSel((int)_tcslen(m_sInitText), -1); return; case VK_BACK: m_edit.SetSel((int)_tcslen(m_sInitText), -1); break; case VK_DOWN: case VK_UP: case VK_RIGHT: case VK_LEFT: case VK_NEXT: case VK_PRIOR: case VK_HOME: case VK_END: m_edit.SetSel(0,-1); return; default: m_edit.SetSel(0,-1); } SendMessage(WM_CHAR, nFirstChar); } else SetFocus(); } CInPlaceList::~CInPlaceList() { } void CInPlaceList::EndEdit() { CString str; if (::IsWindow(m_hWnd)) GetWindowText(str); // Send Notification to parent GV_DISPINFO dispinfo; dispinfo.hdr.hwndFrom = GetSafeHwnd(); dispinfo.hdr.idFrom = GetDlgCtrlID(); dispinfo.hdr.code = GVN_ENDLABELEDIT; dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM; dispinfo.item.row = m_nRow; dispinfo.item.col = m_nCol; dispinfo.item.strText = str; dispinfo.item.lParam = (LPARAM) m_nLastChar; CWnd* pOwner = GetOwner(); if (IsWindow(pOwner->GetSafeHwnd())) pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo ); // Close this window (PostNcDestroy will delete this) if (::IsWindow(m_hWnd)) PostMessage(WM_CLOSE, 0, 0); } int CInPlaceList::GetCorrectDropWidth() { const int nMaxWidth = 200; // don't let the box be bigger than this // Reset the dropped width int nNumEntries = GetCount(); int nWidth = 0; CString str; CClientDC dc(this); int nSave = dc.SaveDC(); dc.SelectObject(GetFont()); int nScrollWidth = ::GetSystemMetrics(SM_CXVSCROLL); for (int i = 0; i < nNumEntries; i++) { GetLBText(i, str); int nLength = dc.GetTextExtent(str).cx + nScrollWidth; nWidth = max(nWidth, nLength); } // Add margin space to the calculations nWidth += dc.GetTextExtent(_T("0")).cx; dc.RestoreDC(nSave); nWidth = min(nWidth, nMaxWidth); return nWidth; //SetDroppedWidth(nWidth); } /* // Fix by Ray ([EMAIL PROTECTED]) void CInPlaceList::OnSelendOK() { int iIndex = GetCurSel(); if( iIndex != CB_ERR) { CString strLbText; GetLBText( iIndex, strLbText); if (!((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST)) m_edit.SetWindowText( strLbText); } GetParent()->SetFocus(); } */ void CInPlaceList::PostNcDestroy() { CComboBox::PostNcDestroy(); delete this; } BEGIN_MESSAGE_MAP(CInPlaceList, CComboBox) //{{AFX_MSG_MAP(CInPlaceList) ON_WM_KILLFOCUS() ON_WM_KEYDOWN() ON_WM_KEYUP() ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown) ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelChange) ON_WM_GETDLGCODE() ON_WM_CTLCOLOR_REFLECT() //}}AFX_MSG_MAP //ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendOK) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CInPlaceList message handlers UINT CInPlaceList::OnGetDlgCode() { return DLGC_WANTALLKEYS; } void CInPlaceList::OnSelChange() { CString csTexte; if (::IsWindow(m_hWnd)) { int isel = GetCurSel(); if (isel != CB_ERR) { GetLBText (isel, csTexte); // Notification du changement // Send Notification to parent owner (grid Owner) GV_DISPINFO dispinfo; CWnd* pParent = GetParent(); dispinfo.hdr.hwndFrom = pParent->GetSafeHwnd(); dispinfo.hdr.idFrom = pParent->GetDlgCtrlID(); dispinfo.hdr.code = GVN_CHANGEDLABELEDIT; dispinfo.item.mask = LVIF_TEXT; dispinfo.item.row = m_nRow; dispinfo.item.col = m_nCol; dispinfo.item.strText = csTexte; CWnd* pOwner = pParent->GetOwner(); if (IsWindow(pOwner->GetSafeHwnd())) pOwner->SendMessage(WM_NOTIFY, dispinfo.hdr.idFrom, (LPARAM)&dispinfo); } } } void CInPlaceList::OnDropdown() { SetDroppedWidth(GetCorrectDropWidth()); } void CInPlaceList::OnKillFocus(CWnd* pNewWnd) { CComboBox::OnKillFocus(pNewWnd); if (GetSafeHwnd() == pNewWnd->GetSafeHwnd()) return; // Only end editing on change of focus if we're using the CBS_DROPDOWNLIST style if ((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST) EndEdit(); } // If an arrow key (or associated) is pressed, then exit if // a) The Ctrl key was down, or // b) m_bExitOnArrows == TRUE void CInPlaceList::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if ((nChar == VK_PRIOR || nChar == VK_NEXT || nChar == VK_DOWN || nChar == VK_UP || nChar == VK_RIGHT || nChar == VK_LEFT) && (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0)) { m_nLastChar = nChar; GetParent()->SetFocus(); return; } CComboBox::OnKeyDown(nChar, nRepCnt, nFlags); } // Need to keep a lookout for Tabs, Esc and Returns. void CInPlaceList::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { if (nChar == VK_ESCAPE) SetWindowText(m_sInitText); // restore previous text if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE) { m_nLastChar = nChar; GetParent()->SetFocus(); // This will destroy this window return; } CComboBox::OnKeyUp(nChar, nRepCnt, nFlags); } HBRUSH CInPlaceList::CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/) { /* static CBrush brush(m_crBackClr); pDC->SetTextColor(m_crForeClr); pDC->SetBkMode(TRANSPARENT); return (HBRUSH) brush.GetSafeHandle(); */ // TODO: Return a non-NULL brush if the parent's handler should not be called return NULL; } ///////////////////////////////////////////////////////////////////////////// // CGridCellCombo ///////////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNCREATE(CGridCellCombo, CGridCell) CGridCellCombo::CGridCellCombo() : CGridCell() { SetStyle(CBS_DROPDOWN); // CBS_DROPDOWN, CBS_DROPDOWNLIST, CBS_SIMPLE, CBS_SORT } // Create a control to do the editing BOOL CGridCellCombo::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar) { m_bEditing = TRUE; // CInPlaceList auto-deletes itself m_pEditWnd = new CInPlaceList(GetGrid(), rect, GetStyle(), nID, nRow, nCol, GetTextClr(), GetBackClr(), m_Strings, GetText(), nChar); return TRUE; } CWnd* CGridCellCombo::GetEditWnd() const { if (m_pEditWnd && (m_pEditWnd->GetStyle() & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST ) return &(((CInPlaceList*)m_pEditWnd)->m_edit); return NULL; } CSize CGridCellCombo::GetCellExtent(CDC* pDC) { CSize sizeScroll(GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL)); //Yogurt $$LR$$ CSize sizeCell (CGridCell::GetCellExtent(pDC)); sizeCell.cx += sizeScroll.cx; sizeCell.cy = max(sizeCell.cy,sizeScroll.cy); return sizeCell; } // Cancel the editing. void CGridCellCombo::EndEdit() { if (m_pEditWnd) ((CInPlaceList*)m_pEditWnd)->EndEdit(); } // Override draw so that when the cell is selected, a drop arrow is shown in the RHS. BOOL CGridCellCombo::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/) { #ifdef _WIN32_WCE return CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd); #else // Cell selected? //if ( !IsFixed() && IsFocused()) if (GetGrid()->IsCellEditable(nRow, nCol) && !IsEditing()) { // Get the size of the scroll box CSize sizeScroll(GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL)); // enough room to draw? if (sizeScroll.cy < rect.Width() && sizeScroll.cy < rect.Height()) { // Draw control at RHS of cell CRect ScrollRect = rect; ScrollRect.left = rect.right - sizeScroll.cx; ScrollRect.bottom = rect.top + sizeScroll.cy; // Do the draw pDC->DrawFrameControl(ScrollRect, DFC_SCROLL, DFCS_SCROLLDOWN); // Adjust the remaining space in the cell rect.right = ScrollRect.left; } } CString strTempText = GetText(); if (IsEditing()) SetText(_T("")); // drop through and complete the cell drawing using the base class' method BOOL bResult = CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd); if (IsEditing()) SetText(strTempText); return bResult; #endif } // For setting the strings that will be displayed in the drop list void CGridCellCombo::SetOptions(const CStringArray& ar) { m_Strings.RemoveAll(); for (int i = 0; i < ar.GetSize(); i++) m_Strings.Add(ar[i]); } ///////////////////////////////////////////////////////////////////////////// // CGridCellList ///////////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNCREATE(CGridCellList, CGridCellCombo) CGridCellList::CGridCellList() : CGridCellCombo() { SetStyle(CBS_DROPDOWNLIST); // CBS_DROPDOWN, CBS_DROPDOWNLIST, CBS_SIMPLE, CBS_SORT }