【发布时间】:2019-07-16 23:30:06
【问题描述】:
我有一个非常奇怪的问题。我正在尝试复制要复制的窗口层次结构。因此,在创建第一级对话框时,我将启动第二级对话框的实例。
我以许多不同的方式做到了这一点,但它总是显示为 2 级低于 1 级,然后通常会发生 zorder 反转(它们翻转位置)。偶尔,倒置不会发生,但是如果我点击所有者,所有者会立即跳转到 zorder 的顶部。
这里有一个小例子的主要部分来展示这种情况:
const unsigned short WMA_DIALOGACTION = WM_APP+1;
// Button event handler for the 0th level
void CdialogcallingdialogsDlg::OnBnClickedDlgLvl1()
{
CDlgLvl1 x(this);
x.DoModal();
}
BEGIN_MESSAGE_MAP(CDlgLvl1, CDialogEx)
ON_WM_WINDOWPOSCHANGED()
ON_MESSAGE(WMA_DIALOGACTION, OnDialogAction)
END_MESSAGE_MAP()
void CDlgLvl1::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
if (!m_shownDlg) {
m_shownDlg = true;
PostMessage(WMA_DIALOGACTION);
}
}
// Level 1 dialog opening up level 2 dialog
LRESULT CDlgLvl1::OnDialogAction(WPARAM wParam, LPARAM lParam)
{
ShowWindow(SW_SHOW);
CDlgLvl2 x(this);
x.DoModal();
return LRESULT();
}
BEGIN_MESSAGE_MAP(CDlgLvl2, CDialogEx)
ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()
// Level 2 dialog offseting its position
void CDlgLvl2::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
ASSERT(lpwndpos->hwnd == m_hWnd);
// Offset dialog to see the problem of dlg2 showing up below dlg1
if (!(lpwndpos->flags & SWP_NOMOVE)) {
lpwndpos->x += 10;
lpwndpos->y += 10;
}
}
在示例中,您单击主对话框中的按钮。然后启动CDlgLvl1,然后启动CDlgLvl2。除了此处显示的消息处理和主应用程序对话框上的按钮之外,这些对话框是默认对话框。如果你仔细看,你可以看到倒置。
我做错了什么?也许有更好的方法来做到这一点?
如果有影响,这个问题在 Windows 10 下更为明显,在 Windows 8.1 上似乎不可见。
可以在此处从我的 git 存储库中提取解决方案的副本:
https://github.com/Ma-XX-oN/dialog-calling-dialogs.git
我刚刚在对话框中添加了一些位图来真正显示问题,但我还没有在我的 8.1 机器上进行测试。
我记录了它是如何弹出的,这里是该记录的第 0、2 和 3 帧:
如您所见,LVL1 在第 2 帧出现在 LVL2 上方,然后在第 3 帧翻转位置。
完整视频可以在here找到。
使用这个示例项目,我无法复制 LVL1 并保持在 LVL2 之上,但我相信 zorder 反转的行为没有发生是某种竞争条件。
【问题讨论】:
-
OnDialogAction()中的ShowWindow(SW_SHOW);是什么意思? -
您介意分享一个完整的示例 .cpp 我可以粘贴到 Visual Studio 中并编译吗?
-
@ConstantineGeorgiou,在显示第二级之前调出(第一级)窗口。否则,在第二级窗口关闭之前它不会显示。
-
覆盖
CDlgLvl1::OnInitDialog并输入DWORD attrib = TRUE; DwmSetWindowAttribute(m_hWnd, DWMWA_TRANSITIONS_FORCEDISABLED, &attrib, sizeof(attrib));以确保立即显示CDlgLvl1。 -
这非常很有趣@BarmakShemirani。所以这指向一个窗口管理器问题。如果您将此作为答案发布,我会将其标记为已接受的答案。