天天看點

List control NM

大家也許熟悉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結構如下:

  1. typedef struct tagNMHDR   
  2. {    
  3.     HWND hwndFrom;    
  4.     UINT idFrom;    
  5.     UINT code;    
  6. } NMHDR;   

其中:

hwndFrom 發送方控件的視窗句柄

idFrom 發送方控件的ID

code 通知代碼

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

  1. typedef struct tagNMCUSTOMDRAWINFO   
  2. {   
  3.     NMHDR  hdr;   
  4.     DWORD  dwDrawStage;   
  5.     HDC    hdc;   
  •     RECT   rc;   
  •     DWORD  dwItemSpec;   
  •     UINT   uItemState;   
  •     LPARAM lItemlParam;   
  • } NMCUSTOMDRAW, FAR * LPNMCUSTOMDRAW;

    hdr NMHDR對象

    dwDrawStage 目前繪制狀态,其取值如表7所示:

    類型值 含義

    CDDS_POSTERASE 擦除循環結束

    CDDS_POSTPAINT 繪制循環結束

    CDDS_PREERASE 準備開始擦除循環

    CDDS_PREPAINT 準備開始繪制循環

    CDDS_ITEM 指定dwItemSpec, uItemState, lItemlParam參數有效

    CDDS_ITEMPOSTERASE 清單項擦除結束

    CDDS_ITEMPOSTPAINT 清單項繪制結束

    CDDS_ITEMPREERASE 準備開始清單項擦除

    CDDS_ITEMPREPAINT 準備開始清單項繪制

    CDDS_SUBITEM 指定清單子項

    表7 dwDrawStage的類型值與含義

    hdc指定了繪制操作所使用的裝置環境。

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

    dwItemSpec 清單項的索引

    uItemState 目前清單項的狀态,其取值如表8所示:

    類型值 含義

    CDIS_CHECKED 标記狀态。

    CDIS_DEFAULT 預設狀态。

    CDIS_DISABLED 禁止狀态。

    CDIS_FOCUS 焦點狀态。

    CDIS_GRAYED 灰化狀态。

    CDIS_SELECTED 選中狀态。

    CDIS_HOTLIGHT 熱點狀态。

    CDIS_INDETERMINATE 不定狀态。

    CDIS_MARKED 标注狀态。

    表8 uItemState的類型值與含義

    lItemlParam 目前清單項的綁定資料

    pResult 指向狀态值的指針,指定系統後續操作,依賴于dwDrawStage:

    當dwDrawStage為CDDS_PREPAINT,pResult含義如表9所示:

    類型值 含義

    CDRF_DODEFAULT 預設操作,即系統在清單項繪制循環過程不再發送NM_CUSTOMDRAW。

    CDRF_NOTIFYITEMDRAW 指定清單項繪制前後發送消息。

    CDRF_NOTIFYPOSTERASE 清單項擦除結束時發送消息。

    CDRF_NOTIFYPOSTPAINT 清單項繪制結束時發送消息。

    表9 pResult的類型值與含義(一)

    當dwDrawStage為CDDS_ITEMPREPAINT,pResult含義如表10所示:

    類型值 含義

    CDRF_NEWFONT 指定後續操作采用應用中指定的新字型。

    CDRF_NOTIFYSUBITEMDRAW 清單子項繪制時發送消息。

    CDRF_SKIPDEFAULT 系統不必再繪制該子項。

    表10 pResult的類型值與含義(二)

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

    List control NM

    圖12 利用NM_CUSTOMDRAW消息美化界面

    對應代碼如下:

    1. void CCoolList::OnCustomDraw  //從CListCtrl派生(NMHDR *pNMHDR, LRESULT *pResult)   
    2. {   
    3.     //類型安全轉換   
    4.     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

繼續閱讀