当前位置:   article > 正文

MFC list ctrl 修改表头和表格字体、双击编辑一步搞定(源码)_mfc list ctrl 修改表头和表格字体、双击编辑一步搞定(源码)

mfc list ctrl 修改表头和表格字体、双击编辑一步搞定(源码)

目录

一、效果图

 二、HeaderCtrlEx 实现修改表头字体、背景颜色

三、CListEdit 实现双击编辑

四、HeaderCtrlEx、CListEdit应用到List Ctrl中

五、实战



一、效果图

 二、HeaderCtrlEx 实现修改表头字体、背景颜色

HeaderCtrlEx.h

  1. class HeaderCtrlEx : public CHeaderCtrl
  2. {
  3. friend class CListCtrlEx;
  4. DECLARE_DYNAMIC(HeaderCtrlEx)
  5. public:
  6. HeaderCtrlEx();
  7. virtual ~HeaderCtrlEx();
  8. private:
  9. COLORREF m_clrBK; //表头背景颜色
  10. COLORREF m_clrFont; //表头字体颜色
  11. CFont* m_pFont; //表头字体样式
  12. protected:
  13. DECLARE_MESSAGE_MAP()
  14. void OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult);
  15. LRESULT OnLayout(WPARAM wParam, LPARAM lParam);
  16. private:
  17. void SetHeaderCtrlFont(CFont* pFont);
  18. };

HeaderCtrlEx.cpp

  1. #include "stdafx.h"
  2. #include "HeaderCtrlEx.h"
  3. IMPLEMENT_DYNAMIC(HeaderCtrlEx, CHeaderCtrl)
  4. static BOOL s_bDeleteFont = TRUE;
  5. BEGIN_MESSAGE_MAP(HeaderCtrlEx, CHeaderCtrl)
  6. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &HeaderCtrlEx::OnNMCustomdraw)
  7. ON_MESSAGE(HDM_LAYOUT, &HeaderCtrlEx::OnLayout)
  8. END_MESSAGE_MAP()
  9. HeaderCtrlEx::HeaderCtrlEx()
  10. {
  11. m_pFont = new CFont;
  12. m_pFont->CreateFont(12, //以逻辑单位方式指定字体的高度
  13. 0, //以逻辑单位方式指定字体中字符的平均宽度
  14. 0, //指定偏离垂线和X轴在显示面上的夹角(单位:0.1度)
  15. 0, //指定字符串基线和X轴之间的夹角(单位:0.1度)
  16. FW_NORMAL, //指定字体磅数
  17. FALSE, //是不是斜体
  18. FALSE, //加不加下划线
  19. 0, //指定是否是字体字符突出
  20. ANSI_CHARSET, //指定字体的字符集
  21. OUT_DEFAULT_PRECIS, //指定所需的输出精度
  22. CLIP_DEFAULT_PRECIS, //指定所需的剪贴精度
  23. DEFAULT_QUALITY, //指示字体的输出质量
  24. DEFAULT_PITCH | FF_SWISS, //指定字体的间距和家族
  25. _T("宋体") //指定字体的字样名称
  26. );
  27. m_clrBK = RGB(255, 255, 255);
  28. m_clrFont = RGB(0, 0, 0);
  29. }
  30. HeaderCtrlEx::~HeaderCtrlEx()
  31. {
  32. if (m_pFont && s_bDeleteFont)
  33. {
  34. m_pFont->DeleteObject();
  35. delete m_pFont;
  36. m_pFont = NULL;
  37. }
  38. }
  39. void HeaderCtrlEx::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
  40. {
  41. LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
  42. // TODO: Add your control notification handler code here
  43. *pResult = CDRF_DODEFAULT;
  44. if (pNMCD->dwDrawStage == CDDS_PREPAINT)
  45. {
  46. CDC* pDC = CDC::FromHandle(pNMCD->hdc);
  47. CRect rect(0, 0, 0, 0);
  48. GetClientRect(&rect);
  49. pDC->FillSolidRect(&rect, m_clrBK);
  50. *pResult = CDRF_NOTIFYITEMDRAW;
  51. }
  52. else if (pNMCD->dwDrawStage == CDDS_ITEMPREPAINT)
  53. {
  54. HDITEM hditem;
  55. TCHAR buffer[MAX_PATH] = { 0 };
  56. SecureZeroMemory(&hditem, sizeof(HDITEM));
  57. hditem.mask = HDI_TEXT;
  58. hditem.pszText = buffer;
  59. hditem.cchTextMax = MAX_PATH;
  60. GetItem(pNMCD->dwItemSpec, &hditem);
  61. CDC* pDC = CDC::FromHandle(pNMCD->hdc);
  62. pDC->SetTextColor(m_clrFont);
  63. pDC->SetBkColor(RGB(255, 255, 255));
  64. pDC->SetBkMode(TRANSPARENT);
  65. CFont* pOldFont = pDC->SelectObject(m_pFont);
  66. CString str(buffer);
  67. CRect rect = pNMCD->rc;
  68. CPen pen;
  69. pen.CreatePen(PS_SOLID, 1, RGB(240, 240, 240));
  70. CPen* pOldPen = pDC->SelectObject(&pen);
  71. pDC->Rectangle(&rect);
  72. pDC->SelectObject(pOldPen);
  73. pen.DeleteObject();
  74. //rect.OffsetRect(6, 0);
  75. pDC->DrawText(str, CRect(rect), DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  76. pDC->SelectObject(pOldFont);
  77. pDC->Detach();
  78. *pResult = CDRF_SKIPDEFAULT;
  79. }
  80. }
  81. LRESULT HeaderCtrlEx::OnLayout(WPARAM wParam, LPARAM lParam)
  82. {
  83. LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
  84. HD_LAYOUT& hdl = *(HD_LAYOUT*)lParam;
  85. RECT* prc = hdl.prc; // The table list rectangle
  86. WINDOWPOS* pwpos = hdl.pwpos; // The table header rectangle
  87. int nHeight = (int)(pwpos->cy * 1.3);
  88. pwpos->cy = nHeight; // New table header height
  89. //pwpos->x += 3;
  90. prc->top = nHeight; // Decreases the table list height on the table header height
  91. return lResult;
  92. }
  93. void HeaderCtrlEx::SetHeaderCtrlFont(CFont* pFont)
  94. {
  95. if (m_pFont && s_bDeleteFont)
  96. {
  97. m_pFont->DeleteObject();
  98. delete m_pFont;
  99. m_pFont = NULL;
  100. }
  101. m_pFont = pFont;
  102. s_bDeleteFont = FALSE;
  103. }

三、CListEdit 实现双击编辑

CListEdit.h

  1. #pragma once
  2. #include <afxcmn.h>
  3. typedef std::function<void()> CallBackFunc;
  4. class CListEdit : public CEdit
  5. {
  6. friend class CListCtrlEx;
  7. DECLARE_DYNAMIC(CListEdit)
  8. public:
  9. CListEdit();
  10. virtual ~CListEdit();
  11. void SetCallBackFunc(const CallBackFunc& func) { m_updataListfunc = func; }
  12. protected:
  13. DECLARE_MESSAGE_MAP()
  14. afx_msg void OnKillFocus(CWnd* pNewWnd);
  15. virtual BOOL PreTranslateMessage(MSG* pMsg);
  16. private:
  17. CFont* m_pFont; //if NULL, same as list
  18. CallBackFunc m_updataListfunc;
  19. void SetListEditCtrlFont(CFont* pFont);
  20. };

CListEdit.cpp

  1. #include "stdafx.h"
  2. #include "CListEdit.h"
  3. //static BOOL s_bDeleteFont = TRUE;
  4. static BOOL s_bUpdataList = TRUE;
  5. IMPLEMENT_DYNAMIC(CListEdit, CEdit)
  6. BEGIN_MESSAGE_MAP(CListEdit, CEdit)
  7. ON_WM_KILLFOCUS()
  8. END_MESSAGE_MAP()
  9. CListEdit::CListEdit()
  10. {
  11. m_pFont = NULL;
  12. }
  13. CListEdit::~CListEdit()
  14. {
  15. }
  16. void CListEdit::OnKillFocus(CWnd* pNewWnd)
  17. {
  18. this->ShowWindow(SW_HIDE);
  19. if(s_bUpdataList) m_updataListfunc();
  20. s_bUpdataList = TRUE;
  21. }
  22. BOOL CListEdit::PreTranslateMessage(MSG* pMsg)
  23. {
  24. if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN))
  25. {
  26. if (pMsg->wParam == VK_ESCAPE)
  27. {
  28. s_bUpdataList = FALSE;
  29. this->ShowWindow(SW_HIDE);
  30. }
  31. else if (pMsg->wParam == VK_RETURN)
  32. {
  33. this->ShowWindow(SW_HIDE);
  34. m_updataListfunc();
  35. }
  36. return TRUE;
  37. }
  38. return CEdit::PreTranslateMessage(pMsg);
  39. }
  40. void CListEdit::SetListEditCtrlFont(CFont* pFont)
  41. {
  42. m_pFont = pFont;
  43. }

四、HeaderCtrlEx、CListEdit应用到List Ctrl中

CListCtrlEx.h

  1. #pragma once
  2. class HeaderCtrlEx;
  3. class CListEdit;
  4. class CListCtrlEx : public CListCtrl
  5. {
  6. DECLARE_DYNAMIC(CListCtrlEx)
  7. public:
  8. CListCtrlEx();
  9. virtual ~CListCtrlEx();
  10. public:
  11. //设置 list ctrl 选中时的颜色
  12. void SetSelectedColor(COLORREF clrSelected);
  13. //设置双击编辑框字体
  14. void SetListEditFont(CFont* pFont);
  15. //设置表头字体
  16. void SetHeaderFont(CFont* pFont);
  17. //设置表头背景颜色
  18. void SetHeaderBKColor(COLORREF clrBK);
  19. //设置表头字体颜色
  20. void SetHeaderFontColor(COLORREF clrFont);
  21. //设置是否可双击编辑
  22. void SetListEdit(BOOL bListEdit = TRUE);
  23. protected:
  24. DECLARE_MESSAGE_MAP()
  25. afx_msg void OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult);
  26. afx_msg BOOL OnNMDBClick(NMHDR* pNMHDR, LRESULT* pResult);
  27. virtual void PreSubclassWindow();
  28. private:
  29. HeaderCtrlEx* m_pHeaderCtrl;
  30. CListEdit* m_pListEditCtrl;
  31. int m_nRow;
  32. int m_nCol;
  33. BOOL m_bListEdit;
  34. private:
  35. void RegisterHeaderCtrl();
  36. void UpdataListCallBackFunc();
  37. };

CListCtrlEx.cpp

  1. #include "stdafx.h"
  2. #include "CListCtrlEx.h"
  3. #include "HeaderCtrlEx.h"
  4. #include "CListEdit.h"
  5. IMPLEMENT_DYNAMIC(CListCtrlEx, CListCtrl)
  6. static COLORREF s_clrSelected = RGB(0, 120, 215); //如果用成员变量, OnNMCustomdraw会把成员变量的颜色变成0
  7. BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
  8. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CListCtrlEx::OnNMCustomdraw)
  9. ON_NOTIFY_REFLECT_EX(NM_DBLCLK, &CListCtrlEx::OnNMDBClick)
  10. /*
  11. 注意:
  12. ON_NOTIFY_REFLECT 控制自己处理消息
  13. ON_NOTIFY_REFLECT_EX 如果控件消息响应函数 OnNMDBClick 返回 FALSE,消息由父窗口继续处理
  14. */
  15. END_MESSAGE_MAP()
  16. //CustomDraw to change selected item color
  17. void CListCtrlEx::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult)
  18. {
  19. NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
  20. *pResult = CDRF_DODEFAULT;
  21. switch (pLVCD->nmcd.dwDrawStage)
  22. {
  23. case CDDS_PREPAINT:
  24. *pResult = CDRF_NOTIFYITEMDRAW;
  25. break;
  26. case CDDS_ITEMPREPAINT:
  27. *pResult = CDRF_NOTIFYSUBITEMDRAW;
  28. break;
  29. case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
  30. {
  31. if ((GetItemState(pLVCD->nmcd.dwItemSpec, LVIS_SELECTED) & LVIS_SELECTED))
  32. {
  33. pLVCD->nmcd.uItemState = CDIS_DEFAULT;
  34. pLVCD->clrTextBk = s_clrSelected;
  35. pLVCD->clrText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  36. *pResult = CDRF_NEWFONT;
  37. }
  38. break;
  39. }
  40. default:
  41. break;
  42. }
  43. }
  44. BOOL CListCtrlEx::OnNMDBClick(NMHDR* pNMHDR, LRESULT* pResult)
  45. {
  46. if (!m_bListEdit) return FALSE;
  47. LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
  48. // TODO: 在此添加控件通知处理程序代码
  49. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  50. CRect rect;
  51. m_nRow = pNMListView->iItem;//获得选中的行
  52. m_nCol = pNMListView->iSubItem;//获得选中列
  53. if (m_nRow != -1 && m_nCol != -1 && m_pListEditCtrl)
  54. {
  55. if (pNMListView->iSubItem != 0)
  56. {
  57. this->GetSubItemRect(m_nRow, m_nCol, LVIR_LABEL, rect);
  58. BOOL bCreat = TRUE;
  59. if (!IsWindow(m_pListEditCtrl->m_hWnd))
  60. {
  61. bCreat = m_pListEditCtrl->Create(WS_BORDER | WS_CHILD | WS_VISIBLE, rect, this, 1);
  62. }
  63. if (bCreat)
  64. {
  65. m_pListEditCtrl->SetParent(this);
  66. m_pListEditCtrl->MoveWindow(&rect);
  67. CFont* pFont = NULL;
  68. if (!m_pListEditCtrl->m_pFont)
  69. {
  70. pFont = this->GetFont(); //if not set, same as list
  71. }
  72. else
  73. {
  74. pFont = m_pListEditCtrl->m_pFont;
  75. }
  76. if(pFont) m_pListEditCtrl->SetFont(pFont);
  77. m_pListEditCtrl->SetWindowText(this->GetItemText(m_nRow, m_nCol));
  78. m_pListEditCtrl->ShowWindow(SW_SHOW);//显示Edit控件;
  79. m_pListEditCtrl->SetFocus();//设置Edit焦点
  80. m_pListEditCtrl->ShowCaret();//显示光标
  81. m_pListEditCtrl->SetSel(0, -1);//将光标移动到最后
  82. }
  83. }
  84. }
  85. *pResult = 0;
  86. return TRUE;
  87. }
  88. void CListCtrlEx::PreSubclassWindow()
  89. {
  90. CHeaderCtrl* pHeader = GetHeaderCtrl();
  91. if (pHeader && m_pHeaderCtrl) { VERIFY(m_pHeaderCtrl->SubclassWindow(pHeader->m_hWnd)); }
  92. CListCtrl::PreSubclassWindow();
  93. }
  94. CListCtrlEx::CListCtrlEx()
  95. {
  96. m_pHeaderCtrl = new HeaderCtrlEx;
  97. m_pListEditCtrl = new CListEdit;
  98. CallBackFunc func = std::bind(&CListCtrlEx::UpdataListCallBackFunc, this);
  99. m_pListEditCtrl->SetCallBackFunc(func);
  100. m_bListEdit = FALSE;
  101. }
  102. CListCtrlEx::~CListCtrlEx()
  103. {
  104. if (m_pHeaderCtrl)
  105. {
  106. delete m_pHeaderCtrl;
  107. m_pHeaderCtrl = NULL;
  108. }
  109. if (m_pListEditCtrl)
  110. {
  111. delete m_pListEditCtrl;
  112. m_pListEditCtrl = NULL;
  113. }
  114. }
  115. void CListCtrlEx::SetSelectedColor(COLORREF clrSelected)
  116. {
  117. s_clrSelected = clrSelected;
  118. }
  119. void CListCtrlEx::SetListEditFont(CFont* pFont)
  120. {
  121. if (m_pListEditCtrl) m_pListEditCtrl->SetListEditCtrlFont(pFont);
  122. }
  123. void CListCtrlEx::SetHeaderFont(CFont* pFont)
  124. {
  125. if (m_pHeaderCtrl) m_pHeaderCtrl->SetHeaderCtrlFont(pFont);
  126. }
  127. void CListCtrlEx::SetHeaderBKColor(COLORREF clrBK)
  128. {
  129. if (m_pHeaderCtrl) m_pHeaderCtrl->m_clrBK = clrBK;
  130. }
  131. void CListCtrlEx::SetHeaderFontColor(COLORREF clrFont)
  132. {
  133. if (m_pHeaderCtrl) m_pHeaderCtrl->m_clrFont = clrFont;
  134. }
  135. void CListCtrlEx::SetListEdit(BOOL bListEdit)
  136. {
  137. m_bListEdit = bListEdit;
  138. }
  139. void CListCtrlEx::UpdataListCallBackFunc()
  140. {
  141. CString str;
  142. if (m_pListEditCtrl)
  143. {
  144. m_pListEditCtrl->GetWindowText(str);
  145. }
  146. if (m_pListEditCtrl)
  147. {
  148. this->SetItemText(m_nRow, m_nCol, str);
  149. }
  150. }
  151. void CListCtrlEx::RegisterHeaderCtrl()
  152. {
  153. CHeaderCtrl* pHeader = GetHeaderCtrl();
  154. if (pHeader && m_pHeaderCtrl) { VERIFY(m_pHeaderCtrl->SubclassWindow(pHeader->m_hWnd)); }
  155. }

五、实战

  1. /***********************.h***********************/
  2. class CMyDialog: public CDialog
  3. {
  4. DECLARE_DYNAMIC(CMyDialog)
  5. public:
  6. CMyDialog(CWnd* pParent = nullptr); // 标准构造函数
  7. virtual ~CMyDialog();
  8. // 对话框数据
  9. #ifdef AFX_DESIGN_TIME
  10. enum { IDD = IDD_DIALOG_SAFETYAPPOPTION_CHAPTER2LIST };
  11. #endif
  12. protected:
  13. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
  14. DECLARE_MESSAGE_MAP()
  15. public:
  16. virtual BOOL OnInitDialog();
  17. }
  18. /***********************.cpp***********************/
  19. void CMyDialog::DoDataExchange(CDataExchange* pDX)
  20. {
  21. CDialog::DoDataExchange(pDX);
  22. DDX_Control(pDX, IDC_LIST, m_list);
  23. }
  24. BOOL CMyDialog::OnInitDialog()
  25. {
  26. CDialog::OnInitDialog();
  27. LONG lStyle;
  28. lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口style
  29. lStyle &= ~LVS_TYPEMASK; //清除显示方式位
  30. lStyle |= LVS_REPORT; //设置style
  31. lStyle |= LVS_SHOWSELALWAYS; //设置style
  32. //lStyle |= LVS_NOCOLUMNHEADER;
  33. //lStyle |= LVS_SINGLESEL; //设置style
  34. SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style
  35. DWORD dwStyle = m_list.GetExtendedStyle();
  36. dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl)
  37. dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl)
  38. dwStyle |= LVS_EX_CHECKBOXES;
  39. dwStyle |= LVS_EX_HEADERDRAGDROP;
  40. dwStyle |= LVS_EX_HEADERINALLVIEWS;
  41. m_list.SetExtendedStyle(dwStyle); //设置扩展风格
  42. m_pFont->CreateFont(12, //以逻辑单位方式指定字体的高度
  43. 0, //以逻辑单位方式指定字体中字符的平均宽度
  44. 0, //指定偏离垂线和X轴在显示面上的夹角(单位:0.1度)
  45. 0, //指定字符串基线和X轴之间的夹角(单位:0.1度)
  46. FW_BOLD, //指定字体磅数
  47. FALSE, //是不是斜体
  48. FALSE, //加不加下划线
  49. 0, //指定是否是字体字符突出
  50. ANSI_CHARSET, //指定字体的字符集
  51. OUT_DEFAULT_PRECIS, //指定所需的输出精度
  52. CLIP_DEFAULT_PRECIS, //指定所需的剪贴精度
  53. DEFAULT_QUALITY, //指示字体的输出质量
  54. DEFAULT_PITCH | FF_SWISS, //指定字体的间距和家族
  55. _T("宋体") //指定字体的字样名称
  56. );
  57. m_list.SetHeaderFont(m_pFont);
  58. m_list.SetListEdit();
  59. m_list.InsertColumn(0, TEXT("col1"), LVCFMT_CENTER, 60);
  60. m_list.InsertColumn(1, TEXT("col2"), LVCFMT_CENTER, rect.Width() - 60);
  61. m_list.SetItemText(0, 0, TEXT("row1 col1"));
  62. m_list.SetItemText(0, 1, TEXT("row1 col2"));
  63. return TRUE; // return TRUE unless you set the focus to a control
  64. // 异常: OCX 属性页应返回 FALSE
  65. }

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

闽ICP备14008679号