
说明:以下内容主要来自腾讯元宝。
以下是
带有
LBS_OWNERDRAWFIXED
样式的列表框
触发
WM_MEASUREITEM
和
WM_DRAWITEM
消息的具体时机和场景:
WM_MEASUREITEM
在以下情况下被系统发送:
CreateWindow
创建列表框
后,系统会立即发送
WM_MEASUREITEM
消息,以确定列表项的尺寸(尤其是高度)。WM_MEASUREITEM
。LBS_OWNERDRAWFIXED
),系统可能发送
WM_MEASUREITEM
。InvalidateRect
或
UpdateWindow
强制重绘列表框窗口时,可能间接触发
WM_MEASUREITEM
。WM_DRAWITEM
在以下情况下被系统发送:
ShowWindow
或
UpdateWindow
显示列表框
时,系统会触发
WM_PAINT
消息,进而引发
WM_DRAWITEM
,以绘制所有列表项。
添加/删除项
:调用
LB_ADDSTRING
、
LB_DELETESTRING
等函数
后,若列表框需要刷新显示,系统会发送
WM_DRAWITEM
。
示例代码 :
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)_T("中国")); // 添加项
InvalidateRect(hWnd, NULL, FALSE); // 强制重绘,触发 WM_PAINT → WM_DRAWITEM
WM_DRAWITEM
,仅绘制当前可见区域的项。SendMessage
发送
LB_RESETCONTENT
清空列表框后重新填充数据
,强制触发重绘。 固定高度 :
LBS_OWNERDRAWFIXED
样式要求所有列表项的高度统一。系统在首次创建列表框时会发送一次
WM_MEASUREITEM
,开发者需在此消息中设置固定高度(如
lpmis->itemHeight = 30
)。后续即使项的内容变化,也不会重复发送
WM_MEASUREITEM
(除非列表框窗口被销毁并重新创建)。
自定义绘制 :
每次列表项需要显示时(如窗口滚动、刷新),系统都会发送
WM_DRAWITEM
,开发者需在此消息中完成背景和文本的自定义绘制。
LBS_OWNERDRAWFIXED )hListBox = CreateWindow(
_T("ListBox"), NULL,
WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS,
20, 20, 60, 120,
hWnd, (HMENU)ID_MYLIST,
hInst, NULL);
WM_MEASUREITEM
,窗口过程设置项高度为 30 像素。WM_PAINT
,窗口过程调用
DefWindowProc
,进而触发
WM_DRAWITEM
,绘制所有列表项。SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)_T("英国"));
InvalidateRect(hWnd, NULL, FALSE); // 触发重绘
| 样式 | WM_MEASUREITEM 触发条件 | WM_DRAWITEM 触发条件 |
|---|---|---|
| LBS_STANDARD | 从不触发(系统自动管理项尺寸) | 从不触发(系统自动绘制项内容) |
| LBS_OWNERDRAWFIXED | 创建时、窗口大小调整时、样式修改时 | 显示时、项变化时、滚动时、程序触发重绘时 |
必须处理 WM_MEASUREITEM :
若未处理此消息,列表项的高度可能为默认值(基于字体大小),导致布局错乱。
必须处理 WM_DRAWITEM :
若未处理此消息,列表项将无法显示内容,甚至导致窗口崩溃。
性能优化 :
WM_DRAWITEM
中避免重复创建 GDI 对象(如刷子),可缓存常用资源。InvalidateRect
,避免频繁重绘。LBS_OWNERDRAWFIXED
或
LBS_OWNERDRAWVARIABLE
样式下触发)。