改變ListCtrl某行的背景色或者字體顏色


大家也許熟悉WM_NOTIFY,控件通過WM_NOTIFY向父窗口發送消息。在WM_NOTIFY消息體中,部分控件會發送NM_CUSTOMDRAW告訴父窗口自己需要繪圖。

也可以反射NM_CUSTOMDRAW消息,如:

ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)         //需要自己加進去
afx_msg void OnCustomDraw(NMHDR *pNMHDR, LRESULT *pResult);

參數:

pNMHDR 說到底只是一個指針,大多數情況下它指向一個NMHDR結構對象,NMHDR結構如下:

typedef struct tagNMHDR   
{    
    HWND hwndFrom;    
    UINT idFrom;    
    UINT code;    
} NMHDR; 

其中:

hwndFrom 發送方控件的窗口句柄

idFrom 發送方控件的ID

code 通知代碼

對於某些控件來說,pNMHDR則會解釋成其它內容更豐富的結構對象的指針,如:對於列表控件來說,pNMHDR常常指向一個NMCUSTOMDRAW對象,NMCUSTOMDRAW結構如下:

typedef struct tagNMCUSTOMDRAWINFO   
{   
    NMHDR  hdr;   
    DWORD  dwDrawStage;   
    HDC    hdc;   
    RECT   rc;   
    DWORD  dwItemSpec;   
    UINT   uItemState;   
    LPARAM lItemlParam;   
} NMCUSTOMDRAW, FAR * LPNMCUSTOMDRAW;

其中:

hdr NMHDR對象

dwDrawStage 當前繪制狀態,其取值如下:

 

CDDS_POSTERASE 擦除循環結束
CDDS_POSTPAINT  繪制循環結束
CDDS_PREERASE  准備開始擦除循環
CDDS_PREPAINT 准備開始繪制循環
CDDS_ITEM 指定dwItemSpec, uItemState, lItemlParam參數有效
CDDS_ITEMPOSTERASE 列表項擦除結束
CDDS_ITEMPOSTPAINT  列表項繪制結束
CDDS_ITEMPREERASE 准備開始列表項擦除
CDDS_ITEMPREPAINT 准備開始列表項繪制
CDDS_SUBITEM 指定列表子項

 

 

 

 

 

 

 

hdc指定了繪制操作所使用的設備環境。

rc指定了將被繪制的矩形區域。

dwItemSpec 列表項的索引

uItemState 當前列表項的狀態,其取值如下:

CDIS_CHECKED 標記狀態
CDIS_DEFAULT 默認狀態
CDIS_DISABLED 禁止狀態
CDIS_FOCUS 焦點狀態
CDIS_GRAYED 灰化狀態
CDIS_SELECTED 選中狀態
CDIS_HOTLIGHT 熱點狀態
CDIS_INDETERMINATE 不定狀態
CDIS_MARKED標注狀態  

 

 

 

 

 

 

 

 

 

lItemlParam 當前列表項的綁定數據

pResult 指向狀態值的指針,指定系統后續操作,依賴於dwDrawStage:

當dwDrawStage為CDDS_PREPAINT,pResult含義如下:

CDRF_DODEFAULT 默認操作,即系統在列表項繪制循環過程不再發送NM_CUSTOMDRAW
CDRF_NOTIFYITEMDRAW  指定列表項繪制前后發送消息
CDRF_NOTIFYPOSTERASE 列表項擦除結束時發送消息
CDRF_NOTIFYPOSTPAINT 列表項繪制結束時發送消息

 

 

 

 

 

 

當dwDrawStage為CDDS_ITEMPREPAINT,pResult含義如下:

CDRF_NEWFONT  指定后續操作采用應用中指定的新字體
CDRF_NOTIFYSUBITEMDRAW  列表子項繪制時發送消息
CDRF_SKIPDEFAULT  系統不必再繪制該子項

 

 

 

 

以下是一個利用NM_CUSTOMDRAW消息繪制出的多色列表框的例子:

對應代碼如下:

void CCoolList::OnCustomDraw  //從CListCtrl派生(NMHDR *pNMHDR, LRESULT *pResult)   
{   
    //類型安全轉換   
    NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR); *pResult = 0; //指定列表項繪制前后發送消息 if(CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYITEMDRAW; } else if(CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage) { //奇數行 if(pLVCD->nmcd.dwItemSpec % 2) pLVCD->clrTextBk = RGB(255, 255, 128); //偶數行 else pLVCD->clrTextBk = RGB(128, 255, 255); //繼續 *pResult = CDRF_DODEFAULT; } } 
注意到上例采取了3.1所推薦的第2種實現方法,派生了一個新類CCoolList。

總體步驟:

  1. 派生CCoolList類
  2. BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
     //{{AFX_MSG_MAP(CMyListCtrl)
      // NOTE - the ClassWizard will add and remove mapping macros here.
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)  //自己添加
     //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
  3. 定義CListCtrl  Control m_list變量,再將CListCtrl 改為CCoolList

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM