【问题标题】:How to detect a selection change in my WTL::CListViewCtrl, and not in the parent?如何检测我的 WTL::CListViewCtrl 中的选择更改,而不是父级中的更改?
【发布时间】:2013-03-03 03:11:05
【问题描述】:

我有自己的 WTL 派生列表控件。

CPopupList : public CWindowImpl<CPopupList, WTL::CListViewCtrl>,

它工作正常,除了一件事:我想在选择更改时捕获通知。不在父窗口中(像这样:How to detect a CListCtrl selection change?),而是在CPopupList本身,然后做一些事情。

实际上,我希望在当前所选项目旁边出现一个小提示窗口,作为当前项目的附加信息。就像 VS 在自动完成期间所做的那样,提供有关函数/属性的更多信息。

有没有人提示如何做到这一点? 非常感谢。


更新:

试过了:

BEGIN_MSG_MAP(CPopupList)
    REFLECTED_NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnListItemChanged)
    DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()

但是 OnListItemChanged() 没有被调用。 在父级中

REFLECT_NOTIFICATIONS()

已添加。


Update2 - 解决方案

我发现了问题:

父母的MSG_HANDLER:

BEGIN_MSG_MAP(CEditorCtrl)
    MESSAGE_RANGE_HANDLER(WM_KEYFIRST,WM_KEYLAST,DelegateMessages)
    ...
    MESSAGE_
    ...
    NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED,OnListItemChanged)
    CHAIN_MSG_MAP(parentType)
    ALT_MSG_MAP(11)
    COMMAND_HANDLER(IDC_PRINT_MONOCHROME,BN_CLICKED,OnPrintMonochromeButton)
    REFLECT_NOTIFICATIONS()
END_MSG_MAP()

将 REFLECT_NOTIFICATIONS() 移到 ALT_MSG_MAP(11) 上方,最后在控件中调用 OnListItemChanged。

正确:

    REFLECT_NOTIFICATIONS()
    ALT_MSG_MAP(11)
    COMMAND_HANDLER(IDC_PRINT_MONOCHROME,BN_CLICKED,OnPrintMonochromeButton)

【问题讨论】:

    标签: listview visual-c++ wtl selectionchanged


    【解决方案1】:

    通知消息无论如何都会发送给父母,您无法更改此设置。您通常做的是从父母到孩子的消息反射,以便[改进的]孩子可以处理其祖先生成的通知。

    父窗口将在消息映射上有一个反射处理程序:

    #include <atlcrack.h>
    
    BEGIN_MSG_MAP_EX(CMyDialog)
        // ...
        REFLECT_NOTIFICATIONS()
    END_MSG_MAP()
    

    并且该控件将有一个处理由控件父级反映的 WM_NOTIFY 通知的处理程序:

    BEGIN_MSG_MAP_EX(CPopupList)
        // ...
        //MSG_OCM_CTLCOLORSTATIC(OnReflectedCtlColorStatic) // Reflected WM_CTLCOLORSTATIC
        MSG_OCM_NOTIFY(OnReflectedNotify) // Reflected WM_NOTIFY
        DEFAULT_REFLECTION_HANDLER()
    END_MSG_MAP()
    

    OnReflectedNotify 是您可以处理控件通知的地方,但父级负责转发它们(有或没有自己的处理)。

    另请参阅 WTL macros for handling reflected messages CodeProject 上的相关内容。

    【讨论】:

    • 谢谢。我的评论是,BEGIN_MSG_MAP_EX 和 MSG_OCM_NOTIFY 在编译期间都会出现语法错误。没有 _EX 的 BEGIN_MSG_MAP 有效。我尝试了什么:REFLECTED_NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnListItemChanged) 我会更新问题但不起作用
    • 你需要#include &lt;atlcrack.h&gt;(WTL的文件)
    • BEGIN_MSG_MAP_EX 是 ATL 的 BEGIN_MSG_MAP 的 WTL 增强
    • 将NOTIFY_CODE_HANDLER添加到父级,在父级中调用。奇怪的。但没有体现在孩子身上。用这个更新了问题
    • 终于!!我有解决办法。由于您的回复对我很有帮助,我接受它作为答案。将用答案更新问题
    【解决方案2】:

    OP 的问题已经解决。但是对于那些仍未收到通知消息的人,请继续阅读...

    你可能不得不subclass窗口!

    假设您已正确配置所有消息映射。通过调试器,您可以看到父对话框正在尝试将消息传递给控件。

    换句话说,您看到它调用SendMessage 来传递消息。如果WM_NOTIFY 被父控件反映,那么OCM_NOTIFY 将被发送到派生控件。

    然而,派生控件的消息处理程序中什么也没有发生。

    如果您的父窗口代码只执行MyDerivedControl.Attach(hwndControl) 之类的操作,那么您将不会在派生控件类上收到任何消息。在幕后Attach 将复制窗口句柄(HWND),仅此而已。为了能够处理来自派生控件的消息,系统需要设置其他几项。

    实际上,这意味着调用SubclassWindow 而不是Attach

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-05
      • 2010-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      • 2020-10-09
      • 1970-01-01
      相关资源
      最近更新 更多