Pregunta

De un par de pruebas preliminares parece que EnumWindows siempre devuelve las ventanas en orden inverso de instanciación, es decir, la ventana instanciada más recientemente primero. ¿Es eso una observación válida? Si es así, ¿es cierto en todas las versiones de Windows? ¿Y es una suposición confiable, es decir, ese comportamiento está documentado en alguna parte?


Contexto: Estoy lidiando con una situación en la que estoy activando una aplicación de terceros para abrir varias ventanas no modales y necesito enviar algunos mensajes de ventana a esas ventanas una vez que están abiertas, pero no tengo una forma segura de identificarlos, ya que ni sus clases de ventana ni sus subtítulos serán diferentes y tampoco sé sus coordenadas esperadas. Sin embargo, si pudiera confiar en el comportamiento anterior de EnumWindows , simplemente podría usar el primer identificador devuelto por EnumWindows cuya clase y título coinciden con mis expectativas. Eso todavía deja algunos agujeros de bucle hipotéticos, pero creo que será lo suficientemente bueno. No obstante, las sugerencias alternativas son bienvenidas.

¿Fue útil?

Solución

Los devuelve en orden Z. Primero la ventana superior con WS_EX_TOPMOST establecida, hasta la ventana inferior con WS_EX_TOPMOST set , luego la ventana superior sin WS_EX_TOPMOST , aunque a la ventana más inferior sin WS_EX_TOPMOST . Tenga en cuenta que la visibilidad no es un factor determinante, por lo que una ventana invisible que es más alta en el orden Z que una ventana visible todavía aparecerá delante de ella.

EDITAR :

Es muy poco probable que pueda usar esto como lo desee, simplemente tomando el primer retorno de EnumWindows . No solo es improbable que su nueva ventana sea el primer regreso, sino que también tendría una condición de carrera en la que otras ventanas podrían abrirse mientras tanto. Sin embargo, podría mantener una lista de todas las ventanas conocidas para la aplicación, y cuando necesite encontrar una ventana recién abierta, llame a EnumWindows y compare los identificadores de ventana con los de su lista. Cuando encuentre uno que tenga la clase y el título correctos (incluso puede verificar que pertenece al proceso correcto con GetWindowThreadProcessID ) que es not en su lista, entonces usted ' encontré la nueva ventana.

Sin embargo, para sus propósitos, puede ser aún mejor si instala un enlace CBT y observa la notificación HCBT_CREATEWND. Consulte la ayuda de MSDN en SetWindowsHookEx () y el CBTProc devolución de llamada para obtener más información.

Nivel de certeza sobre el orden de enumeración :

Varios comentarios y otras respuestas a esta pregunta han mencionado la falta de documentación precisa en MSDN sobre el orden en que EnumWindows devuelve los identificadores de las ventanas. Y, de hecho, las páginas en EnumWindows y el EnumWindowsProc la devolución de llamada son bastante silenciosas sobre el tema. Ofrezco como evidencia lo siguiente:

  1. A C ++ Q & amp; Un artículo en la revista MSDN indica específicamente:

      

    EnumWindows enumera las ventanas en orden Z de arriba hacia abajo

  2. La página en EnumChildWindows alude al orden en la sección de comentarios:

      

    Una ventana secundaria que se mueve o reposiciona en el orden Z durante el proceso de enumeración se enumerará correctamente.

    Esto implica que el orden depende del orden Z. Y dado que, en la descripción del parámetro hWndParent , dice esto:

      

    Si este parámetro es NULL, esta función es equivalente a EnumWindows.

    se puede suponer que la misma lógica y orden se aplica a EnumWindows.

  3. Este es el comportamiento observable de esta función, lo que hace que sea un cambio radical alterarla. En general, Microsoft ha sido muy bueno al no realizar cambios importantes en el comportamiento observable. Eso no es una garantía, pero es una apuesta bastante segura. Es más probable que descubra que en la próxima versión la función que está utilizando ha quedado en desuso y ha sido reemplazada por otra " Ex " versión, que descubrir que su comportamiento observable ha cambiado.

Por supuesto, todo esto es muy académico en este punto, ya que EnumWindows probablemente no sea la mejor solución para el problema del OP, al menos EnumThreadWindows probablemente sea una

Otros consejos

Las respuestas anteriores necesitan un refinamiento considerable. Enum-order = Z-order solo si GetSystemMetrics (SM_IMMENABLED) = 0, es decir, las funciones del Administrador de métodos de entrada / Editor de métodos de entrada están deshabilitadas. Porque todas las clases de Windows "IME" (el título " IME predeterminado ") y " MSCTFIME UI " se enumeran después de la ventana "Progman" (" Administrador de programas "), es decir, no en orden Z.

El pedido no se especifica en la API ( enlace MSDN ) por lo que no se garantiza que sea algo en particular: si hubiera una garantía, se especificaría explícitamente en la API. ¿Qué sucede, por ejemplo, si se crea una ventana a mitad de la enumeración? ¿Se incluye en la enumeración? Esto le permite al administrador de ventanas la libertad de cambiar su implementación en caso de que sea más eficiente hacerlo.

Sin embargo, hay un valor único que se puede usar para diferenciar entre ventanas: el identificador de la ventana en sí. En su método EnumWindowProc , guarde el identificador de ventana para cada ventana coincidente; de ??todos modos, lo necesita para enviar mensajes a la ventana.

Si controla ambos procesos, puede enviar desde el primero un SendMessage con " HWND_BROADCAST " como primer parámetro.

Luego, el otro programa cuando recibe el mensaje, puede hacer un SendMessage a sus ventanas secundarias.

Si la documentación no dice nada sobre el orden de enumeración, sugiero que se mantenga alejado de cualquier suposición. Un par de publicaciones en el blog de Raymond Chen (blogs.msdn.com/oldnewthing) le revelarán cuántas aplicaciones hay que dependen de todas estas cosas / observaciones indocumentadas, y algo sale terriblemente mal cuando sale una nueva versión de Windows (a menos que Los desarrolladores de MS introducen otro calce para otra aplicación que se comporta mal).

En cuanto a su propósito, hay varias funciones, como GetWindowThreadProcessID, GetParent, EnumThreadWindows y EnumWindows que podrían ayudarlo a lograr la tarea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top