CUSTOMDRAW和OwnerDraw
1.Owner Draw
当Button控件被设置成OwnerDraw属性时,父窗体就会接受到WM_DRAWITEM、WM_MEASUREITEM、WM_COMPAREITEM、WM_DELETEITEM四个消息。
除了Button空间外,还有ListBox控件设置CBS_OWNERDRAWVARIABLE属性。
The WM_DRAWITEM message is sent to the owner window of an owner-drawn button, combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.
在MFC中,已经将这个4个消息反射到子控件的类中,如
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
int CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct);
void DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct);
2.Custom Draw
如下控件都支持Custom Draw。
父窗体会收到NM_CUSTOMDRAW的通知消息。即
WM_NOTIFY idCtrl = (int) wParam;
pnmh = (LPNMHDR) lParam;
typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code; //通知消息码
} NMHDR;
当控制码是NM_CUSTOMDRAW时候
#ifdef LIST_VIEW_CUSTOM_DRAW
lpNMCustomDraw = (LPNMLVCUSTOMDRAW) lParam;
#elif TOOL_TIPS_CUSTOM_DRAW
lpNMCustomDraw = (LPNMTTCUSTOMDRAW) lParam;
#elif TREE_VIEW_CUSTOM_DRAW
lpNMCustomDraw = (LPNMTVCUSTOMDRAW) lParam;
#elif TOOL_BAR_CUSTOM_DRAW
lpNMCustomDraw = (LPNMTBCUSTOMDRAW) lParam;
#else
lpNMCustomDraw = (LPNMCUSTOMDRAW) lParam;
#endif
lpNMCustomDraw->dwDrawStage有如下几种可能
Global Values
Description
CDDS_POSTERASE
After the erasing cycle is complete.
CDDS_POSTPAINT
After the painting cycle is complete.
CDDS_PREERASE
Before the erasing cycle begins.
CDDS_PREPAINT
Before the painting cycle begins.
Item-specific Values
Description
CDDS_ITEM
Indicates that the dwItemSpec, uItemState, and lItemlParam members are valid.
CDDS_ITEMPOSTERASE
After an item has been erased.
CDDS_ITEMPOSTPAINT
After an item has been drawn.
CDDS_ITEMPREERASE
Before an item is erased.
CDDS_ITEMPREPAINT
Before an item is drawn.
CDDS_SUBITEM
Version 4.71. Flag combined with CDDS_ITEMPREPAINT or CDDS_ITEMPOSTPAINT if a subitem is being drawn. This will only be set if CDRF_NOTIFYITEMDRAW is returned from CDDS_PREPAINT.
在MFC或WTL中,已经反射到子控件,并封装好如下函数
DWORD OnPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPostEraset(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnSubItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
当Button控件被设置成OwnerDraw属性时,父窗体就会接受到WM_DRAWITEM、WM_MEASUREITEM、WM_COMPAREITEM、WM_DELETEITEM四个消息。
除了Button空间外,还有ListBox控件设置CBS_OWNERDRAWVARIABLE属性。
The WM_DRAWITEM message is sent to the owner window of an owner-drawn button, combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.
在MFC中,已经将这个4个消息反射到子控件的类中,如
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
int CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct);
void DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct);
2.Custom Draw
如下控件都支持Custom Draw。
父窗体会收到NM_CUSTOMDRAW的通知消息。即
WM_NOTIFY idCtrl = (int) wParam;
pnmh = (LPNMHDR) lParam;
typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code; //通知消息码
} NMHDR;
当控制码是NM_CUSTOMDRAW时候
#ifdef LIST_VIEW_CUSTOM_DRAW
lpNMCustomDraw = (LPNMLVCUSTOMDRAW) lParam;
#elif TOOL_TIPS_CUSTOM_DRAW
lpNMCustomDraw = (LPNMTTCUSTOMDRAW) lParam;
#elif TREE_VIEW_CUSTOM_DRAW
lpNMCustomDraw = (LPNMTVCUSTOMDRAW) lParam;
#elif TOOL_BAR_CUSTOM_DRAW
lpNMCustomDraw = (LPNMTBCUSTOMDRAW) lParam;
#else
lpNMCustomDraw = (LPNMCUSTOMDRAW) lParam;
#endif
lpNMCustomDraw->dwDrawStage有如下几种可能
Global Values
Description
CDDS_POSTERASE
After the erasing cycle is complete.
CDDS_POSTPAINT
After the painting cycle is complete.
CDDS_PREERASE
Before the erasing cycle begins.
CDDS_PREPAINT
Before the painting cycle begins.
Item-specific Values
Description
CDDS_ITEM
Indicates that the dwItemSpec, uItemState, and lItemlParam members are valid.
CDDS_ITEMPOSTERASE
After an item has been erased.
CDDS_ITEMPOSTPAINT
After an item has been drawn.
CDDS_ITEMPREERASE
Before an item is erased.
CDDS_ITEMPREPAINT
Before an item is drawn.
CDDS_SUBITEM
Version 4.71. Flag combined with CDDS_ITEMPREPAINT or CDDS_ITEMPOSTPAINT if a subitem is being drawn. This will only be set if CDRF_NOTIFYITEMDRAW is returned from CDDS_PREPAINT.
在MFC或WTL中,已经反射到子控件,并封装好如下函数
DWORD OnPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnPostErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPostPaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPreErase(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnItemPostEraset(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
DWORD OnSubItemPrePaint(int idCtrl, LPNMCUSTOMDRAW lpNMCD);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现