我创建一个窗口CreateWindow()
并用ShowWindow()
. 但是创建它的父窗口应该被禁用,直到用户从这个窗口返回,即它应该模拟模式对话框。
5 回答
确保在显示弹出窗口后设置hwndParent
inCreateWindow
并使用来禁用父级。然后在弹出窗口关闭后EnableWindow(hwndParent, FALSE)
启用父级。EnableWindow(hwndParent, TRUE)
模态,第 1 部分:UI 模态与代码模态解释了如何执行此操作,以及您可能不想这样做的原因。
您需要考虑成为模态窗口意味着什么 - 基本上,窗口的父级被禁用。这样做的唯一自动方法(我知道)是调用DialogBox()
创建一个模式对话框。但是,既然要使用CreateWindow()
,那么您需要做的就是自己手动禁用父窗口。
理想情况下,最好走对话框路线(因为操作系统确切地知道必须做什么才能创建模式窗口),但我想如果你必须使用它,这个选项就在那里。
您还可以运行“辅助消息循环”,使父窗口保持非活动状态,直到您使用“模态”对话框完成工作。
好吧,我自己也遇到了同样的问题。如果我使用 DialogBox(),我需要一个快速对话框,但我不想为我正在使用的特定项目创建模板。
我发现如果你禁用对话框的父窗口,你也会禁用对话框。如果不重新启用父对话框,您将无法启用该对话框。所以这种方法行不通。
我还发现您不能使用 SetCapture() / ReleaseCapture() 因为对话框的子窗口不会收到消息。
我确实找到了一个可行的解决方案:使用由 PeekMessage() 或 GetMessage() 驱动的本地消息泵。这是对我有用的代码:
while (!m_bFinished)
{
BOOL bEat;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_CHAR)
{
if (msg.wParam == VK_ESCAPE)
{
m_bFinished = TRUE;
continue;
}
}
bEat = FALSE;
if (msg.message >= WM_MOUSEFIRST &&
msg.message <= WM_MOUSELAST)
{
RECT rectMe;
pcMe->GetWindowRect(&rectMe);
if (!::PtInRect(&rectMe, msg.pt))
bEat = TRUE;
}
if (!bEat)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
对于传递给该应用程序的所有消息,这实际上会“吃掉”窗口客户区域之外的任何鼠标消息。它不禁止在应用程序外部单击,只需单击应用程序内部不在“模态”窗口客户区域内的任何位置。如果您在接收消息时添加 MessageBeep(),您将获得与真正的模态对话框完全相同的行为。
m_bFinished 是该类的 BOOL 成员,如果在“对话框”上访问“确定”或“取消”按钮,并且在此处代码片段范围之外的某些其他条件下,它就会被设置。