【问题标题】:Consume events in MFC's CStatic and pass them to the parent消费 MFC 的 CStatic 中的事件并将它们传递给父级
【发布时间】:2010-01-18 00:13:34
【问题描述】:

我正在构建 MFC 应用程序,其中有 CDialog 以及从 CStatic 派生的子控件。

我想接收 CStatic 控件的鼠标事件,因此我将 "Notify" 设置为 true。现在我可以直接在MyStatic 中通过消息映射接收消息事件:

class CMyStatic : public CStatic { afx_msg void OnLButtonDown(UINT nFlags, CPoint point); // Gets invoked DECLARE_MESSAGE_MAP() }

问题是从现在开始,当鼠标悬停在MyStatic child 上时,父 CDialog 不会接收鼠标事件。我可以手动从MyStatic 发送它们,但有什么方法可以让它们自动通过?并且仍然可以使用消息映射在MyStatic 上接收它们?

【问题讨论】:

    标签: events mfc event-bubbling


    【解决方案1】:

    不,你误会了。 SS_NOTIFY 不会导致您的 CStatic 接收消息,它会导致 CStatic 将消息中继回父级。所以“现在我可以直接在 MyStatic 中通过消息映射接收消息事件”是基于一个错误的前提。

    这是很重要的一点,因为控件只能接收自身的消息,而不是其子级的消息,除非这些子级通过中继消息或通过其他技巧(全局挂钩, ...) ;但这些情况是例外,“正常”的方式是每个窗口都为自己接收消息。

    所以这回答了您的问题:不,没有办法让父母(您的 CDialog)和孩子(您的 CStatic)在不“手动”这样做或参与繁琐的消息路由黑客的情况下接收鼠标事件。因此,在您的情况下,您需要做的是 GetParent()->SendMessage(WM_LBUTTONDOWN, ...) 等,手动重新创建 WPARAM 和 LPARAM 值;或直接在 CDialog 上调用 OnLButtonDown:GetParent()->OnLButtonDown(...)。不过,您必须考虑将什么鼠标坐标传回给 CDialog,您可能需要将它们转换为 CDialog 的客户端坐标。

    【讨论】:

    • 罗尔,谢谢你的解释。但是,除非设置 SS_NOTIFY,否则我无法使用消息映射接收消息。也许这是一些奇怪的 MFC 行为?
    • 尝试在 CStatic 中捕获 WM_MOUSEMOVE 并在其中执行 SetFocus()。
    【解决方案2】:

    如果您调用基本 OnLButtonDown 处理程序,则应将消息发送到父级。

    CMyStatic::OnLButtonDown(UINT nFlags, CPoint point)
    {
        CStatic::OnLButtonDown(nFlags, point);
    
        // custom handling
    }
    

    【讨论】:

    • 这对我不起作用。我必须将GetParent()->SendMessage(WM_COMMAND, GetDlgCtrlID() | WM_LBUTTONDOWN << 16, (LONG) GetSafeHwnd()); 放入我的 CMyStatic::OnLButtonDown() 方法中才能完成这项工作。 WM_LBUTTONUP 和 CMyStatic::OnLButtonUp() 也是如此。 this page 建议使用该技术。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    • 2015-10-29
    相关资源
    最近更新 更多