2008-09-09 19 views
5

Cuando una aplicación está detrás de otras aplicaciones y hago clic en el icono de la barra de tareas de mi aplicación, espero que toda la aplicación en llegue al principio del orden z, incluso si un cuadro de diálogo de aplicación modal WS_POPUP es abierto.¿Por qué hacer clic en una ventana secundaria no siempre trae la aplicación al primer plano?

Sin embargo, algunas veces, para algunos de los cuadros de diálogo (y otros), solo aparece el cuadro de diálogo; el resto de la aplicación se queda atrás.

He examinado Spy ++ y para las que funcionan correctamente, puedo ver WM_WINDOWPOSCHANGING siendo enviado al elemento primario del diálogo. Para los que abandonan el resto de la aplicación, WM_WINDOWPOSCHANGING no se está enviando al elemento primario del diálogo.

Tengo un ejemplo en el que un diálogo generalmente trae toda la aplicación y el otro no. Tanto el cuadro de diálogo de trabajo como el cuadro de diálogo que no funciona tienen el mismo estilo de ventana, subestilo, principal, propietario, ontogenia.

En resumen, ambas ventanas WS_POPUPWINDOW creadas con DialogBoxParam(), han pasado en HWND idénticos como el tercer argumento.

¿Alguien más ha notado esta rareza de comportamiento en los programas de Windows? ¿Qué mensajes envía TaskBar a la aplicación cuando hago clic en su botón? ¿Quién es la responsabilidad de asegurarse de que todos de las ventanas de la aplicación salgan al primer plano?

En mi caso, el origen de la base es un marco MDI ... ¿eso tiene algún factor?

Respuesta

0

¿La ventana primaria del cuadro de diálogo está configurada correctamente?

Después de publicar esto, inicié mi propia aplicación Windows Forms y reproduje el problema que describes. Tengo dos diálogos, uno funciona correctamente y el otro no, y no veo ninguna razón inmediata para explicar por qué se comportan de manera diferente. Actualizaré esta publicación si me entero.

Raymond Chen, donde estás!

1

Al hacer clic en el icono de la barra de tareas, Windows enviará un mensaje WM_ACTIVATE a su aplicación.

¿Está seguro de su código está pasando el WM_ACTIVATE mensaje al procedimiento de ventana DefWindowProc para procesamiento?

4

Sé que esto es muy viejo ahora, pero me topé con él, y sé la respuesta.

En las aplicaciones que he visto (y escrito), donde lo que el cuadro de diálogo al primer plano hicieron no traer la ventana principal de arriba junto con él, el desarrollador ha descuidado simplemente para especificar el propietario del cuadro de diálogo.

Esto se aplica tanto a ventanas modales, como cuadros de diálogo y cuadros de mensaje, como a ventanas sin modo. Configurar al propietario de una ventana emergente no modal también mantiene la ventana emergente por encima de su propietario en todo momento.

En la API de Win32, las funciones para que aparezca un cuadro de diálogo o un cuadro de mensaje tomar la ventana propietaria como parámetro:

INT_PTR DialogBox(
    HINSTANCE hInstance, 
    LPCTSTR lpTemplate, 
    HWND hWndParent,  /* this is the owner */ 
    DLGPROC lpDialogFunc 
); 

int MessageBox(
    HWND hWnd,   /* this is the owner */ 
    LPCTSTR lpText, 
    LPCTSTR lpCaption, 
    UINT uType 
); 

De manera parecida, en .NET WinForms, el propietario puede especificar:

public DialogResult ShowDialog(
    IWin32Window owner 
) 

public static DialogResult Show(
    IWin32Window owner, 
    string text 
) /* ...and other overloads that include this first parameter */ 

Además, en Windows Forms, es fácil de configurar el dueño de una ventana modal:

public void Show(
    IWin32Window owner, 
) 

o, equivalentemente:

form.Owner = this; 
form.Show(); 

En el código WinAPI recta, el dueño de una ventana modal se puede establecer cuando se crea la ventana:

HWND CreateWindow(
    LPCTSTR lpClassName, 
    LPCTSTR lpWindowName, 
    DWORD dwStyle, 
    int x, 
    int y, 
    int nWidth, 
    int nHeight, 
    HWND hWndParent, /* this is the owner if dwStyle does not contain WS_CHILD */ 
    HMENU hMenu, 
    HINSTANCE hInstance, 
    LPVOID lpParam 
); 

o después:

SetWindowLong(hWndPopup, GWL_HWNDPARENT, (LONG)hWndOwner); 

o (Compatible con 64 bits)

SetWindowLongPtr(hWndPopup, GWLP_HWNDPARENT, (LONG_PTR)hWndOwner); 

Nota MSDN que tiene la siguiente que decir sobre SetWindowLong[Ptr]:

No llamar SetWindowLongPtr con el índice GWLP_HWNDPARENT para cambiar la matriz de una ventana secundaria. En su lugar, use la función SetParent.

Esto es algo engañoso, ya que parece implicar que los dos últimos fragmentos anteriores son incorrectos. Esto no es asi Llamar al SetParent convertirá la ventana emergente deseada en un hijo de la ventana primaria (estableciendo su bit WS_CHILD), en lugar de convertirlo en una ventana propiedad. El código anterior es la forma correcta de hacer que una ventana emergente existente sea propiedad de una ventana.

+0

Gracias por su respuesta! Sin embargo, esta no es la causa del problema con mi aplicación. Como dije en mi pregunta, estoy pasando al propietario en todos los casos. ¿Alguna otra idea? –

+0

¿Tiene una muestra reproducible, por casualidad? –

Cuestiones relacionadas