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

详细解析 ListView_GetEditControl()

书籍:《Visual C++ 2017从入门到精通》的2.3.8 Win32控件编程

环境:visual studio 2022

内容:【例2.28】支持主项可编辑的列表视图控件

说明:以下内容大部分来自腾讯元宝。

函数原型

HWND ListView_GetEditControl(HWND hwndList);
功能说明
  • 作用:获取当前处于编辑模式的列表视图项(主项)的编辑控件句柄(HWND)。
  • 适用场景当用户点击列表项标签并进入编辑模式时,通过此函数操作编辑框(如读取或设置文本)。
  • 返回值
    • 成功:返回编辑控件的句柄。
    • 失败:返回 NULL(例如未启用标签编辑、未进入编辑模式、控件无效等)。

核心机制

  1. 标签编辑触发

    • 用户点击列表项标签时,若列表视图控件启用了标签编辑(通过样式 LVS_EDITLABELS 或 LVM_SETITEMCOUNT 启用),系统会自动创建一个编辑框(通常为 CEdit 类)。
    • 函数调用时机:仅在 LVN_BEGINLABELEDIT 消息触发时有效。
  2. 内部实现

    • 列表视图控件通过子窗口管理编辑框,ListView_GetEditControl 内部通过遍历子窗口或直接关联控件句柄返回编辑框指针。

使用注意事项

1. 启用标签编辑
  • 必须设置样式:在创建列表视图控件时,需启用 LVS_EDITLABELS 样式
    HWND hListView = CreateWindowEx(
        0, WC_LISTVIEW, _T("List View"),
        LVS_EDITLABELS | /* 其他样式 */, ... );
  • 动态启用:可通过 ListView_SetStyle 动态启用。
    ListView_SetStyle(hListView, LVS_EDITLABELS);
2. 调用时机限制
  • 仅限 LVN_BEGINLABELEDIT 事件:在用户开始编辑标签时调用,其他时刻可能返回无效句柄。
    case LVN_BEGINLABELEDIT:
        hEdit = ListView_GetEditControl(hListView); // 正确时机
        break;
3. 检查句柄有效性
  • 避免空指针操作:调用后需检查 hEdit 是否为 NULL
    hEdit = ListView_GetEditControl(hListView);
    if (!hEdit) {
        // 处理错误(如日志输出或返回)
        return;
    }
4. 编辑控件生命周期
  • 及时操作:获取句柄后需尽快完成操作(如读取文本),因为编辑控件可能在用户取消编辑(按 ESC)或完成编辑(按回车)后被销毁。
  • 禁止延迟操作:不要在异步线程或长时间耗时操作中保留句柄。
5. 多列列表视图的局限性
  • 仅支持主项编辑ListView_GetEditControl 仅返回主项的编辑控件句柄,子项编辑需其他方法(如自定义控件或消息处理)。
  • 子项编辑方案:需监听 LVN_BEGINLABELEDIT,并通过 iSubItem 字段判断编辑的子项,但无法直接获取子项编辑框句柄。
6. 与 LVN_ENDLABELEDIT 的协作
  • 避免重复读取:在 LVN_ENDLABELEDIT 事件中,编辑控件已销毁,​不要调用 GetWindowText(hEdit, ...)
    • 正确做法:在 LVN_BEGINLABELEDIT 中保存原始文本,在 LVN_ENDLABELEDIT 中直接使用事件参数 pszText
    case LVN_ENDLABELEDIT:
        NMLVENDLABELEDIT* pEndEdit = (NMLVENDLABELEDIT*)lParam;
        if (!gbPreeEscKey) {
            // 使用用户输入的文本(pEndEdit->pszText)
            item.pszText = pEndEdit->pszText;
        } else {
            // 使用保存的原始文本(strRaw)
            item.pszText = strRaw;
        }
        break;
7. 线程安全
  • UI线程专属:必须在创建列表视图控件的线程中调用,跨线程操作会导致崩溃。
8. 兼容性
  • Windows 版本:支持 Windows XP 及以上版本,但建议使用 LVM_GETEDITCONTROL 宏(兼容性更强)。
    #define ListView_GetEditControl(hwndList) \
        ((HWND)(SendMessage(hwndList, LVM_GETEDITCONTROL, 0, 0)))

示例代码改进

// LVN_BEGINLABELEDIT 处理
case LVN_BEGINLABELEDIT:
    hEdit = ListView_GetEditControl(hListView);
    if (hEdit) {
        GetWindowText(hEdit, strRaw, sizeof(strRaw)); // 保存原始文本
    }
    break;

// LVN_ENDLABELEDIT 处理
case LVN_ENDLABELEDIT:
    NMLVENDLABELEDIT* pEndEdit = (NMLVENDLABELEDIT*)lParam;
    int iIndex = pEndEdit->iItem;
    if (!gbPreeEscKey && pEndEdit->pszText) {
        // 使用用户输入的文本
        item.iSubItem = 0;
        item.pszText = pEndEdit->pszText;
    } else {
        // 恢复原始文本
        item.iSubItem = 0;
        item.pszText = strRaw;
    }
    SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)iIndex, (LPARAM)&item);
    break;

常见问题与调试

  1. 句柄为 NULL

    • 未启用标签编辑?检查样式 LVS_EDITLABELS
    • 调用时机错误?确保在 LVN_BEGINLABELEDIT 中调用。
  2. 文本无法恢复

    • 全局变量 gbPreeEscKey 未正确设置?检查键盘事件处理逻辑。
  3. 多列编辑失效

    • ListView_GetEditControl 仅支持主项,子项需自定义实现。

总结

ListView_GetEditControl() 是操作列表视图标签编辑的核心函数,需严格遵循以下原则:

  1. 启用标签编辑:样式 LVS_EDITLABELS 必不可少。
  2. 时机精准:仅在 LVN_BEGINLABELEDIT 中调用。
  3. 句柄有效性检查:防止空指针操作。
  4. 协作事件处理:结合 LVN_ENDLABELEDIT 的 pszText 成员,避免间接访问已销毁控件。

通过合理使用该函数,可高效实现列表视图项的标签编辑与状态管理。


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

相关文章:

  • Linux入门 全面整理终端 Bash、Vim 基础命令速记
  • Xxl-Job学习笔记
  • Vue系统学习day01
  • 258.反转字符串中的单词
  • 【每日学点HarmonyOS Next知识】span问题、组件标识属性、属性动画回调、图文混排、相对布局问题
  • Linux 部署Java应用程序
  • OpenCV实现图像分割与无缝合并
  • FORTRAN语言的数据结构
  • GStreamer —— 2.17、Windows下Qt加载GStreamer库后运行 - “播放教程 5:色彩平衡“(附:完整源码)
  • FastJSON与Java序列化:数据处理与转换的关键技术
  • Python爬虫实战:基于 Scrapy 框架的腾讯视频数据采集研究
  • 『Rust』Rust运行环境搭建
  • Linux笔记之通配符和正则表达式的区别
  • cocos creator 3.8如何在代码中打印drawcall,fps
  • Matlab 灰度质心法提取条纹中心线
  • Git的详细使用方法
  • 基于stm32的视觉物流机器人
  • 智慧城市新基建!图扑智慧路灯,点亮未来城市生活!
  • AWS云编排详解-Cloud Formation
  • 一文讲清楚CUDA与PyTorch、GPU之间的关系