2009-04-09 47 views
13

Creo una ventana con CreateWindow() y la muestro con ShowWindow(). Pero la ventana principal en la que se creó debe estar desactivada hasta que el usuario regrese desde esta ventana, es decir, debe simular un cuadro de diálogo modal.Creando una ventana modal win32 con CreateWindow

Respuesta

3

Debe considerar lo que significa ser una ventana modal; básicamente, el elemento primario de la ventana está deshabilitado. La única forma automática de hacer esto (que yo sepa) es llamar al DialogBox() para crear un cuadro de diálogo modal. Sin embargo, dado que desea utilizar CreateWindow(), todo lo que necesita hacer es deshabilitar manualmente la ventana primaria.

Idealmente, sería mejor ir a la ruta del cuadro de diálogo (ya que el sistema operativo sabe exactamente lo que se debe hacer para crear una ventana modal), pero supongo que esta opción está ahí si debe usarla.

12

Modality, part 1: UI-modality vs code-modality explica cómo hacerlo y por qué es posible que no desee hacerlo.

+6

Como regla, voto todas las referencias de Old New Thing. – Aardvark

+0

Las referencias Old New Thing son geniales, pero es una respuesta negativa. Es posible que desee reformular algún contenido del artículo en sus propias palabras. – jrh

16

Asegúrese de configurar el hwndParent en CreateWindow y use EnableWindow(hwndParent, FALSE) para deshabilitar el elemento principal después de mostrar la ventana emergente. A continuación, habilite el elemento principal con EnableWindow(hwndParent, TRUE) después de que se haya cerrado la ventana emergente.

+3

Tiene que 'EnableWindow (hwndParent, TRUE)' * antes * de que la ventana emergente esté cerrada, consulte [El orden correcto para deshabilitar y habilitar ventanas] (http://blogs.msdn.com/b/oldnewthing/archive/2004 /02/27/81155.aspx) –

2

También podría ejecutar un "bucle de mensaje secundario" que mantiene inactiva la ventana primaria hasta que finalice su trabajo con el cuadro de diálogo "modal".

0

Bien Acabo de pelear con este mismo problema yo mismo. Necesitaba un diálogo rápido que se comportara como lo haría si usara DialogBox() pero no quería crear una plantilla para el proyecto en particular que estaba usando.

Lo que descubrí es que si deshabilita la ventana primaria del cuadro de diálogo, también deshabilita el cuadro de diálogo. Y no puede habilitar ese diálogo sin volver a habilitar el cuadro de diálogo principal. Entonces ese método no funcionará

También descubrí que no puede usar SetCapture()/ReleaseCapture() porque las ventanas secundarias del cuadro de diálogo no recibirán mensajes.

Encontré una solución que funciona: utilice una bomba de mensajes local, impulsada por PeekMessage() o GetMessage(). Aquí está el código que funcionó para mí:

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); 
     } 
    } 
    } 

Lo que esto hace es efectivamente "comer" cualquier mensaje de ratón que se encuentran fuera del área de cliente de la ventana de todos los mensajes entregados a esa aplicación. No prohíbe hacer clic fuera de la aplicación, simplemente haciendo clic en cualquier lugar dentro de la aplicación que no se encuentre dentro del área del cliente de la ventana "modal". Si agrega un MessageBeep() cuando come un mensaje obtendrá exactamente el mismo comportamiento que un diálogo modal real.

m_bFinished es un miembro BOOL de la clase y se establece si se accede a los botones Aceptar o Cancelar en el "cuadro de diálogo" y en otras condiciones que están fuera del alcance del fragmento de código aquí.

Cuestiones relacionadas