当前位置:   article > 正文

MFC界面美化第四篇----自绘list列表(重绘列表)

MFC界面美化第四篇----自绘list列表(重绘列表)

1.前言

最近发现读者对我的mfc美化的专栏比较感兴趣,因此在这里进行续写,这里我会计划写几个连续的篇章,包括对MFC按钮的美化,菜单栏的美化,标题栏的美化,list列表的美化,直到最后形成一个完整的成品效果。

2.最终效果展示

3.思路分析

1.编写mfc的list的派生类对 列表进行重绘

2.list和其他的空间有些区别,要分别对标题栏,和内容栏进行重绘。

4.实现的过程

1.在mfc界面,增加空间list

2.修改list的属性

边框:false
静态边缘:false
视图:Reporte
无滚动:true
 

3.声明list的变量

  1. public:
  2. CListCtrlComboEx m_list;

4.OnInitDialog 里面的核心代码

  1. BOOL CCustomListDlg::OnInitDialog()
  2. {
  3. CDialogEx::OnInitDialog();
  4. // 将“关于...”菜单项添加到系统菜单中。
  5. // IDM_ABOUTBOX 必须在系统命令范围内。
  6. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  7. ASSERT(IDM_ABOUTBOX < 0xF000);
  8. CMenu* pSysMenu = GetSystemMenu(FALSE);
  9. if (pSysMenu != nullptr)
  10. {
  11. BOOL bNameValid;
  12. CString strAboutMenu;
  13. bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
  14. ASSERT(bNameValid);
  15. if (!strAboutMenu.IsEmpty())
  16. {
  17. pSysMenu->AppendMenu(MF_SEPARATOR);
  18. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  19. }
  20. }
  21. // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
  22. // 执行此操作
  23. SetIcon(m_hIcon, TRUE); // 设置大图标
  24. SetIcon(m_hIcon, FALSE); // 设置小图标
  25. //LIST
  26. CRect rect;
  27. m_list.GetClientRect(&rect);
  28. DWORD dwStyle = m_list.GetExtendedStyle();
  29. //dwStyle = (dwStyle | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
  30. dwStyle |= dwStyle | LVS_REPORT & ~LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_SHOWSELALWAYS | LVS_EX_HEADERDRAGDROP;
  31. m_list.SetExtendedStyle(dwStyle);
  32. //m_list.SetBo
  33. m_list.SetItemHeight(25);
  34. m_list.SetFontSize(17);
  35. m_list.InsertColumn(0, _T("编号"), LVCFMT_CENTER, (rect.Width() / 3) + 30, 0);
  36. m_list.InsertColumn(1, _T("菜谱"), LVCFMT_CENTER, (rect.Width() - (rect.Width() / 3) - 30), 1);
  37. m_list.InsertColumn(2, _T(""), LVCFMT_CENTER, 1000, 2);
  38. m_list.InsertItem(0, _T("1"));
  39. m_list.InsertItem(1, _T("2"));
  40. m_list.InsertItem(2, _T("3"));
  41. m_list.InsertItem(3, _T("4"));
  42. m_list.InsertItem(4, _T("5"));
  43. m_list.InsertItem(5, _T("6"));
  44. m_list.InsertItem(6, _T("7"));
  45. m_list.InsertItem(7, _T("8"));
  46. m_list.InsertItem(8, _T("9"));
  47. m_list.InsertItem(9, _T(""));
  48. m_list.InsertItem(10, _T(""));
  49. m_list.InsertItem(11, _T(""));
  50. // TODO: 在此添加额外的初始化代码
  51. return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
  52. }

5.list重写的对应封装代码

BitMark.h

  1. #pragma once
  2. #define BITMARK_MAX (2500)
  3. #define BITMARK_ROWS_DEF (100)
  4. #define BITMARK_COLS_DEF (20)
  5. class BitMark
  6. {
  7. public:
  8. BitMark(void);
  9. virtual ~BitMark(void);
  10. virtual BOOL Seek(DWORD uRows, DWORD uCols);
  11. virtual void Set(DWORD uRow, DWORD uCol, BOOL bValid);
  12. virtual BOOL IsValid(DWORD uRow, DWORD uCol);
  13. virtual void Clear();
  14. protected:
  15. DWORD m_uRows, m_uCols;
  16. BYTE m_aBit[BITMARK_MAX];
  17. };

BitMark.cpp

  1. #include "pch.h"
  2. #include "BitMark.h"
  3. #ifdef _AFX
  4. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #undef THIS_FILE
  7. static const char THIS_FILE[] = __FILE__;
  8. #endif
  9. #endif
  10. BitMark::BitMark(void)
  11. {
  12. ZeroMemory(m_aBit, BITMARK_MAX);
  13. }
  14. BitMark::~BitMark(void)
  15. {
  16. }
  17. BOOL BitMark::Seek(DWORD uRows, DWORD uCols)
  18. {
  19. if((uRows*uCols) > BITMARK_MAX)
  20. return FALSE;
  21. m_uRows = uRows;
  22. m_uCols = uCols;
  23. return TRUE;
  24. }
  25. void BitMark::Set(DWORD uRow, DWORD uCol, BOOL bValid)
  26. {
  27. if((uRow*m_uCols + uCol) >= BITMARK_MAX)
  28. return;
  29. m_aBit[uRow*m_uCols+ uCol] = ( bValid ? 1 : 0 );
  30. }
  31. BOOL BitMark::IsValid(DWORD uRow, DWORD uCol)
  32. {
  33. BOOL bValid =FALSE;
  34. if((uRow*m_uCols + uCol) >= BITMARK_MAX)
  35. return FALSE;
  36. if(0 != m_aBit[uRow*m_uCols + uCol])
  37. bValid = TRUE;
  38. return bValid;
  39. }
  40. void BitMark::Clear()
  41. {
  42. ZeroMemory(m_aBit, BITMARK_MAX);
  43. }

HeaderCtrlEx.h

  1. #pragma once
  2. #include <afxcmn.h>
  3. class HeaderCtrlEx :
  4. public CHeaderCtrl
  5. {
  6. DECLARE_DYNAMIC(HeaderCtrlEx)
  7. protected:
  8. DECLARE_MESSAGE_MAP()
  9. void OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult);
  10. LRESULT OnLayout(WPARAM wParam, LPARAM lParam);
  11. afx_msg BOOL OnEraseBkgnd(CDC* pDC);
  12. };

HeaderCtrlEx.cpp

  1. #include "pch.h"
  2. #include "HeaderCtrlEx.h"
  3. IMPLEMENT_DYNAMIC(HeaderCtrlEx, CHeaderCtrl)
  4. BEGIN_MESSAGE_MAP(HeaderCtrlEx, CHeaderCtrl)
  5. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &HeaderCtrlEx::OnNMCustomdraw)
  6. ON_MESSAGE(HDM_LAYOUT, &HeaderCtrlEx::OnLayout)
  7. ON_WM_ERASEBKGND()
  8. END_MESSAGE_MAP()
  9. void HeaderCtrlEx::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
  10. {
  11. // ref: https://stackoverflow.com/questions/28766659/changing-mfc-list-control-header-color
  12. LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
  13. // TODO: Add your control notification handler code here
  14. *pResult = CDRF_DODEFAULT;
  15. if (pNMCD->dwDrawStage == CDDS_PREPAINT)
  16. {
  17. CDC* pDC = CDC::FromHandle(pNMCD->hdc);
  18. CRect rect(0, 0, 0, 0);
  19. GetClientRect(&rect);
  20. //pDC->FillSolidRect(&rect, RGB(215, 235, 226));
  21. pDC->FillSolidRect(&rect, RGB(30, 34, 39));
  22. *pResult = CDRF_NOTIFYITEMDRAW;
  23. }
  24. else if (pNMCD->dwDrawStage == CDDS_ITEMPREPAINT)
  25. {
  26. HDITEM hditem;
  27. TCHAR buffer[MAX_PATH] = { 0 };
  28. SecureZeroMemory(&hditem, sizeof(HDITEM));
  29. hditem.mask = HDI_TEXT;
  30. hditem.pszText = buffer;
  31. hditem.cchTextMax = MAX_PATH;
  32. GetItem(pNMCD->dwItemSpec, &hditem);
  33. CDC* pDC = CDC::FromHandle(pNMCD->hdc);
  34. //pDC->SetTextColor(RGB(0, 0, 0));
  35. pDC->SetTextColor(RGB(255, 255, 255));
  36. //pDC->SetBkColor(RGB(215, 235, 226));
  37. pDC->SetBkColor(RGB(30, 34, 39));
  38. //CFont m_pFont;
  39. //m_pFont.CreateFont(ConvertWithDPIRatio(31),
  40. // 0, 0, 0, FW_MEDIUM,
  41. // FALSE, FALSE,
  42. // 0,
  43. // ANSI_CHARSET, // nCharSet
  44. // OUT_DEFAULT_PRECIS, // nOutPrecision
  45. // CLIP_DEFAULT_PRECIS, // nClipPrecision
  46. // DEFAULT_QUALITY, // nQuality
  47. // DEFAULT_PITCH | FF_SWISS, _T("Arial"));
  48. //pDC->SelectObject(m_pFont);
  49. CString str(buffer);
  50. CRect rect = pNMCD->rc;
  51. rect.OffsetRect(6, 0);
  52. pDC->DrawText(str, CRect(rect), DT_SINGLELINE | DT_VCENTER);
  53. *pResult = CDRF_SKIPDEFAULT;
  54. }
  55. }
  56. /*
  57. * Describe: Change the height of table header
  58. * Author : Canliang Wu
  59. * Date : 2021/12/15
  60. */
  61. LRESULT HeaderCtrlEx::OnLayout(WPARAM wParam, LPARAM lParam)
  62. {
  63. LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
  64. HD_LAYOUT& hdl = *(HD_LAYOUT*)lParam;
  65. RECT* prc = hdl.prc; // The table list rectangle
  66. WINDOWPOS* pwpos = hdl.pwpos; // The table header rectangle
  67. int nHeight = (int)(pwpos->cy * 1.3);
  68. pwpos->cy = nHeight; // New table header height
  69. //pwpos->x += 3;
  70. prc->top = nHeight; // Decreases the table list height on the table header height
  71. return lResult;
  72. }
  73. BOOL HeaderCtrlEx::OnEraseBkgnd(CDC* pDC)
  74. {
  75. // TODO: Add your message handler code here and/or call default
  76. //return CListCtrl::OnEraseBkgnd(pDC);
  77. return FALSE;
  78. }

ListControlDefine.h

  1. #pragma once
  2. #define ListCtrlMask_Rows (500)
  3. #define ListCtrlMask_Cols (20)
  4. #define ListCtrlMask_Max (ListCtrlMask_Rows * ListCtrlMask_Cols)
  5. typedef struct ListCtrlMask {
  6. BYTE Bit[ListCtrlMask_Max];
  7. } ListCtrlMask;

ListControlDefine.cpp

  1. #include "pch.h"
  2. #include "ListControlDefine.h"

ListCtrlComboEx.h

  1. #if !defined(AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_)
  2. #define AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_
  3. #if _MSC_VER > 1000
  4. #pragma once
  5. #endif // _MSC_VER > 1000
  6. // ListCtrlComboEx.h : header file
  7. #include "ListControlDefine.h"
  8. #include "BitMark.h"
  9. #include "HeaderCtrlEx.h"
  10. #include <afxcmn.h>
  11. #define cgCComboBox CComboBox //you can use yourself defined combobox
  12. /
  13. // CListCtrlComboEx window
  14. #include <vector>
  15. using namespace std;
  16. struct stEditAble
  17. {
  18. int nRow;
  19. int nCol;
  20. };
  21. struct stComboAble
  22. {
  23. int nRow;
  24. int nCol;
  25. cgCComboBox *pCombo;
  26. };
  27. #define IDCB_ONLISTCONTROL 9001
  28. #define CListCtrlComboEx_ColumnMax (200)
  29. class CListCtrlComboEx : public CListCtrl
  30. {
  31. // Construction
  32. public:
  33. CListCtrlComboEx();
  34. public:
  35. UINT m_nMsgComboSelChange;
  36. BitMark m_oBm;
  37. int m_nRowDblClk;
  38. int m_nColDblClk;
  39. int InsertColumn(int nCol, LPCTSTR lpszColumnHeading,
  40. int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1);
  41. void SetItemWarning(int nItem, int nSubItem, BOOL bValid);
  42. int m_anFormat[CListCtrlComboEx_ColumnMax];
  43. void CreateComboBox(UINT nMsgComboSelChange);
  44. void CreateEditBox();
  45. CComboBox* GetCombo();
  46. protected:
  47. CComboBox* m_pcbListCtrl;
  48. HeaderCtrlEx m_HeaderCtrl;
  49. protected:
  50. vector<stEditAble> m_EditAbleArray;
  51. vector<stComboAble> m_ComboAbleArray;
  52. int m_iRow;
  53. int m_iCol;
  54. CEdit *m_pEdit;
  55. int m_iHeight;
  56. CFont m_oFont;
  57. // Attributes
  58. public:
  59. void SetEditAble(int nRow,int nCol);
  60. void SetComboAble(int nRow,int nCol,cgCComboBox *pCombo);
  61. void SetItemHeight(int nHeight);
  62. COLORREF GetTableItemColor(int nRow, int nCol, COLORREF clrDef);
  63. void ClearAllAbles();
  64. BOOL GetCellRect(int nRow, int nCol, CRect& rect);
  65. void SetFontSize(int cHeight = 18);
  66. BOOL m_bFontSeted;
  67. // Operations
  68. public:
  69. virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
  70. void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
  71. // Overrides
  72. // ClassWizard generated virtual function overrides
  73. //{{AFX_VIRTUAL(CListCtrlComboEx)
  74. //}}AFX_VIRTUAL
  75. // Implementation
  76. public:
  77. virtual ~CListCtrlComboEx();
  78. // Generated message map functions
  79. protected:
  80. BOOL IsEditAble(int nRow,int nCol);
  81. BOOL IsComboAble(int nRow,int nCol);
  82. virtual void PreSubclassWindow();
  83. LPCTSTR MakeShortString(CDC *pDC,LPCTSTR lpszLong,int nColumnLen,int nOffset);
  84. protected:
  85. //{{AFX_MSG(CListCtrlComboEx)
  86. // NOTE - the ClassWizard will add and remove member functions here.
  87. virtual afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
  88. virtual afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
  89. virtual afx_msg BOOL OnHeaderEndResize(UINT, NMHDR* pNMHDR, LRESULT* pResult);
  90. afx_msg void OnCbnKillfocusCombo();
  91. afx_msg void OnCbnSelchangeCombo();
  92. afx_msg BOOL OnEraseBkgnd(CDC* pDC);
  93. //}}AFX_MSG
  94. DECLARE_DYNAMIC(CListCtrlComboEx)
  95. DECLARE_MESSAGE_MAP()
  96. public:
  97. afx_msg void OnPaint();
  98. public:
  99. afx_msg BOOL OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult);
  100. };
  101. /
  102. //{{AFX_INSERT_LOCATION}}
  103. // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
  104. #endif // !defined(AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_)

ListCtrlComboEx.cpp

  1. // ListCtrlComboEx.cpp : implementation file
  2. //
  3. #include "pch.h"
  4. //#include "cgListComboTest.h"
  5. #include "ListCtrlComboEx.h"
  6. //#include "resource.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /
  13. // CListCtrlComboEx
  14. CListCtrlComboEx::CListCtrlComboEx()
  15. {
  16. m_pcbListCtrl = NULL;
  17. m_nRowDblClk = 0;
  18. m_nColDblClk = 0;
  19. m_bFontSeted = FALSE;
  20. m_EditAbleArray.clear();
  21. m_ComboAbleArray.clear();
  22. m_iRow = -1;
  23. m_iCol = -1;
  24. m_iHeight = 0;
  25. m_pEdit = NULL;
  26. m_nMsgComboSelChange = 0;
  27. ZeroMemory(&m_anFormat, sizeof(m_anFormat));
  28. //m_pListCtrlMask = NULL;
  29. }
  30. CListCtrlComboEx::~CListCtrlComboEx()
  31. {
  32. if(m_pcbListCtrl) {
  33. m_pcbListCtrl->DestroyWindow();
  34. delete m_pcbListCtrl;
  35. m_pcbListCtrl = NULL;
  36. }
  37. }
  38. int CListCtrlComboEx::InsertColumn(int nCol, LPCTSTR lpszColumnHeading,
  39. int nFormat /*= LVCFMT_LEFT*/, int nWidth /*= -1*/, int nSubItem /*= -1*/)
  40. {
  41. if(nCol>=0)
  42. m_anFormat[nCol] = nFormat;
  43. return CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat, nWidth, nSubItem);
  44. }
  45. void CListCtrlComboEx::SetItemWarning(int nItem, int nSubItem, BOOL bValid)
  46. {
  47. //return;
  48. m_oBm.Set(nItem, nSubItem, bValid);
  49. }
  50. void CListCtrlComboEx::CreateComboBox(UINT nMsgComboSelChange)
  51. {
  52. m_nMsgComboSelChange = nMsgComboSelChange;
  53. CFont* cf = GetFont();
  54. CComboBox *pCombo;
  55. pCombo = new CComboBox();
  56. CRect rect;
  57. GetCellRect(0,1,rect);
  58. pCombo->Create(WS_CHILD/*|WS_VISIBLE*/|CBS_AUTOHSCROLL|CBS_DROPDOWNLIST,rect,(CWnd*)this, IDCB_ONLISTCONTROL);
  59. pCombo->SetFont(cf);
  60. m_pcbListCtrl = pCombo;
  61. }
  62. CComboBox* CListCtrlComboEx::GetCombo()
  63. {
  64. return m_pcbListCtrl;
  65. }
  66. COLORREF CListCtrlComboEx::GetTableItemColor(int nRow, int nCol, COLORREF clrDef)
  67. {
  68. COLORREF clr;
  69. clr = clrDef; //RGB(0, 0, 0);
  70. //if((nRow*nCol) >= ListCtrlMask_Max)
  71. // return clr;
  72. //if(!m_pListCtrlMask)
  73. // return clr;
  74. //if(m_pListCtrlMask->Bit[nRow*ListCtrlMask_Cols + nCol])
  75. // clr = RGB(255, 0, 0);
  76. if(m_oBm.IsValid(nRow, nCol))
  77. clr = RGB(255, 0, 0);
  78. //if(myutil::GetBit(m_oWarningBitMark.bit[nRow], nCol))
  79. //{
  80. // clr = RGB(255, 0, 0);
  81. //}
  82. //if(myutil::GetBit(theApp.m_pYmVoltTblRow[nRow].upper_warning_bit, nCol))
  83. //{
  84. // clr = RGB(255, 0, 0);
  85. //}
  86. //if(myutil::GetBit(theApp.m_pYmVoltTblRow[nRow].lower_warning_bit, nCol))
  87. //{
  88. // clr = RGB(255, 0, 0);
  89. //}
  90. //if(m_oVoltTbl.v_row[nRow].v[nCol] > m_nUpper)
  91. //{
  92. // clr = RGB(255, 0, 0);
  93. //}
  94. //if(m_oVoltTbl.v_row[nRow].v[nCol] < m_nLower)
  95. //{
  96. // clr = RGB(255, 0, 0);
  97. //}
  98. //if(theApp.m_pYmVoltTblRow[nRow].V.volt[nCol] < theApp.m_pYmVoltTblRow[nRow].Lower)
  99. //{
  100. // clr = RGB(255, 0, 0);
  101. //}
  102. return clr;
  103. }
  104. void CListCtrlComboEx::ClearAllAbles()
  105. {
  106. m_EditAbleArray.clear();
  107. m_ComboAbleArray.clear();
  108. m_iRow = -1;
  109. m_iCol = -1;
  110. m_pEdit = NULL;
  111. }
  112. IMPLEMENT_DYNAMIC(CListCtrlComboEx, CListCtrl)
  113. BEGIN_MESSAGE_MAP(CListCtrlComboEx, CListCtrl)
  114. //{{AFX_MSG_MAP(CListCtrlComboEx)
  115. // NOTE - the ClassWizard will add and remove mapping macros here.
  116. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
  117. ON_NOTIFY_EX(HDN_ENDTRACKA, 0, OnHeaderEndResize)
  118. ON_NOTIFY_EX(HDN_ENDTRACKW, 0, OnHeaderEndResize)
  119. ON_WM_MEASUREITEM_REFLECT()
  120. ON_WM_LBUTTONDOWN()
  121. ON_WM_ERASEBKGND()
  122. ON_CBN_KILLFOCUS(IDCB_ONLISTCONTROL, &CListCtrlComboEx::OnCbnKillfocusCombo)
  123. ON_CBN_SELCHANGE(IDCB_ONLISTCONTROL, &CListCtrlComboEx::OnCbnSelchangeCombo)
  124. //}}AFX_MSG_MAP
  125. ON_WM_PAINT()
  126. ON_NOTIFY_REFLECT_EX(NM_DBLCLK, &CListCtrlComboEx::OnNMDblclk)
  127. END_MESSAGE_MAP()
  128. /
  129. // CListCtrlComboEx message handlers
  130. void CListCtrlComboEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
  131. {
  132. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
  133. int nRow = (int)pLVCD->nmcd.dwItemSpec;
  134. pResult = CDRF_DODEFAULT;
  135. /* // Allow column-traits to perform their custom drawing
  136. if (pLVCD->nmcd.dwDrawStage & CDDS_SUBITEM)
  137. {
  138. CComboBox* pCombo = GetCellColumnTrait(nRow, pLVCD->iSubItem);
  139. if (pCombo != NULL)
  140. return; // Everything is handled by the column-trait
  141. }
  142. // Always perform drawing of cell-focus rectangle
  143. switch (pLVCD->nmcd.dwDrawStage)
  144. {
  145. case CDDS_PREPAINT:
  146. *pResult |= CDRF_NOTIFYITEMDRAW;
  147. break;
  148. // Before painting a row
  149. case CDDS_ITEMPREPAINT:
  150. {
  151. *pResult |= CDRF_NOTIFYPOSTPAINT; // Ensure row-traits gets called
  152. *pResult |= CDRF_NOTIFYSUBITEMDRAW; // Ensure column-traits gets called
  153. } break;
  154. // After painting the entire row
  155. case CDDS_ITEMPOSTPAINT:
  156. {
  157. ;
  158. } break;
  159. }*/
  160. }
  161. BOOL CListCtrlComboEx::OnHeaderEndResize(UINT, NMHDR* pNMHDR, LRESULT* pResult)
  162. {
  163. int size = m_ComboAbleArray.size();
  164. int i;
  165. for(i=0;i<size;i++)
  166. {
  167. int nRow = m_ComboAbleArray[i].nRow;
  168. int nCol = m_ComboAbleArray[i].nCol;
  169. cgCComboBox *pCombo = m_ComboAbleArray[i].pCombo;
  170. CRect rect;
  171. GetCellRect(nRow,nCol,rect);
  172. rect.bottom -= 2*::GetSystemMetrics(SM_CXEDGE);
  173. pCombo->MoveWindow(rect);
  174. pCombo->SetWindowPos(NULL, // not relative to any other windows
  175. 0, 0, // TopLeft corner doesn't change
  176. rect.Width(), (pCombo->GetCount()+1)*rect.Height(), // existing width, new height
  177. SWP_NOMOVE | SWP_NOZORDER // don't move box or change z-ordering.
  178. );
  179. pCombo->ShowWindow(TRUE);
  180. }
  181. Invalidate(FALSE);
  182. return FALSE;
  183. }
  184. void CListCtrlComboEx::OnCbnKillfocusCombo()
  185. {
  186. int size = m_ComboAbleArray.size();
  187. int i;
  188. for(i=0;i<size;i++)
  189. {
  190. int nRow = m_ComboAbleArray[i].nRow;
  191. int nCol = m_ComboAbleArray[i].nCol;
  192. cgCComboBox *pCombo = m_ComboAbleArray[i].pCombo;
  193. pCombo->ShowWindow(FALSE);
  194. }
  195. Invalidate(FALSE);
  196. }
  197. void CListCtrlComboEx::OnCbnSelchangeCombo()
  198. {
  199. CWnd* P = this->GetParent();
  200. if(m_nMsgComboSelChange)
  201. P->PostMessage(m_nMsgComboSelChange);
  202. int size = m_ComboAbleArray.size();
  203. int i;
  204. for(i=0;i<size;i++)
  205. {
  206. int nRow = m_ComboAbleArray[i].nRow;
  207. int nCol = m_ComboAbleArray[i].nCol;
  208. cgCComboBox *pCombo = m_ComboAbleArray[i].pCombo;
  209. pCombo->ShowWindow(FALSE);
  210. }
  211. Invalidate(FALSE);
  212. }
  213. void CListCtrlComboEx::SetItemHeight(int nHeight)
  214. {
  215. m_iHeight = nHeight;
  216. CRect rcWin;
  217. GetWindowRect(&rcWin);
  218. WINDOWPOS wp;
  219. wp.hwnd = m_hWnd;
  220. wp.cx = rcWin.Width();
  221. wp.cy = rcWin.Height();
  222. wp.flags = SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER;
  223. SendMessage(WM_WINDOWPOSCHANGED,0,(LPARAM)&wp);
  224. }
  225. BOOL CListCtrlComboEx::GetCellRect(int nRow, int nCol,CRect& rect)
  226. {
  227. if (GetSubItemRect(nRow, nCol, LVIR_BOUNDS, rect)==FALSE)
  228. return FALSE;
  229. CRect colRect;
  230. if (GetHeaderCtrl()->GetItemRect(nCol, colRect)==FALSE)
  231. return FALSE;
  232. if (nCol==0)
  233. {
  234. // Fix bug where LVIR_BOUNDS gives the entire row for nCol==0
  235. CRect labelRect;
  236. if (GetSubItemRect(nRow, nCol, LVIR_LABEL, labelRect)==FALSE)
  237. return FALSE;
  238. rect.right = labelRect.right;
  239. rect.left = labelRect.right - colRect.Width();
  240. }
  241. else
  242. {
  243. // Fix bug when width is smaller than subitem image width
  244. rect.right = rect.left + colRect.Width();
  245. }
  246. return TRUE;
  247. }
  248. void CListCtrlComboEx::SetFontSize(int cHeight)
  249. {
  250. if(m_bFontSeted)
  251. return;
  252. m_bFontSeted = TRUE;
  253. m_oFont.CreateFont(
  254. cHeight, // nHeight
  255. 0, // nWidth
  256. 0, // nEscapement
  257. 0, // nOrientation
  258. FW_NORMAL, // nWeight
  259. FALSE, // bItalic
  260. FALSE, // bUnderline
  261. 0, // cStrikeOut
  262. ANSI_CHARSET, // nCharSet
  263. OUT_DEFAULT_PRECIS, // nOutPrecision
  264. CLIP_DEFAULT_PRECIS, // nClipPrecision
  265. DEFAULT_QUALITY, // nQuality
  266. DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
  267. _T("Arial")); // lpszFacename
  268. SetFont(&m_oFont, TRUE);
  269. }
  270. BOOL CListCtrlComboEx::IsEditAble(int nRow,int nCol)
  271. {
  272. int i;
  273. int size = m_EditAbleArray.size();
  274. if(size > 0)
  275. {
  276. for(i=0;i<size;i++)
  277. {
  278. if(m_EditAbleArray[i].nRow == nRow && m_EditAbleArray[i].nCol == nCol)
  279. return TRUE;
  280. }
  281. }
  282. return FALSE;
  283. }
  284. BOOL CListCtrlComboEx::IsComboAble(int nRow,int nCol)
  285. {
  286. int i;
  287. int size = m_ComboAbleArray.size();
  288. if(size > 0)
  289. {
  290. for(i=0;i<size;i++)
  291. {
  292. if(m_ComboAbleArray[i].nRow == nRow && m_ComboAbleArray[i].nCol == nCol)
  293. return TRUE;
  294. }
  295. }
  296. return FALSE;
  297. }
  298. void CListCtrlComboEx::SetEditAble(int nRow,int nCol)
  299. {
  300. stEditAble sam;
  301. sam.nRow = nRow;
  302. sam.nCol = nCol;
  303. m_EditAbleArray.push_back(sam);
  304. }
  305. void CListCtrlComboEx::SetComboAble(int nRow,int nCol,cgCComboBox *pCombo)
  306. {
  307. stComboAble sam;
  308. sam.nRow = nRow;
  309. sam.nCol = nCol;
  310. sam.pCombo = pCombo;
  311. m_ComboAbleArray.push_back(sam);
  312. CRect rect;
  313. GetCellRect(nRow,nCol,rect);
  314. rect.bottom -= 2*::GetSystemMetrics(SM_CXEDGE);
  315. pCombo->SetWindowPos(NULL, // not relative to any other windows
  316. 0, 0, // TopLeft corner doesn't change
  317. rect.Width(), (pCombo->GetCount()+1)*rect.Height(), // existing width, new height
  318. SWP_NOMOVE | SWP_NOZORDER // don't move box or change z-ordering.
  319. );
  320. pCombo->ShowWindow(TRUE);
  321. pCombo->SetFocus();
  322. }
  323. void CListCtrlComboEx::OnLButtonDown(UINT nFlags, CPoint point)
  324. {
  325. int nRow, nCol;
  326. if(m_pEdit != NULL)
  327. {
  328. CString str;
  329. m_pEdit->GetWindowText(str);
  330. SetItemText(m_iRow,m_iCol,str);
  331. m_iRow = -1;
  332. m_iCol = -1;
  333. delete m_pEdit;
  334. // m_pEdit->PostMessage(WM_CLOSE);
  335. m_pEdit = NULL;
  336. }
  337. LVHITTESTINFO lvhti = {0};
  338. lvhti.pt = point;
  339. nRow = ListView_SubItemHitTest(m_hWnd, &lvhti); // SubItemHitTest is non-const
  340. nCol = lvhti.iSubItem;
  341. if (!(lvhti.flags & LVHT_ONITEM))
  342. nRow = -1;
  343. if(nRow == -1 || nCol == -1)
  344. {
  345. CListCtrl::OnLButtonDown(nFlags, point);
  346. return;
  347. }
  348. if(IsEditAble(nRow,nCol))
  349. {
  350. m_iRow = nRow;
  351. m_iCol = nCol;
  352. CRect rect;
  353. GetCellRect(nRow,nCol,rect);
  354. m_pEdit = new CEdit();
  355. m_pEdit->Create(WS_CHILD|ES_LEFT|ES_AUTOHSCROLL,rect,this,0);
  356. CString str;
  357. str = GetItemText(nRow,nCol);
  358. m_pEdit->SetWindowText(str);
  359. m_pEdit->ShowWindow(SW_SHOW);
  360. m_pEdit->SetFocus();
  361. return;
  362. }
  363. CListCtrl::OnLButtonDown(nFlags,point);
  364. }
  365. void CListCtrlComboEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  366. {
  367. if(m_iHeight>0)
  368. {
  369. lpMeasureItemStruct->itemHeight = m_iHeight;
  370. }
  371. }
  372. void CListCtrlComboEx::PreSubclassWindow()
  373. {
  374. ModifyStyle(0,LVS_OWNERDRAWFIXED);
  375. //CListCtrl::PreSubclassWindow();
  376. CHeaderCtrl* pHeader = GetHeaderCtrl();
  377. if (pHeader != NULL) { VERIFY(m_HeaderCtrl.SubclassWindow(pHeader->m_hWnd)); }
  378. CListCtrl::PreSubclassWindow();
  379. }
  380. void CListCtrlComboEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  381. {
  382. int nItem = lpDrawItemStruct->itemID;
  383. if(nItem == -1)
  384. return;
  385. CRect rcCol = lpDrawItemStruct->rcItem;
  386. CString sText;
  387. CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  388. int nOldDCMode = pDC->SaveDC();
  389. LVITEM item;
  390. item.iItem = nItem;
  391. item.iSubItem = 0;
  392. item.mask = LVIF_IMAGE|LVIF_STATE;
  393. item.stateMask = 0xFFFF;
  394. GetItem(&item);
  395. BOOL bSelected = item.state & LVIS_SELECTED;
  396. COLORREF color = RGB(30, 34, 39);
  397. if(bSelected)
  398. {
  399. pDC->SetBkColor(RGB(30, 34, 39));
  400. pDC->SetTextColor(RGB(255,255,255)/*::GetSysColor(COLOR_HIGHLIGHTTEXT)*//*GetTableItemColor(nItem, item.iSubItem)*/);
  401. color = RGB(30, 34, 39);
  402. }
  403. else
  404. {
  405. pDC->SetBkColor(RGB(30, 34, 39));
  406. pDC->SetTextColor(RGB(255,255,255)/*::GetSysColor(COLOR_WINDOWTEXT)*//*GetTableItemColor(nItem, item.iSubItem)*/);
  407. }
  408. LV_COLUMN lvc;
  409. lvc.mask = LVCF_FMT|LVCF_WIDTH;
  410. rcCol.right = rcCol.left;
  411. for(int nCol=0;GetColumn(nCol,&lvc);nCol++)
  412. {
  413. rcCol.left = rcCol.right;
  414. rcCol.right = rcCol.left + GetColumnWidth(nCol);
  415. HPEN hOldPen = (HPEN)::SelectObject(lpDrawItemStruct->hDC,::CreatePen(PS_SOLID,1,color));
  416. HBRUSH hOldBrush = (HBRUSH)::SelectObject(lpDrawItemStruct->hDC,::CreateSolidBrush(color));
  417. ::Rectangle(lpDrawItemStruct->hDC,rcCol.left-1,rcCol.top-1,rcCol.right,rcCol.bottom);
  418. ::DeleteObject(SelectObject(lpDrawItemStruct->hDC,hOldBrush));
  419. ::DeleteObject(SelectObject(lpDrawItemStruct->hDC,hOldPen));
  420. sText = MakeShortString(pDC,GetItemText(nItem,nCol),rcCol.Width(),3);
  421. if(bSelected)
  422. {
  423. pDC->SetBkColor(RGB(30, 34, 39));
  424. //pDC->SetTextColor(GetTableItemColor(nItem, nCol, ::GetSysColor(COLOR_HIGHLIGHTTEXT)));
  425. pDC->SetTextColor(GetTableItemColor(nItem, nCol, RGB(255, 255, 255)));
  426. color = RGB(30, 34, 39);
  427. }
  428. else
  429. {
  430. pDC->SetBkColor(RGB(30, 34, 39));
  431. pDC->SetTextColor(GetTableItemColor(nItem, nCol, RGB(255, 255, 255)));
  432. }
  433. //在这里进行测试
  434. //在这里进行测试
  435. UINT format = DT_CENTER;
  436. switch(/*lvc.fmt*/m_anFormat[nCol] & (LVCFMT_LEFT | LVCFMT_CENTER | LVCFMT_RIGHT))
  437. {
  438. case LVCFMT_LEFT:
  439. format = DT_LEFT;
  440. break;
  441. case LVCFMT_CENTER:
  442. format = DT_CENTER;
  443. break;
  444. case LVCFMT_RIGHT:
  445. format = DT_RIGHT;
  446. break;
  447. default:
  448. break;
  449. }
  450. pDC->DrawText(sText,CRect::CRect(rcCol.left+3,rcCol.top,rcCol.right,rcCol.bottom), format/*DT_CENTER*//*format*//*DT_LEFT*/|DT_VCENTER|DT_SINGLELINE );
  451. }
  452. pDC->RestoreDC(nOldDCMode);
  453. }
  454. LPCTSTR CListCtrlComboEx::MakeShortString(CDC *pDC,LPCTSTR lpszLong,int nColumnLen,int nOffset)
  455. {
  456. static const _TCHAR szThreeDots[] = _T("...");
  457. int nStringLen = lstrlen(lpszLong);
  458. if(nStringLen == 0 ||
  459. (pDC->GetTextExtent(lpszLong,nStringLen).cx+nOffset) <= nColumnLen)
  460. {
  461. return(lpszLong);
  462. }
  463. static _TCHAR szShort[MAX_PATH];
  464. lstrcpy(szShort,lpszLong);
  465. int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;
  466. for(int i=nStringLen-1; i>0; i--)
  467. {
  468. szShort[i] = 0;
  469. if((pDC->GetTextExtent(szShort,i).cx+nAddLen+nOffset) <= nColumnLen)
  470. {
  471. break;
  472. }
  473. }
  474. lstrcat(szShort,szThreeDots);
  475. return(szShort);
  476. }
  477. void CListCtrlComboEx::OnPaint()
  478. {
  479. //CPaintDC dc(this); // device context for painting
  480. TODO: 在此处添加消息处理程序代码
  481. 不为绘图消息调用 CListCtrl::OnPaint()
  482. //
  483. //CPaintDC dc(this); // device context for painting
  484. //const MSG *msg = GetCurrentMessage();
  485. //DefWindowProc( msg->message, msg->wParam, msg->lParam ); //这两句不能省,否则程序会因消息循环出现异常
  486. Draw the lines only for LVS_REPORT mode
  487. //if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )
  488. //{
  489. // // Get the number of columns
  490. // CClientDC dc(this );
  491. // CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
  492. // int nColumnCount = pHeader->GetItemCount();
  493. // // The bottom of the header corresponds to the top of the line
  494. // RECT rect;
  495. // pHeader->GetClientRect( &rect );
  496. // int top = rect.bottom;
  497. // // Now get the client rect so we know the line length and
  498. // // when to stop
  499. // GetClientRect( &rect );
  500. // // The border of the column is offset by the horz scroll
  501. // int borderx = 0 - GetScrollPos( SB_HORZ );
  502. // CPen listSepPen(PS_SOLID, 1, RGB(201, 213, 240)); //定制你的分割线的颜色
  503. // //CPen listSepPen(PS_SOLID, 1, RGB(30, 34, 39));
  504. // CPen *pOldPen = dc.SelectObject(&listSepPen);
  505. // for( int i = 0; i < nColumnCount; i++ )
  506. // {
  507. // // Get the next border
  508. // borderx += GetColumnWidth( i );
  509. // // if next border is outside client area, break out
  510. // if( borderx >= rect.right ) break;
  511. // // Draw the line.
  512. // dc.MoveTo( borderx, top);
  513. // dc.LineTo( borderx, rect.bottom );
  514. // }
  515. // // Draw the horizontal grid lines
  516. // // First get the height
  517. // if( !GetItemRect( 0, &rect, LVIR_BOUNDS ))
  518. // return;
  519. // int height = rect.bottom - rect.top;
  520. // GetClientRect( &rect );
  521. // int width = rect.right;
  522. // for(int i = 1; i <= GetCountPerPage(); i++ )
  523. // {
  524. // dc.MoveTo( 0, top + height*i);
  525. // dc.LineTo( width, top + height*i );
  526. // }
  527. // dc.SelectObject(pOldPen);
  528. //
  529. //}
  530. //-------------------------------替换
  531. const MSG* msg = GetCurrentMessage();
  532. DefWindowProc(msg->message, msg->wParam, msg->lParam);
  533. CClientDC dc(this);
  534. CRect rect;
  535. GetClientRect(&rect);
  536. CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
  537. int nColumnCount = pHeader->GetItemCount();
  538. CRect rectHead;
  539. pHeader->GetClientRect(&rectHead);
  540. // 画边框
  541. //CPen penBorder(PS_SOLID, 1, RGB(0, 66, 66));
  542. //CPen* pOldPen = dc->SelectObject(&penBorder);
  543. //dc.MoveTo(rect.left, rect.top );
  544. //dc.LineTo(rect.left, rect.bottom);
  545. //dc.MoveTo(rect.right - 1, rect.top );
  546. //dc.LineTo(rect.right - 1, rect.bottom)
  547. if ((GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
  548. {
  549. CPen penGrid;
  550. //penGrid.CreatePen(PS_SOLID, 1, RGB(0, 66, 66));//颜色
  551. penGrid.CreatePen(PS_SOLID, 1, RGB(48, 48, 48));//颜色
  552. CPen* oldPen = dc.SelectObject(&penGrid);
  553. int borderx = 0 - GetScrollPos(SB_HORZ);
  554. //画边框
  555. //dc.MoveTo(rect.right, rect.top);
  556. //dc.LineTo(rect.left, rect.top);
  557. //dc.MoveTo(rect.right, rect.bottom);
  558. //dc.LineTo(rect.left, rect.bottom);
  559. //dc.MoveTo(rect.left, rect.top);
  560. //dc.LineTo(rect.left, rect.bottom);
  561. //dc.MoveTo(rect.right, rect.top);
  562. //dc.LineTo(rect.right, rect.bottom);
  563. //取客户区域
  564. CRect item;
  565. int nHightPerLine = 18;
  566. if (GetItemRect(0, &item, LVIR_BOUNDS))
  567. {
  568. nHightPerLine = item.bottom - item.top;
  569. }
  570. //画纵向线
  571. for (int i = 0; i < nColumnCount; i++)
  572. {
  573. borderx += GetColumnWidth(i);
  574. if (borderx > rect.right)
  575. {
  576. break;
  577. }
  578. dc.MoveTo(borderx, rectHead.bottom);
  579. dc.LineTo(borderx, rect.bottom);
  580. }
  581. //画横向线
  582. for (int i = 0; i <= GetCountPerPage(); i++)
  583. {
  584. dc.MoveTo(rect.left, rectHead.bottom + nHightPerLine * i + 1);
  585. dc.LineTo(borderx, rectHead.bottom + nHightPerLine * i + 1);
  586. }
  587. dc.SelectObject(penGrid);
  588. penGrid.DeleteObject();
  589. }
  590. }
  591. BOOL CListCtrlComboEx::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
  592. {
  593. // TODO: 在此添加控件通知处理程序代码
  594. *pResult = 0;
  595. NM_LISTVIEW* pNMListView=(NM_LISTVIEW*)pNMHDR;
  596. m_nRowDblClk=pNMListView->iItem;//m_row为被选中行的行序号(int类型成员变量)
  597. m_nColDblClk=pNMListView->iSubItem;//m_column为被选中行的列序号(int类型成员变量)
  598. return FALSE;
  599. }
  600. BOOL CListCtrlComboEx::OnEraseBkgnd(CDC* pDC)
  601. {
  602. // TODO: Add your message handler code here and/or call default
  603. //return CListCtrl::OnEraseBkgnd(pDC);
  604. return FALSE;
  605. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/306289
推荐阅读
相关标签
  

闽ICP备14008679号