简体   繁体   中英

Creating a win32 modal window with CreateWindow

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, ie it should simulate modal dialog box.

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.

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

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.

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.

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

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.

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.

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:

  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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM