【问题标题】:How to subclass Windows Common Controls?如何继承 Windows 公共控件?
【发布时间】:2015-08-16 07:48:35
【问题描述】:

我有问题。 我像这样子类化我的 TreeView:

SetWindowSubclass(hTV, SubClassProc, 0, 0);

其中 hTv - 由 CreateWindowEx 生成的 WC_TREEVIEW 窗口句柄。 这是我的 SubClassProc:

LRESULT CALLBACK    SubClassProc(HWND hWnd, UINT uMsg, WPARAM wParam,
                                 LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
    case TVM_EXPAND:
        // This line of code is never executed
        MessageBox(NULL, _T("I'm expanded"), _T("TreeView"), MB_ICONINFORMATION);
        break;
    case WM_NCDESTROY:
        RemoveWindowSubclass(hWnd, SubClassProc, uIdSubclass);
        break;
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

为什么我不能处理 TVM_EXPAND 消息?我的代码有什么问题?

我上传了我的项目here

【问题讨论】:

  • 不清楚您在问什么,但我想您想知道为什么当您单击 + 号以展开树的分支时看不到 TVM_EXPAND。这是因为树不会将TVM_EXPAND 发送给它自己。如果您想捕获 all 扩展,则需要对树的 parent 进行子类化并注意 TVN_ITEMEXPANDING 通知消息。
  • 好的,我去试试。但是除了树视图控件,还有谁可以收到TVM_EXPAND?如果我是发件人(或其他任何人),则必须有人处理此邮件。
  • @Jonathan Potter,请将您的评论格式化为答案。从技术上讲,它工作正常。但是语义呢?现在,我仍然是一个独立的控件,但我的父母似乎不是这样。如果其他人在我之后/之前打电话给SetWindowSubclass 怎么办?那会发生什么?
  • SetWindowSubclass 为您处理,无需担心。
  • 正如用户 IInspectable 所指出的,我已经尝试处理树展开/折叠节点时的所有其他情况,但这太过分了。我会强烈建议您按照其他答案建议的方式做事 -> 通过通知消息。我已经删除了我的答案,以免误导其他有同样问题的读者。如果您仍然希望继续“我的方式”,请发表评论,我将取消删除答案。最好的问候。

标签: c user-interface winapi subclassing


【解决方案1】:

这是在主窗口过程中处理的。在这种情况下不需要子类。

检查 TVN_ITEMEXPANDED,这是在项目展开时收到的通知。如需展开项目,请发送TVM_EXPAND 消息。

另见:
- TreeView send Messages(例如:TVM_EXPAND
- TreeView receive Notifications(例如:TVN_ITEMEXPANDED

BOOL CALLBACK mainProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lParam)
{
    switch (msg)
    {

    case WM_NOTIFY:
    {
        LPNMHDR hdr = (LPNMHDR)lParam;
        if (hdr->hwndFrom == hWndTree && hdr->code == TVN_ITEMEXPANDED)
        {
            MessageBox(hwnd, _T("I'm expanded"), _T("TreeView"), MB_ICONINFORMATION);
            break;
        }
        break;
    }
    ...    
}

【讨论】:

  • 要是这么简单,我就不会发这个帖子了。有一件事。我需要获得绝对独立的控制权。我无法访问主窗口过程。我只需要修改标准行为。子类化是我唯一的方法。
  • 根据 MSDN TVN_ITEMEXPANDING 通知树视图控件的父窗口... 并且可能会将 TVM_EXPAND 发送给控件。
  • 你需要继承TreeView的父窗口来拦截从TreeView发送的TVN_...notifications。 TVM_... 消息不是通知,它们是发送到 TreeView 以执行操作和查询数据的消息。您可以使用SetWindowSubclass(GetParent(hTV), ...) 子类化父窗口。
  • 你可以包装控件。创建您自己的作为树视图的父窗口,并让您的客户创建您的父控件。这是一种标准技术。
  • 这是TVM_EXPAND 的用法:SendMessage(hTree, TVM_EXPAND, TVE_TOGGLE, (LPARAM)hItem); 此消息不是由 Windows 或 TreeView 生成的。您自己(以编程方式)发送它以展开/折叠树项,它可以在 TreeView 的子类中捕获。然而,对于用户输入,TreeView 将处理输入并为父窗口生成TVN_X 消息。先处理TVN_ITEMEXPANDED。稍后您可以测试发送TVM_EXPAND 以确保该部分也可以正常工作。我认为TVM_EXPAND 会为父母生成TVN_ITEMEXPANDED 消息,但它只会这样做一次。另见TVIS_EXPANDEDONCE
猜你喜欢
  • 1970-01-01
  • 2011-01-05
  • 2011-03-11
  • 2015-07-14
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多