使用CreateWindow创建win32模式窗口

时间:2022-04-01 06:53:56

I create a window with CreateWindow() and show it with ShowWindow(). But the parent window on which this was created should be disabled until user returns from this window, i.e. it should simulate modal dialog box.

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

5 个解决方案

#1


Make sure you set the hwndParent in CreateWindow and use EnableWindow(hwndParent, FALSE) to disable the parent after showing the pop up window. Then enable the parent with EnableWindow(hwndParent, TRUE) after the pop up window has been closed.

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

#2


Modality, part 1: UI-modality vs code-modality explains how to do this, and why you might not want to.

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

#3


You need to consider what it means to be a modal window - basically, the window's parent is disabled. The only automatic way of doing this (that I am aware of) is to call DialogBox() to create a modal dialog box. However, since you want to use CreateWindow(), then all that you need to do is to manually disable the parent window yourself.

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

Ideally, it would be better to go the dialog box route (since the OS knows exactly what must be done in order to create a modal window), but I suppose this option is there if you must use it.

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

#4


You could also run a "secondary message loop" which keeps the parent window inactive till your work with the "modal" dialog is finished.

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

#5


Okay I just wrestled with this same problem myself. I needed a quick dialog that behaved like it would if I used DialogBox() but I didn't want to create a template for the particular project I was using.

好吧,我自己也在解决同样的问题。我需要一个快速的对话框,其表现就像我使用DialogBox()时那样,但我不想为我正在使用的特定项目创建模板。

What I discovered is that if you disable the parent window of the dialog you also disable the dialog. And you can't enable that dialog without re-enabling the parent dialog. So that method won't work.

我发现如果您禁用对话框的父窗口,您也会禁用该对话框。如果不重新启用父对话框,则无法启用该对话框。所以这种方法不起作用。

I also discovered that you can't use SetCapture() / ReleaseCapture() because then the child windows of the dialog won't get messages.

我还发现你不能使用SetCapture()/ ReleaseCapture(),因为那时对话框的子窗口不会得到消息。

I did find a solution that works: Use a local message pump, driven by either PeekMessage() or GetMessage(). Here is the code that worked for me:

我找到了一个有效的解决方案:使用本地消息泵,由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);
        }
     }
  }

What this effectively does is "eat" any mouse messages that are outside the client area of the window for all messages delivered to that application. It does not prohibit clicking outside the application, just clicking anywhere inside the application that isn't within the client area of the "modal" window. If you add a MessageBeep() when you eat a message you'll get the exact same behavior as a real modal dialog.

这实际上做的是“吃掉”窗口客户区域之外的任何鼠标消息,以便传递给该应用程序的所有消息。它不禁止在应用程序外部单击,只需单击应用程序内不在“模态”窗口的客户区域内的任何位置。如果您在吃消息时添加MessageBeep(),您将获得与真实模态对话框完全相同的行为。

m_bFinished is a BOOL member of the class and it gets set if either the OK or Cancel buttons are accessed on the "dialog," and under certain other conditions that are outside the scope of the code snippet here.

m_bFinished是类的BOOL成员,如果在“对话框”*问“确定”或“取消”按钮,并且在此处的代码片段范围之外的某些其他条件下,它将被设置。

#1


Make sure you set the hwndParent in CreateWindow and use EnableWindow(hwndParent, FALSE) to disable the parent after showing the pop up window. Then enable the parent with EnableWindow(hwndParent, TRUE) after the pop up window has been closed.

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

#2


Modality, part 1: UI-modality vs code-modality explains how to do this, and why you might not want to.

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

#3


You need to consider what it means to be a modal window - basically, the window's parent is disabled. The only automatic way of doing this (that I am aware of) is to call DialogBox() to create a modal dialog box. However, since you want to use CreateWindow(), then all that you need to do is to manually disable the parent window yourself.

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

Ideally, it would be better to go the dialog box route (since the OS knows exactly what must be done in order to create a modal window), but I suppose this option is there if you must use it.

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

#4


You could also run a "secondary message loop" which keeps the parent window inactive till your work with the "modal" dialog is finished.

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

#5


Okay I just wrestled with this same problem myself. I needed a quick dialog that behaved like it would if I used DialogBox() but I didn't want to create a template for the particular project I was using.

好吧,我自己也在解决同样的问题。我需要一个快速的对话框,其表现就像我使用DialogBox()时那样,但我不想为我正在使用的特定项目创建模板。

What I discovered is that if you disable the parent window of the dialog you also disable the dialog. And you can't enable that dialog without re-enabling the parent dialog. So that method won't work.

我发现如果您禁用对话框的父窗口,您也会禁用该对话框。如果不重新启用父对话框,则无法启用该对话框。所以这种方法不起作用。

I also discovered that you can't use SetCapture() / ReleaseCapture() because then the child windows of the dialog won't get messages.

我还发现你不能使用SetCapture()/ ReleaseCapture(),因为那时对话框的子窗口不会得到消息。

I did find a solution that works: Use a local message pump, driven by either PeekMessage() or GetMessage(). Here is the code that worked for me:

我找到了一个有效的解决方案:使用本地消息泵,由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);
        }
     }
  }

What this effectively does is "eat" any mouse messages that are outside the client area of the window for all messages delivered to that application. It does not prohibit clicking outside the application, just clicking anywhere inside the application that isn't within the client area of the "modal" window. If you add a MessageBeep() when you eat a message you'll get the exact same behavior as a real modal dialog.

这实际上做的是“吃掉”窗口客户区域之外的任何鼠标消息,以便传递给该应用程序的所有消息。它不禁止在应用程序外部单击,只需单击应用程序内不在“模态”窗口的客户区域内的任何位置。如果您在吃消息时添加MessageBeep(),您将获得与真实模态对话框完全相同的行为。

m_bFinished is a BOOL member of the class and it gets set if either the OK or Cancel buttons are accessed on the "dialog," and under certain other conditions that are outside the scope of the code snippet here.

m_bFinished是类的BOOL成员,如果在“对话框”*问“确定”或“取消”按钮,并且在此处的代码片段范围之外的某些其他条件下,它将被设置。