1.前言
最近发现读者对我的mfc美化的专栏比较感兴趣,因此在这里进行续写,这里我会计划写几个连续的篇章,包括对MFC按钮的美化,菜单栏的美化,标题栏的美化,list列表的美化,直到最后形成一个完整的成品效果。
2.最终效果展示
3.思路分析
1.编写mfc的list的派生类对 列表进行重绘
2.list和其他的空间有些区别,要分别对标题栏,和内容栏进行重绘。
4.实现的过程
1.在mfc界面,增加空间list
2.修改list的属性
边框:false
静态边缘:false
视图:Reporte
无滚动:true
3.声明list的变量
public: CListCtrlComboEx m_list;
4.OnInitDialog 里面的核心代码
BOOL CCustomListDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 //LIST CRect rect; m_list.GetClientRect(&rect); DWORD dwStyle = m_list.GetExtendedStyle(); //dwStyle = (dwStyle | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); dwStyle |= dwStyle | LVS_REPORT & ~LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_SHOWSELALWAYS | LVS_EX_HEADERDRAGDROP; m_list.SetExtendedStyle(dwStyle); //m_list.SetBo m_list.SetItemHeight(25); m_list.SetFontSize(17); m_list.InsertColumn(0, _T("编号"), LVCFMT_CENTER, (rect.Width() / 3) + 30, 0); m_list.InsertColumn(1, _T("菜谱"), LVCFMT_CENTER, (rect.Width() - (rect.Width() / 3) - 30), 1); m_list.InsertColumn(2, _T(""), LVCFMT_CENTER, 1000, 2); m_list.InsertItem(0, _T("1")); m_list.InsertItem(1, _T("2")); m_list.InsertItem(2, _T("3")); m_list.InsertItem(3, _T("4")); m_list.InsertItem(4, _T("5")); m_list.InsertItem(5, _T("6")); m_list.InsertItem(6, _T("7")); m_list.InsertItem(7, _T("8")); m_list.InsertItem(8, _T("9")); m_list.InsertItem(9, _T("")); m_list.InsertItem(10, _T("")); m_list.InsertItem(11, _T("")); // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE }
5.list重写的对应封装代码
BitMark.h
#pragma once #define BITMARK_MAX (2500) #define BITMARK_ROWS_DEF (100) #define BITMARK_COLS_DEF (20) class BitMark { public: BitMark(void); virtual ~BitMark(void); virtual BOOL Seek(DWORD uRows, DWORD uCols); virtual void Set(DWORD uRow, DWORD uCol, BOOL bValid); virtual BOOL IsValid(DWORD uRow, DWORD uCol); virtual void Clear(); protected: DWORD m_uRows, m_uCols; BYTE m_aBit[BITMARK_MAX]; };
BitMark.cpp
#include "pch.h" #include "BitMark.h" #ifdef _AFX #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static const char THIS_FILE[] = __FILE__; #endif #endif BitMark::BitMark(void) { ZeroMemory(m_aBit, BITMARK_MAX); } BitMark::~BitMark(void) { } BOOL BitMark::Seek(DWORD uRows, DWORD uCols) { if((uRows*uCols) > BITMARK_MAX) return FALSE; m_uRows = uRows; m_uCols = uCols; return TRUE; } void BitMark::Set(DWORD uRow, DWORD uCol, BOOL bValid) { if((uRow*m_uCols + uCol) >= BITMARK_MAX) return; m_aBit[uRow*m_uCols+ uCol] = ( bValid ? 1 : 0 ); } BOOL BitMark::IsValid(DWORD uRow, DWORD uCol) { BOOL bValid =FALSE; if((uRow*m_uCols + uCol) >= BITMARK_MAX) return FALSE; if(0 != m_aBit[uRow*m_uCols + uCol]) bValid = TRUE; return bValid; } void BitMark::Clear() { ZeroMemory(m_aBit, BITMARK_MAX); }
HeaderCtrlEx.h
#pragma once #include class HeaderCtrlEx : public CHeaderCtrl { DECLARE_DYNAMIC(HeaderCtrlEx) protected: DECLARE_MESSAGE_MAP() void OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult); LRESULT OnLayout(WPARAM wParam, LPARAM lParam); afx_msg BOOL OnEraseBkgnd(CDC* pDC); };
HeaderCtrlEx.cpp
#include "pch.h" #include "HeaderCtrlEx.h" IMPLEMENT_DYNAMIC(HeaderCtrlEx, CHeaderCtrl) BEGIN_MESSAGE_MAP(HeaderCtrlEx, CHeaderCtrl) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &HeaderCtrlEx::OnNMCustomdraw) ON_MESSAGE(HDM_LAYOUT, &HeaderCtrlEx::OnLayout) ON_WM_ERASEBKGND() END_MESSAGE_MAP() void HeaderCtrlEx::OnNMCustomdraw(NMHDR* pNMHDR, LRESULT* pResult) { // ref: https://stackoverflow.com/questions/28766659/changing-mfc-list-control-header-color LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR); // TODO: Add your control notification handler code here *pResult = CDRF_DODEFAULT; if (pNMCD->dwDrawStage == CDDS_PREPAINT) { CDC* pDC = CDC::FromHandle(pNMCD->hdc); CRect rect(0, 0, 0, 0); GetClientRect(&rect); //pDC->FillSolidRect(&rect, RGB(215, 235, 226)); pDC->FillSolidRect(&rect, RGB(30, 34, 39)); *pResult = CDRF_NOTIFYITEMDRAW; } else if (pNMCD->dwDrawStage == CDDS_ITEMPREPAINT) { HDITEM hditem; TCHAR buffer[MAX_PATH] = { 0 }; SecureZeroMemory(&hditem, sizeof(HDITEM)); hditem.mask = HDI_TEXT; hditem.pszText = buffer; hditem.cchTextMax = MAX_PATH; GetItem(pNMCD->dwItemSpec, &hditem); CDC* pDC = CDC::FromHandle(pNMCD->hdc); //pDC->SetTextColor(RGB(0, 0, 0)); pDC->SetTextColor(RGB(255, 255, 255)); //pDC->SetBkColor(RGB(215, 235, 226)); pDC->SetBkColor(RGB(30, 34, 39)); //CFont m_pFont; //m_pFont.CreateFont(ConvertWithDPIRatio(31), // 0, 0, 0, FW_MEDIUM, // FALSE, FALSE, // 0, // ANSI_CHARSET, // nCharSet // OUT_DEFAULT_PRECIS, // nOutPrecision // CLIP_DEFAULT_PRECIS, // nClipPrecision // DEFAULT_QUALITY, // nQuality // DEFAULT_PITCH | FF_SWISS, _T("Arial")); //pDC->SelectObject(m_pFont); CString str(buffer); CRect rect = pNMCD->rc; rect.OffsetRect(6, 0); pDC->DrawText(str, CRect(rect), DT_SINGLELINE | DT_VCENTER); *pResult = CDRF_SKIPDEFAULT; } } /* * Describe: Change the height of table header * Author : Canliang Wu * Date : 2021/12/15 */ LRESULT HeaderCtrlEx::OnLayout(WPARAM wParam, LPARAM lParam) { LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam); HD_LAYOUT& hdl = *(HD_LAYOUT*)lParam; RECT* prc = hdl.prc; // The table list rectangle WINDOWPOS* pwpos = hdl.pwpos; // The table header rectangle int nHeight = (int)(pwpos->cy * 1.3); pwpos->cy = nHeight; // New table header height //pwpos->x += 3; prc->top = nHeight; // Decreases the table list height on the table header height return lResult; } BOOL HeaderCtrlEx::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default //return CListCtrl::OnEraseBkgnd(pDC); return FALSE; }
ListControlDefine.h
#pragma once #define ListCtrlMask_Rows (500) #define ListCtrlMask_Cols (20) #define ListCtrlMask_Max (ListCtrlMask_Rows * ListCtrlMask_Cols) typedef struct ListCtrlMask { BYTE Bit[ListCtrlMask_Max]; } ListCtrlMask;
ListControlDefine.cpp
#include "pch.h" #include "ListControlDefine.h"
ListCtrlComboEx.h
#if !defined(AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_) #define AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // ListCtrlComboEx.h : header file #include "ListControlDefine.h" #include "BitMark.h" #include "HeaderCtrlEx.h" #include #define cgCComboBox CComboBox //you can use yourself defined combobox / // CListCtrlComboEx window #include using namespace std; struct stEditAble { int nRow; int nCol; }; struct stComboAble { int nRow; int nCol; cgCComboBox *pCombo; }; #define IDCB_ONLISTCONTROL 9001 #define CListCtrlComboEx_ColumnMax (200) class CListCtrlComboEx : public CListCtrl { // Construction public: CListCtrlComboEx(); public: UINT m_nMsgComboSelChange; BitMark m_oBm; int m_nRowDblClk; int m_nColDblClk; int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1); void SetItemWarning(int nItem, int nSubItem, BOOL bValid); int m_anFormat[CListCtrlComboEx_ColumnMax]; void CreateComboBox(UINT nMsgComboSelChange); void CreateEditBox(); CComboBox* GetCombo(); protected: CComboBox* m_pcbListCtrl; HeaderCtrlEx m_HeaderCtrl; protected: vector m_EditAbleArray; vector m_ComboAbleArray; int m_iRow; int m_iCol; CEdit *m_pEdit; int m_iHeight; CFont m_oFont; // Attributes public: void SetEditAble(int nRow,int nCol); void SetComboAble(int nRow,int nCol,cgCComboBox *pCombo); void SetItemHeight(int nHeight); COLORREF GetTableItemColor(int nRow, int nCol, COLORREF clrDef); void ClearAllAbles(); BOOL GetCellRect(int nRow, int nCol, CRect& rect); void SetFontSize(int cHeight = 18); BOOL m_bFontSeted; // Operations public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CListCtrlComboEx) //}}AFX_VIRTUAL // Implementation public: virtual ~CListCtrlComboEx(); // Generated message map functions protected: BOOL IsEditAble(int nRow,int nCol); BOOL IsComboAble(int nRow,int nCol); virtual void PreSubclassWindow(); LPCTSTR MakeShortString(CDC *pDC,LPCTSTR lpszLong,int nColumnLen,int nOffset); protected: //{{AFX_MSG(CListCtrlComboEx) // NOTE - the ClassWizard will add and remove member functions here. virtual afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); virtual afx_msg void OnLButtonDown(UINT nFlags, CPoint point); virtual afx_msg BOOL OnHeaderEndResize(UINT, NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnCbnKillfocusCombo(); afx_msg void OnCbnSelchangeCombo(); afx_msg BOOL OnEraseBkgnd(CDC* pDC); //}}AFX_MSG DECLARE_DYNAMIC(CListCtrlComboEx) DECLARE_MESSAGE_MAP() public: afx_msg void OnPaint(); public: afx_msg BOOL OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult); }; / //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_LISTCTRLCOMBOEX_H__CF78F101_D071_46A3_BCA8_CB30861448F1__INCLUDED_)
ListCtrlComboEx.cpp
// ListCtrlComboEx.cpp : implementation file // #include "pch.h" //#include "cgListComboTest.h" #include "ListCtrlComboEx.h" //#include "resource.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif / // CListCtrlComboEx CListCtrlComboEx::CListCtrlComboEx() { m_pcbListCtrl = NULL; m_nRowDblClk = 0; m_nColDblClk = 0; m_bFontSeted = FALSE; m_EditAbleArray.clear(); m_ComboAbleArray.clear(); m_iRow = -1; m_iCol = -1; m_iHeight = 0; m_pEdit = NULL; m_nMsgComboSelChange = 0; ZeroMemory(&m_anFormat, sizeof(m_anFormat)); //m_pListCtrlMask = NULL; } CListCtrlComboEx::~CListCtrlComboEx() { if(m_pcbListCtrl) { m_pcbListCtrl->DestroyWindow(); delete m_pcbListCtrl; m_pcbListCtrl = NULL; } } int CListCtrlComboEx::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat /*= LVCFMT_LEFT*/, int nWidth /*= -1*/, int nSubItem /*= -1*/) { if(nCol>=0) m_anFormat[nCol] = nFormat; return CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat, nWidth, nSubItem); } void CListCtrlComboEx::SetItemWarning(int nItem, int nSubItem, BOOL bValid) { //return; m_oBm.Set(nItem, nSubItem, bValid); } void CListCtrlComboEx::CreateComboBox(UINT nMsgComboSelChange) { m_nMsgComboSelChange = nMsgComboSelChange; CFont* cf = GetFont(); CComboBox *pCombo; pCombo = new CComboBox(); CRect rect; GetCellRect(0,1,rect); pCombo->Create(WS_CHILD/*|WS_VISIBLE*/|CBS_AUTOHSCROLL|CBS_DROPDOWNLIST,rect,(CWnd*)this, IDCB_ONLISTCONTROL); pCombo->SetFont(cf); m_pcbListCtrl = pCombo; } CComboBox* CListCtrlComboEx::GetCombo() { return m_pcbListCtrl; } COLORREF CListCtrlComboEx::GetTableItemColor(int nRow, int nCol, COLORREF clrDef) { COLORREF clr; clr = clrDef; //RGB(0, 0, 0); //if((nRow*nCol) >= ListCtrlMask_Max) // return clr; //if(!m_pListCtrlMask) // return clr; //if(m_pListCtrlMask->Bit[nRow*ListCtrlMask_Cols + nCol]) // clr = RGB(255, 0, 0); if(m_oBm.IsValid(nRow, nCol)) clr = RGB(255, 0, 0); //if(myutil::GetBit(m_oWarningBitMark.bit[nRow], nCol)) //{ // clr = RGB(255, 0, 0); //} //if(myutil::GetBit(theApp.m_pYmVoltTblRow[nRow].upper_warning_bit, nCol)) //{ // clr = RGB(255, 0, 0); //} //if(myutil::GetBit(theApp.m_pYmVoltTblRow[nRow].lower_warning_bit, nCol)) //{ // clr = RGB(255, 0, 0); //} //if(m_oVoltTbl.v_row[nRow].v[nCol] > m_nUpper) //{ // clr = RGB(255, 0, 0); //} //if(m_oVoltTbl.v_row[nRow].v[nCol] nmcd.dwItemSpec; pResult = CDRF_DODEFAULT; /* // Allow column-traits to perform their custom drawing if (pLVCD->nmcd.dwDrawStage & CDDS_SUBITEM) { CComboBox* pCombo = GetCellColumnTrait(nRow, pLVCD->iSubItem); if (pCombo != NULL) return; // Everything is handled by the column-trait } // Always perform drawing of cell-focus rectangle switch (pLVCD->nmcd.dwDrawStage) { case CDDS_PREPAINT: *pResult |= CDRF_NOTIFYITEMDRAW; break; // Before painting a row case CDDS_ITEMPREPAINT: { *pResult |= CDRF_NOTIFYPOSTPAINT; // Ensure row-traits gets called *pResult |= CDRF_NOTIFYSUBITEMDRAW; // Ensure column-traits gets called } break; // After painting the entire row case CDDS_ITEMPOSTPAINT: { ; } break; }*/ } BOOL CListCtrlComboEx::OnHeaderEndResize(UINT, NMHDR* pNMHDR, LRESULT* pResult) { int size = m_ComboAbleArray.size(); int i; for(i=0;iMoveWindow(rect); pCombo->SetWindowPos(NULL, // not relative to any other Windows 0, 0, // TopLeft corner doesn't change rect.Width(), (pCombo->GetCount()+1)*rect.Height(), // existing width, new height SWP_NOMOVE | SWP_NOZORDER // don't move box or change z-ordering. ); pCombo->ShowWindow(TRUE); } Invalidate(FALSE); return FALSE; } void CListCtrlComboEx::OnCbnKillfocusCombo() { int size = m_ComboAbleArray.size(); int i; for(i=0;iShowWindow(FALSE); } Invalidate(FALSE); } void CListCtrlComboEx::OnCbnSelchangeCombo() { CWnd* P = this->GetParent(); if(m_nMsgComboSelChange) P->PostMessage(m_nMsgComboSelChange); int size = m_ComboAbleArray.size(); int i; for(i=0;iShowWindow(FALSE); } Invalidate(FALSE); } void CListCtrlComboEx::SetItemHeight(int nHeight) { m_iHeight = nHeight; CRect rcWin; GetWindowRect(&rcWin); WINDOWPOS wp; wp.hwnd = m_hWnd; wp.cx = rcWin.Width(); wp.cy = rcWin.Height(); wp.flags = SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER; SendMessage(WM_WINDOWPOSCHANGED,0,(LPARAM)&wp); } BOOL CListCtrlComboEx::GetCellRect(int nRow, int nCol,CRect& rect) { if (GetSubItemRect(nRow, nCol, LVIR_BOUNDS, rect)==FALSE) return FALSE; CRect colRect; if (GetHeaderCtrl()->GetItemRect(nCol, colRect)==FALSE) return FALSE; if (nCol==0) { // Fix bug where LVIR_BOUNDS gives the entire row for nCol==0 CRect labelRect; if (GetSubItemRect(nRow, nCol, LVIR_LABEL, labelRect)==FALSE) return FALSE; rect.right = labelRect.right; rect.left = labelRect.right - colRect.Width(); } else { // Fix bug when width is smaller than subitem image width rect.right = rect.left + colRect.Width(); } return TRUE; } void CListCtrlComboEx::SetFontSize(int cHeight) { if(m_bFontSeted) return; m_bFontSeted = TRUE; m_oFont.CreateFont( cHeight, // nHeight 0, // nWidth 0, // nEscapement 0, // nOrientation FW_NORMAL, // nWeight FALSE, // bItalic FALSE, // bUnderline 0, // cStrikeOut ANSI_CHARSET, // nCharSet OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily _T("Arial")); // lpszFacename SetFont(&m_oFont, TRUE); } BOOL CListCtrlComboEx::IsEditAble(int nRow,int nCol) { int i; int size = m_EditAbleArray.size(); if(size > 0) { for(i=0;i 0) { for(i=0;iSetWindowPos(NULL, // not relative to any other windows 0, 0, // TopLeft corner doesn't change rect.Width(), (pCombo->GetCount()+1)*rect.Height(), // existing width, new height SWP_NOMOVE | SWP_NOZORDER // don't move box or change z-ordering. ); pCombo->ShowWindow(TRUE); pCombo->SetFocus(); } void CListCtrlComboEx::OnLButtonDown(UINT nFlags, CPoint point) { int nRow, nCol; if(m_pEdit != NULL) { CString str; m_pEdit->GetWindowText(str); SetItemText(m_iRow,m_iCol,str); m_iRow = -1; m_iCol = -1; delete m_pEdit; // m_pEdit->PostMessage(WM_CLOSE); m_pEdit = NULL; } LVHITTESTINFO lvhti = {0}; lvhti.pt = point; nRow = ListView_SubItemHitTest(m_hWnd, &lvhti); // SubItemHitTest is non-const nCol = lvhti.iSubItem; if (!(lvhti.flags & LVHT_ONITEM)) nRow = -1; if(nRow == -1 || nCol == -1) { CListCtrl::OnLButtonDown(nFlags, point); return; } if(IsEditAble(nRow,nCol)) { m_iRow = nRow; m_iCol = nCol; CRect rect; GetCellRect(nRow,nCol,rect); m_pEdit = new CEdit(); m_pEdit->Create(WS_CHILD|ES_LEFT|ES_AUTOHSCROLL,rect,this,0); CString str; str = GetItemText(nRow,nCol); m_pEdit->SetWindowText(str); m_pEdit->ShowWindow(SW_SHOW); m_pEdit->SetFocus(); return; } CListCtrl::OnLButtonDown(nFlags,point); } void CListCtrlComboEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { if(m_iHeight>0) { lpMeasureItemStruct->itemHeight = m_iHeight; } } void CListCtrlComboEx::PreSubclassWindow() { ModifyStyle(0,LVS_OWNERDRAWFIXED); //CListCtrl::PreSubclassWindow(); CHeaderCtrl* pHeader = GetHeaderCtrl(); if (pHeader != NULL) { VERIFY(m_HeaderCtrl.SubclassWindow(pHeader->m_hWnd)); } CListCtrl::PreSubclassWindow(); } void CListCtrlComboEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { int nItem = lpDrawItemStruct->itemID; if(nItem == -1) return; CRect rcCol = lpDrawItemStruct->rcItem; CString sText; CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); int nOldDCMode = pDC->SaveDC(); LVITEM item; item.iItem = nItem; item.iSubItem = 0; item.mask = LVIF_IMAGE|LVIF_STATE; item.stateMask = 0xFFFF; GetItem(&item); BOOL bSelected = item.state & LVIS_SELECTED; COLORREF color = RGB(30, 34, 39); if(bSelected) { pDC->SetBkColor(RGB(30, 34, 39)); pDC->SetTextColor(RGB(255,255,255)/*::GetSysColor(COLOR_HIGHLIGHTTEXT)*//*GetTableItemColor(nItem, item.iSubItem)*/); color = RGB(30, 34, 39); } else { pDC->SetBkColor(RGB(30, 34, 39)); pDC->SetTextColor(RGB(255,255,255)/*::GetSysColor(COLOR_WINDOWTEXT)*//*GetTableItemColor(nItem, item.iSubItem)*/); } LV_COLUMN lvc; lvc.mask = LVCF_FMT|LVCF_WIDTH; rcCol.right = rcCol.left; for(int nCol=0;GetColumn(nCol,&lvc);nCol++) { rcCol.left = rcCol.right; rcCol.right = rcCol.left + GetColumnWidth(nCol); HPEN hOldPen = (HPEN)::SelectObject(lpDrawItemStruct->hDC,::CreatePen(PS_SOLID,1,color)); HBRUSH hOldBrush = (HBRUSH)::SelectObject(lpDrawItemStruct->hDC,::CreateSolidBrush(color)); ::Rectangle(lpDrawItemStruct->hDC,rcCol.left-1,rcCol.top-1,rcCol.right,rcCol.bottom); ::DeleteObject(SelectObject(lpDrawItemStruct->hDC,hOldBrush)); ::DeleteObject(SelectObject(lpDrawItemStruct->hDC,hOldPen)); sText = MakeShortString(pDC,GetItemText(nItem,nCol),rcCol.Width(),3); if(bSelected) { pDC->SetBkColor(RGB(30, 34, 39)); //pDC->SetTextColor(GetTableItemColor(nItem, nCol, ::GetSysColor(COLOR_HIGHLIGHTTEXT))); pDC->SetTextColor(GetTableItemColor(nItem, nCol, RGB(255, 255, 255))); color = RGB(30, 34, 39); } else { pDC->SetBkColor(RGB(30, 34, 39)); pDC->SetTextColor(GetTableItemColor(nItem, nCol, RGB(255, 255, 255))); } //在这里进行测试 //在这里进行测试 UINT format = DT_CENTER; switch(/*lvc.fmt*/m_anFormat[nCol] & (LVCFMT_LEFT | LVCFMT_CENTER | LVCFMT_RIGHT)) { case LVCFMT_LEFT: format = DT_LEFT; break; case LVCFMT_CENTER: format = DT_CENTER; break; case LVCFMT_RIGHT: format = DT_RIGHT; break; default: break; } pDC->DrawText(sText,CRect::CRect(rcCol.left+3,rcCol.top,rcCol.right,rcCol.bottom), format/*DT_CENTER*//*format*//*DT_LEFT*/|DT_VCENTER|DT_SINGLELINE ); } pDC->RestoreDC(nOldDCMode); } LPCTSTR CListCtrlComboEx::MakeShortString(CDC *pDC,LPCTSTR lpszLong,int nColumnLen,int nOffset) { static const _TCHAR szThreeDots[] = _T("..."); int nStringLen = lstrlen(lpszLong); if(nStringLen == 0 || (pDC->GetTextExtent(lpszLong,nStringLen).cx+nOffset) GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx; for(int i=nStringLen-1; i>0; i--) { szShort[i] = 0; if((pDC->GetTextExtent(szShort,i).cx+nAddLen+nOffset) message, msg->wParam, msg->lParam ); //这两句不能省,否则程序会因消息循环出现异常 Draw the lines only for LVS_REPORT mode //if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT ) //{ // // Get the number of columns // CClientDC dc(this ); // CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0); // int nColumnCount = pHeader->GetItemCount(); // // The bottom of the header corresponds to the top of the line // RECT rect; // pHeader->GetClientRect( &rect ); // int top = rect.bottom; // // Now get the client rect so we know the line length and // // when to stop // GetClientRect( &rect ); // // The border of the column is offset by the horz scroll // int borderx = 0 - GetScrollPos( SB_HORZ ); // CPen listSepPen(PS_SOLID, 1, RGB(201, 213, 240)); //定制你的分割线的颜色 // //CPen listSepPen(PS_SOLID, 1, RGB(30, 34, 39)); // CPen *pOldPen = dc.SelectObject(&listSepPen); // for( int i = 0; i = rect.right ) break; // // Draw the line. // dc.MoveTo( borderx, top); // dc.LineTo( borderx, rect.bottom ); // } // // Draw the horizontal grid lines // // First get the height // if( !GetItemRect( 0, &rect, LVIR_BOUNDS )) // return; // int height = rect.bottom - rect.top; // GetClientRect( &rect ); // int width = rect.right; // for(int i = 1; i message, msg->wParam, msg->lParam); CClientDC dc(this); CRect rect; GetClientRect(&rect); CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0); int nColumnCount = pHeader->GetItemCount(); CRect rectHead; pHeader->GetClientRect(&rectHead); // 画边框 //CPen penBorder(PS_SOLID, 1, RGB(0, 66, 66)); //CPen* pOldPen = dc->SelectObject(&penBorder); //dc.MoveTo(rect.left, rect.top ); //dc.LineTo(rect.left, rect.bottom); //dc.MoveTo(rect.right - 1, rect.top ); //dc.LineTo(rect.right - 1, rect.bottom) if ((GetStyle() & LVS_TYPEMASK) == LVS_REPORT) { CPen penGrid; //penGrid.CreatePen(PS_SOLID, 1, RGB(0, 66, 66));//颜色 penGrid.CreatePen(PS_SOLID, 1, RGB(48, 48, 48));//颜色 CPen* oldPen = dc.SelectObject(&penGrid); int borderx = 0 - GetScrollPos(SB_HORZ); //画边框 //dc.MoveTo(rect.right, rect.top); //dc.LineTo(rect.left, rect.top); //dc.MoveTo(rect.right, rect.bottom); //dc.LineTo(rect.left, rect.bottom); //dc.MoveTo(rect.left, rect.top); //dc.LineTo(rect.left, rect.bottom); //dc.MoveTo(rect.right, rect.top); //dc.LineTo(rect.right, rect.bottom); //取客户区域 CRect item; int nHightPerLine = 18; if (GetItemRect(0, &item, LVIR_BOUNDS)) { nHightPerLine = item.bottom - item.top; } //画纵向线 for (int i = 0; i rect.right) { break; } dc.MoveTo(borderx, rectHead.bottom); dc.LineTo(borderx, rect.bottom); } //画横向线 for (int i = 0; i iItem;//m_row为被选中行的行序号(int类型成员变量) m_nColDblClk=pNMListView->iSubItem;//m_column为被选中行的列序号(int类型成员变量) return FALSE; } BOOL CListCtrlComboEx::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default //return CListCtrl::OnEraseBkgnd(pDC); return FALSE; }