Создание модального окна win32 с помощью CreateWindow

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

Ответы

Ответ 1

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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