Создание модального окна win32 с помощью CreateWindow - PullRequest
15 голосов
/ 09 апреля 2009

Я создаю окно с CreateWindow() и показываю его с ShowWindow(). Но родительское окно, в котором оно было создано, должно быть отключено до тех пор, пока пользователь не вернется из этого окна, т.е. оно должно имитировать модальное диалоговое окно.

Ответы [ 5 ]

18 голосов
/ 10 апреля 2009

Убедитесь, что вы установили hwndParent в CreateWindow и используете EnableWindow(hwndParent, FALSE), чтобы отключить родительский элемент после отображения всплывающего окна. Затем включите родительский элемент с помощью EnableWindow(hwndParent, TRUE) после закрытия всплывающего окна.

13 голосов
/ 09 апреля 2009

Модальность, часть 1: UI-модальность против кодовой модальности объясняет, как это сделать, и почему вы можете этого не хотеть.

3 голосов
/ 09 апреля 2009

Вы должны рассмотреть, что значит быть модальным окном - в основном родитель окна отключен. Единственный автоматический способ сделать это (что мне известно) - вызвать DialogBox(), чтобы создать модальное диалоговое окно. Однако, поскольку вы хотите использовать CreateWindow(), все, что вам нужно сделать, - это вручную отключить родительское окно.

В идеале было бы лучше пойти по пути диалогового окна (поскольку ОС точно знает, что необходимо сделать для создания модального окна), но я полагаю, что эта опция есть, если вы должны ее использовать.

2 голосов
/ 31 мая 2010

Вы также можете запустить «вторичный цикл сообщений», в котором родительское окно будет неактивным, пока ваша работа с «модальным» диалогом не будет завершена.

0 голосов
/ 15 января 2018

Хорошо, я сам боролся с этой же проблемой. Мне нужен был быстрый диалог, который бы вел себя так, как если бы я использовал 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 класса и устанавливается, если в диалоговом окне доступны кнопки «ОК» или «Отмена», а также при определенных других условиях, выходящих за рамки фрагмента кода.

...