大家也许熟悉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结构如下:
其中:
hwndFrom 发送方控件的窗口句柄
idFrom 发送方控件的ID
code 通知代码
对于某些控件来说,pNMHDR则会解释成其它内容更丰富的结构对象的指针,如:对于列表控件来说,pNMHDR常常指向一个NMCUSTOMDRAW对象,NMCUSTOMDRAW结构如下:
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消息绘制出的多色列表框的例子:
对应代码如下:
注意到上例采取了3.1所推荐的第2种实现方法,派生了一个新类CCoolList。
总体步骤: