当前位置: 首页 > article >正文

带有LBS_OWNERDRAWFIXED 样式的列表框,系统在什么时候向窗口发送WM_DRAWITEM 和WM_MEASUREITEM消息de呢?

说明:以下内容主要来自腾讯元宝。

以下是 ​带有 LBS_OWNERDRAWFIXED 样式的列表框触发 WM_MEASUREITEM 和 WM_DRAWITEM 消息的具体时机和场景:


1. WM_MEASUREITEM 消息的触发时机

WM_MEASUREITEM 在以下情况下被系统发送:

​**(1) 列表框首次创建时**
  • 当窗口过程通过 CreateWindow 创建列表框后,系统会立即发送 WM_MEASUREITEM 消息,以确定列表项的尺寸(尤其是高度)。
​**(2) 列表框窗口大小调整时**
  • 如果列表框的父窗口大小发生变化,导致列表框的布局需要重新计算,系统可能触发 WM_MEASUREITEM
​**(3) 列表框样式动态修改时**
  • 如果运行时修改了列表框的样式(如添加 LBS_OWNERDRAWFIXED),系统可能发送 WM_MEASUREITEM
​**(4) 通过代码显式触发**
  • 调用 InvalidateRect 或 UpdateWindow 强制重绘列表框窗口时,可能间接触发 WM_MEASUREITEM

2. WM_DRAWITEM 消息的触发时机

WM_DRAWITEM 在以下情况下被系统发送:

​**(1) 列表框首次显示时**
  • 当窗口过程调用 ShowWindow 或 UpdateWindow 显示列表框时,系统会触发 WM_PAINT 消息,进而引发 WM_DRAWITEM,以绘制所有列表项。
​**(2) 列表项内容发生变化时**
  • 添加/删除项:调用 LB_ADDSTRINGLB_DELETESTRING 等函数后,若列表框需要刷新显示,系统会发送 WM_DRAWITEM
  • 示例代码
    SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)_T("中国")); // 添加项
    InvalidateRect(hWnd, NULL, FALSE); // 强制重绘,触发 WM_PAINT → WM_DRAWITEM
​**(3) 用户交互触发**
  • 滚动列表框滚动时系统会动态发送 WM_DRAWITEM,仅绘制当前可见区域的项。
  • 窗口激活/最小化恢复:窗口状态变化时触发重绘。
​**(4) 程序主动触发**
  • 通过 SendMessage 发送 LB_RESETCONTENT 清空列表框后重新填充数据,强制触发重绘。

3. LBS_OWNERDRAWFIXED 样式的特殊行为

  • 固定高度
    LBS_OWNERDRAWFIXED 样式要求所有列表项的高度统一。系统在首次创建列表框时会发送一次 WM_MEASUREITEM,开发者需在此消息中设置固定高度(如 lpmis->itemHeight = 30)。后续即使项的内容变化,也不会重复发送 WM_MEASUREITEM(除非列表框窗口被销毁并重新创建)。

  • 自定义绘制
    每次列表项需要显示时(如窗口滚动、刷新),系统都会发送 WM_DRAWITEM,开发者需在此消息中完成背景和文本的自定义绘制。


4. 消息触发流程示例

步骤 1:创建列表框(启用 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);
步骤 2:触发 WM_MEASUREITEM(首次创建时自动触发)​
  • 系统发送 WM_MEASUREITEM,窗口过程设置项高度为 30 像素。
步骤 3:触发 WM_DRAWITEM(首次显示时自动触发)​
  • 系统发送 WM_PAINT,窗口过程调用 DefWindowProc,进而触发 WM_DRAWITEM,绘制所有列表项。
步骤 4:动态添加项并触发 WM_DRAWITEM
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)_T("英国"));
InvalidateRect(hWnd, NULL, FALSE); // 触发重绘

5. 对比 LBS_STANDARD 和 LBS_OWNERDRAWFIXED

样式WM_MEASUREITEM 触发条件WM_DRAWITEM 触发条件
LBS_STANDARD从不触发(系统自动管理项尺寸)从不触发(系统自动绘制项内容)
LBS_OWNERDRAWFIXED创建时、窗口大小调整时、样式修改时显示时、项变化时、滚动时、程序触发重绘时

6. 注意事项

  1. 必须处理 WM_MEASUREITEM
    若未处理此消息,列表项的高度可能为默认值(基于字体大小),导致布局错乱。

  2. 必须处理 WM_DRAWITEM
    若未处理此消息,列表项将无法显示内容,甚至导致窗口崩溃。

  3. 性能优化

    • 在 WM_DRAWITEM 中避免重复创建 GDI 对象(如刷子),可缓存常用资源。
    • 仅在必要时调用 InvalidateRect,避免频繁重绘。

总结

  • WM_MEASUREITEM:用于初始化或调整列表项的高度(仅在 LBS_OWNERDRAWFIXED 或 LBS_OWNERDRAWVARIABLE 样式下触发)。
  • WM_DRAWITEM:用于自定义绘制列表项的内容(每次项需要显示时触发)。
  • LBS_OWNERDRAWFIXED 的列表框需通过这两个消息实现完全的自定义控制。

http://www.kler.cn/a/581883.html

相关文章:

  • 使用DeepSeek+蓝耘快速设计网页简易版《我的世界》小游戏
  • 如何在Spring Boot中配置和使用MyBatis-Plus
  • NO.36十六届蓝桥杯备战|位运算和操作符属性|进制转换|原码反码补码|左移|右移|按位与|按位或|按位异或|按位取反(C++)
  • 帕金森病如何 “偷走” 患者的正常生活?
  • HttpMediaTypeNotAcceptableException报错解决,状态码显示为406
  • 3dsmax烘焙光照贴图然后在unity中使用
  • shell脚本一键更新部署docker中服务
  • 《深度学习进阶》第7集:深度实战 通过训练一个智能体玩游戏 来洞察 强化学习(RL)与决策系统
  • 操作系统与网络基础:掌握网络安全的核心技能
  • 基于django+pytorch(Faster R-CNN)的钢材缺陷识别系统
  • HTML 列表详解
  • 【前端】【webpack-dev-server】proxy跨域代理
  • C++全栈聊天项目(2) 单例模式封装Http管理者
  • mac本地部署Qwq-32b记录
  • 【Spring】基础/体系结构/核心模块
  • 计算机网络开发(3)——端口复用、I\O多路复用
  • CSS 中 margin 的margin塌陷问题
  • 图论·拓扑排序
  • ClickHouse 数据倾斜实战:案例分析与优化技巧
  • 【Go】Go zap 日志模块