(1)首先須要自定義一個類,派生自CListCtrl。以下圖:app
(2)而後在派生類的頭文件中聲明一個成員函數,以下圖:less
(3)在源文件中實現該成員方法,如圖:函數
(4)在源文件中作消息映射,如圖:字體
這時候,當CListCtrl控件在繪製的時候,就會有NM_CUSTOMDRAW消息被咱們的函數截獲。this
咱們就在實現函數中篩選出CListCtrl控件應該設置內容(文字顏色,文字背景顏色)的時機,對繪製的內容作相應的修改便可。spa
// ColorListCtrl.cpp : implementation file // #include "stdafx.h" #include "test.h" #include "ColorListCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CColorListCtrl CColorListCtrl::CColorListCtrl() { m_iRow = -1; //這裏咱們定義了三個成員變量,分別用於表示單元格的「行號」,「列號」,「字體」 在構造函數中初始化他們。 m_iCol = -1; m_Font = NULL; } CColorListCtrl::~CColorListCtrl() { if ( m_Font ) delete m_Font; //刪除字體 析構函數中銷燬字體所指對象。 } BEGIN_MESSAGE_MAP(CColorListCtrl, CListCtrl) //{{AFX_MSG_MAP(CColorListCtrl) // NOTE - the ClassWizard will add and remove mapping macros here. ON_NOTIFY_REFLECT(NM_CUSTOMDRAW,OnNMCustomdraw) //這裏就是消息映射了。 //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CColorListCtrl message handlers void CColorListCtrl::PreSubclassWindow() { // TODO: Add your specialized code here and/or call the base class CListCtrl::PreSubclassWindow(); } void CColorListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) //獲取消息後的實現代碼。 { NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR ); //首先聲明一個NMLVCUSTOMDRAW結構體的指針pLVCD,關聯pNMHDR,爲了下面的操做。 // Take the default processing unless we set this to something else below. *pResult = CDRF_DODEFAULT; // First thing - check the draw stage. If it's the control's prepaint // stage, then tell Windows we want messages for every item. if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage ) { *pResult = CDRF_NOTIFYITEMDRAW; } else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage ) { // This is the notification message for an item. We'll request // notifications before each subitem's prepaint stage. *pResult = CDRF_NOTIFYSUBITEMDRAW; } else if ( (CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage ) //僅當pLVCD結構體中nmcd成員的dwDrawStage狀態爲CDDS_ITEMPREPAINT | CDDS_SUBITEM時 { //咱們就能夠判斷「行」和「列」,從而來設置文字顏色和文字背景顏色了。 // This is the prepaint stage for a subitem. Here's where we set the // item's text and background colors. Our return value will tell // Windows to draw the subitem itself, but it will use the new colors // we set here. if ( m_iCol == pLVCD->iSubItem && m_iRow == pLVCD->nmcd.dwItemSpec) { pLVCD->clrTextBk = m_Color; pLVCD->clrText = m_TextColor; //SetFont(m_Font, false); } else { pLVCD->clrTextBk = 16777215;//若是不是選擇的「行」和「列」就設置成系統默認的那種顏色。 pLVCD->clrText = 0; } //SetFont(m_Font, false); // Store the colors back in the NMLVCUSTOMDRAW struct. // Tell Windows to paint the control itself. *pResult = CDRF_DODEFAULT; } } void CColorListCtrl::SetColor(int iRow, int iCol, COLORREF color) { m_iRow = iRow; m_iCol = iCol; m_Color = color; /*m_vctRow.push_back(iRow); m_vctCol.push_back(iCol); m_vctColorValue.push_back(color);*/ } void CColorListCtrl::SetSubItemFont(LOGFONT font, COLORREF color, long lsize) { if ( m_Font ) delete m_Font; //刪除舊字體 m_Font = new CFont; m_Font->CreateFontIndirect(&font); m_TextColor = color; m_TextSize = lsize; }
最後,要使用的時候(及要改變列表框中文字顏色或文字背景顏色的時候),咱們只須要調用這個派生類的對象的這兩個Public方法,把顏色傳入。以下:3d
void CTestDlg::OnApply() { // TODO: Add your control notification handler code here CString strRow; CString strCol; GetDlgItem(IDC_EDIT1)->GetWindowText(strRow); GetDlgItem(IDC_EDIT2)->GetWindowText(strCol); int iRow = atoi(strRow); int iCol = atoi(strCol); // m_List.SetColor(iRow, iCol, m_color); //m_List.SetItemColor(iRow, iCol, m_color); m_List.SetColor(iRow, iCol, m_color); m_List.SetSubItemFont(m_Font, m_TextColor, m_TextSize); Invalidate(TRUE); }
爲了讓咱們的修改生效,必須調用Invalidate(TRUE);指針
////////////////////////////////////////////////////////////////////////////////////////////////////////code
/////////////////////////////////////////////////////////////////////////////////////////////////////////對象
下面代碼實現列表框的選擇項的顏色修改。。。。。。另一個消息相應函數。
void CXListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) { /*修改內容: 改用switch case語句 case語句中增長了CDDS_ITEMPREPAINT和CDDS_ITEMPOSTPAINT兩個狀態判斷 同時在改變顏色時增長了一個函數SetItemState */ static BOOL s_bThisItemSelect = FALSE; NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR); int nItemIndex=pLVCD->nmcd.dwItemSpec; *pResult = CDRF_DODEFAULT; switch (pLVCD->nmcd.dwDrawStage) { case CDDS_PREPAINT: *pResult = CDRF_NOTIFYITEMDRAW; break; case CDDS_ITEMPREPAINT: { UINT ordin = pLVCD->nmcd.lItemlParam; s_bThisItemSelect = FALSE; //選中行顏色改變 if (GetItemState(nItemIndex,LVIS_SELECTED) == LVIS_SELECTED/*pLVCD->nmcd.uItemState & CDIS_SELECTED*/) { s_bThisItemSelect = TRUE; //增長了下面這個SetItemState函數 SetItemState(pLVCD->nmcd.dwItemSpec, 0, LVIS_SELECTED); pLVCD->clrText = RGB(255,255,255)/*m_SelectItemTextColor*/; pLVCD->clrTextBk =RGB(255,128,0)/*m_SelectItemBkColor*/; } *pResult = CDRF_NOTIFYPOSTPAINT; } break; //加了一個狀體判斷 case CDDS_ITEMPOSTPAINT: if (s_bThisItemSelect) SetItemState(pLVCD->nmcd.dwItemSpec, 0xFF, LVIS_SELECTED); break; } }