MFC 控件重繪(2) NM_CUSTOMDRAW, WM_DRAWITEM, 虛函數DrawItem

控件重繪有三種方法:
1 設定界面屬性
2 利用Windows的消息機制,通過Windows消息映射(Message Mapping)和反映射(Message Reflecting),在合適的時機修改控件的狀態和行爲。此方式涉及NM_CUSTOMDRAWWM_DRAWITEM
3 利用虛函數機制,重載虛函數。即DrawItem虛函數。

對於NM_CUSTOMDRAW,某些支持此消息的控件會發送NM_CUSTOMDRAW給宿主類(父窗口),
如果不需要對控件重寫,則ON_NOTIFY(NM_CUSTOMDRAW, IDC_CONTROL, OnCustomDrawMyControl),
處理函數原形如下: afx_msg void OnCustomDrawMyControl(NMHDR* pNMHDR, LRESULT *pResult),
這兩句話的含義是需要宿主類處理IDC_CONTROL發出的ON_NOTIFY消息,Message是 NM_CUSTOMDRAW,OnCustomDrawMyControl就是處理函數。
注意:此函數在宿主類中,即一般格式是CxxxDlg::OnCustomDrawMyControl();
如果需要重寫控件,例如:Class CMyButton:public CButton,
在CMyButton中添加ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw), 然後在CMyButton::OnCustomDraw中添加相應的代碼。
這兩種方式都使用了NM_CUSTOMDRAW消息,不同點在於一個在宿主類中實現CxxxDlg::OnCustomDrawMyControl,一個在派生類裏實現CMyButton::OnCustomDraw.
在派生類中實現的OnCustomDraw是反映射機制,有些像回調函數。
對於NM_CUSTOMDRAW, MFC將控件繪製分爲四部分:繪製前後和擦除前後,具體可參看msdn文檔。

下面談談WM_DRAWITEM。WM_DRAW稱爲Owner Draw。不是所有控件都支持,具體要查msdn。
對於一個派生類,它不可能接受到WM_DRAWITEM消息,此消息是在子控件將要繪畫時,Windows向宿主類發送,
當宿主類接受到此消息後,如果沒有重寫控件,則在宿主類中處理相應業務需求,即CxxxDlg::OnDrawItem,
如果重寫了控件,例如: Class CMyButton:public CButton,則宿主類會調用派生類的虛函數CMyButton::DrawItem.
注意:如果需要響應OnDrawItem,必須在控件屬性中選擇OwnerDraw=TRUE,否則OnDrawItem將無效。

最後捎帶再談談OnPaint和OnDraw,看以下源碼即可明白:

void CView::OnPaint()
{
    CPaintDC dc(this);
    OnPrepareDC(&dc);
    OnDraw(&dc);
}

OnPaint會響應WM_PAINT,OnDraw不會。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章