2009-04-09 387 views

回答

3

你需要考虑它是什么意思是模态窗口 - 基本上,窗口的父项被禁用。这样做的唯一自动方法(我知道)是调用DialogBox()创建一个模态对话框。但是,由于您想使用CreateWindow(),所以您只需手动禁用父窗口即可。理想情况下,最好是去对话框路由(因为操作系统确切地知道必须做什么才能创建一个模式窗口),但是如果你必须使用它,我想这个选项是存在的。

12

Modality, part 1: UI-modality vs code-modality解释如何做到这一点,为什么你可能不希望。

+6

作为一个规则,我投票的所有旧新事物的参考。 – Aardvark 2009-04-09 15:38:15

+0

旧的新事物引用是伟大的,但太糟糕了,这是一个链接唯一的答案。您可能需要用自己的文字重新翻译文章中的某些内容。 – jrh 2017-12-28 16:55:35

16

确保在CreateWindow设置hwndParent和使用​​显示弹出窗口后,禁用父。然后在弹出窗口关闭后启用EnableWindow(hwndParent, TRUE)

2

你也可以运行一个“二级消息循环”,这一直不活跃的父窗口,直到您的工作与“模式”对话框完成。

0

好吧我只是自己与这个相同的问题摔跤。我需要一个快速的对话框,如果我使用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成员,如果在“对话框”上以及在此代码片段范围之外的某些其他条件下访问了“确定”或“取消”按钮,它将被设置。

相关问题