19

我创建一个窗口CreateWindow()并用ShowWindow(). 但是创建它的父窗口应该被禁用,直到用户从这个窗口返回,即它应该模拟模式对话框。

4

5 回答 5

22

确保在显示弹出窗口后设置hwndParentinCreateWindow并使用来禁用父级。然后在弹出窗口关闭后EnableWindow(hwndParent, FALSE)启用父级。EnableWindow(hwndParent, TRUE)

于 2009-04-10T12:14:14.767 回答
14

模态,第 1 部分:UI 模态与代码模态解释了如何执行此操作,以及您可能不想这样做的原因。

于 2009-04-09T15:28:15.527 回答
4

您需要考虑成为模态窗口意味着什么 - 基本上,窗口的父级被禁用。这样做的唯一自动方法(我知道)是调用DialogBox()创建一个模式对话框。但是,既然要使用CreateWindow(),那么您需要做的就是自己手动禁用父窗口。

理想情况下,最好走对话框路线(因为操作系统确切地知道必须做什么才能创建模式窗口),但我想如果你必须使用它,这个选项就在那里。

于 2009-04-09T15:19:12.303 回答
3

您还可以运行“辅助消息循环”,使父窗口保持非活动状态,直到您使用“模态”对话框完成工作。

于 2010-05-31T12:09:18.557 回答
2

好吧,我自己也遇到了同样的问题。如果我使用 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 成员,如果在“对话框”上访问“确定”或“取消”按钮,并且在此处代码片段范围之外的某些其他条件下,它就会被设置。

于 2018-01-15T20:10:09.583 回答