MFC(C++):为啥顶部的控件不接收事件?

Posted

技术标签:

【中文标题】MFC(C++):为啥顶部的控件不接收事件?【英文标题】:MFC (C++): Why control on top does not receive event?MFC(C++):为什么顶部的控件不接收事件? 【发布时间】:2020-02-05 23:25:42 【问题描述】:

在设计阶段,

A(列表框)在 B(列表 Ctrl)之前绘制 A 最初是不可见的 A 覆盖 B 的一部分

在运行时,按钮切换 A 的可见性,当 A 可见时,将其置于 B 之上(使用 SetWindowPos(...))。

显示A时,不接收重叠区域的事件(例如,当我点击下图中的“item 4”和“item 5”时)。为什么以及如何解决?

可在此处访问示例代码https://138.197.210.223/test/test.zip。

【问题讨论】:

什么是 A 和 B?当没有重叠时,您会收到“事件”消息吗? 我猜你说的是对话资源。您尝试使用 tab 顺序(这是控件在脚本中出现的顺序 - 不,您不能指定绘图顺序)和 clip-siblings 属性(样式)。当然,控件 A 必须能够接收鼠标输入。您也可以尝试以编程方式设置 Z 顺序。 @ConstantineGeorgiou,你是对的,A 在 B 后面有跳位顺序。另一点:最初 A 的可见是错误的。有影响吗?无论如何,我看到 A 覆盖 B,但是当我单击重叠区域时,A 没有响应。如果我删除 B,A 会有响应。 尝试在 Tab 键顺序中将控件 A 放在 B 之前。如果 B 在此设置中隐藏 A,请为 B 设置剪辑兄弟样式。这应该可以。但我不知道这样的 UI 设计(即 A 在选项卡顺序中位于 B 之前)是否可以接受(尽管我无法想象两个重叠控件都接受用户输入的设计)。或者,您可以尝试从 B 中删除 Notify 样式(同样,如果可以接受的话)。 @ConstantineGeorgiou,我编辑问题,请看一下,谢谢。我也在 rc 文件中尝试了您对“WS_CLIPSIBLINGS”的建议,但它不起作用。 【参考方案1】:

我确实检查了代码,发现问题是由OnBnClickedCheck1()中的::SetWindowPos()命令引起的。您调用它来解决绘图问题,但您通过更改 Z-Order 来解决此问题,这会导致 B 控件改为捕获输入。所以必须去掉,OnBnClickedCheck1()中的代码可以改成如下图(我已经简化了语法,用的是MFC,而不是WinAPI命令):

void CTestDlgActXDlg::OnBnClickedCheck1()

        m_list_A.ShowWindow(m_list_A.IsWindowVisible() ? SW_HIDE : SW_SHOW);

绘制问题可以通过在资源脚本中设置WS_CLIPSIBLINGS样式来解决,如cmets中所建议的:

.
.
LISTBOX         IDC_LIST_A,114,36,48,42,LBS_SORT | LBS_NOINTEGRALHEIGHT | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP
CONTROL         "",IDC_LIST_B,"SysListView32",LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP | WS_CLIPSIBLINGS,108,60,60,54
.
.

这种方式对我有用,A 控件优先于 B,并针对单击的任何项目发送 LBN_SELCHANGE 通知。

我注意到一些奇怪的事情,testdlg.cpp 中的DDX_Control(pDX, IDC_LIST_B, m_list_B); 命令运行了两次。删除第二次通话。

顺便说一句,奇怪的 UI 设计。 ?

【讨论】:

你的解决方案很完美,非常感谢你的帮助!!

以上是关于MFC(C++):为啥顶部的控件不接收事件?的主要内容,如果未能解决你的问题,请参考以下文章

WS_EX_LAYERED 父级的 Win32 编辑控件在其背景透明时不接收鼠标/单击事件

(MFC) 如果控件是私有成员,父类如何接收控件的消息?

MFC OnTimer 从其他地方接收额外事件

控件不接收用户交互的情况以及事件响应顺序

在 MFC 中,非活动窗口是不是接收 PreTranslateMessage 事件?

为啥我的编辑控件在没有使用 MFC 的 win32 c++ 应用程序中看起来很奇怪?