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不会。

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