【问题标题】:How to capture which treeview node is clicked如何捕获单击了哪个树视图节点
【发布时间】:2017-01-03 00:14:05
【问题描述】:

我使用 WinApi 创建了一个树视图控件。我想捕捉鼠标点击复选框。通知消息 NM_CLICK 包含 NMHDR,其中没有关于被单击节点的信息。由于单击的节点可能与选定的节点不同,因此应该有一种方法可以找到已选中或未选中的节点,它可以是 HTREEITEM,或者在向树视图添加项目时插入了 lParam。我想实时捕获检查/取消检查。如何指定选中/取消选中哪个节点?任何帮助或链接表示赞赏。 阿布扎德先生

【问题讨论】:

    标签: c winapi treeview


    【解决方案1】:

    我想实时捕捉检查/取消检查。我怎样才能 指定哪个节点被选中/取消选中?

    对于此存在通知 TVN_ITEMCHANGINGTVN_ITEMCHANGED - 寻找 uStateNewuStateOld 的成员 NMTVITEMCHANGE - 当树视图有复选框(TVS_CHECKBOXES 样式)时,它用作带有 2 个图像的状态图像列表- uncheckedchecked

    所以state & TVIS_STATEIMAGEMASK 将在没有复选框时为0INDEXTOSTATEIMAGEMASK(1) 为未选中,INDEXTOSTATEIMAGEMASK(2) 为选中。基于此信息,我们可以捕获鼠标单击复选框

    通过使用TVN_ITEMCHANGING,您还可以在为此通知返回 TRUE 时阻止更改。如果您只需要通知 - 使用 TVN_ITEMCHANGED

        case WM_NOTIFY:
            {
                union {
                    LPARAM lp;
                    NMTVITEMCHANGE  *pnm;
                    NMHDR* phdr;
                };
                lp = lParam;
    
                switch (phdr->code)
                {
                case TVN_ITEMCHANGING:
                    {
                        UINT CheckStateOld = pnm->uStateOld & TVIS_STATEIMAGEMASK;
                        UINT CheckStateNew = pnm->uStateNew & TVIS_STATEIMAGEMASK;
    
                        if (CheckStateNew != CheckStateOld)
                        {
                            PCSTR szstate = "??";
                            switch (CheckStateNew)
                            {
                            case INDEXTOSTATEIMAGEMASK(1):
                                szstate = "uncheck";
                                break;
                            case INDEXTOSTATEIMAGEMASK(2):
                                szstate = "check";
                                break;
                            }
                            DbgPrint("%p>%s\n", pnm->lParam, szstate);
                        }
                    }
                    return FALSE;
                }
            }
    

    另请阅读How to Work With State Image Indexes

      // Image 1 in the tree-view check box image list is the unchecked box. 
      // Image 2 is the checked box.
    
      tvItem.state = INDEXTOSTATEIMAGEMASK((fCheck ? 2 : 1));
    

    通知TVN_ITEMCHANGINGTVN_ITEMCHANGED 从Windows Vista 开始可用。如果你也需要 XP 支持 - 在 xp 选项上使用 @IInspectable solution

    【讨论】:

    • 值得一提的是,TVN_ITEMCHANGING 从 Vista 开始可用,否则 OP 必须使用命中测试。
    • @AlwaysLearningNewStuff 是的..,我想念这个。我的错误
    • 不是一个错误,只是需要提一下。我赞成你的回答。
    【解决方案2】:

    您可以发送TVM_HITTEST 消息(或使用TreeView_HitTest 宏)在给定客户端相对坐标的情况下查找树视图项。

    要在生成NM_CLICK 消息时获取光标位置,请使用GetMessagePos API。

    这允许您监视控件客户区域中的任何鼠标单击。如果您对标准树视图控件实现导致的状态更改感兴趣,则可以改为处理TVN_ITEMCHANGINGTVN_ITEMCHANGED 通知。两者都提供NMTVITEMCHANGE 结构,其中hItem 标识正在更改的项目,lParam 携带特定于应用程序的数据。

    【讨论】:

    • 否决 OP 问题的糟糕且无效的解决方案 - “我如何指定哪个节点被选中/取消选中?”
    • 您添加了有关 TVN_ITEMCHANGINGTVN_ITEMCHANGED 通知的信息已经在我用这个写了自己的答案 - 这在编辑历史记录中可见。这就是最小的不好:)
    • @RbMm:由于您还没有完全掌握这个地方的运作方式,请收下tour 并访问help center。采纳来自反馈的建议正确的做法。
    • @RbMm:你为什么坚持,你不需要使用tour?它可能只是告诉你一两件事你不知道。
    • 值得一提的是,TVN_ITEMCHANGING 从 Vista 开始可用,否则 OP 必须使用命中测试。
    猜你喜欢
    • 2011-03-18
    • 2013-07-13
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多