2008-11-17 10 views
16

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


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

Respuesta

23

Los devuelve en orden Z. Primero la ventana más alta con WS_EX_TOPMOST establecida, hasta la ventana inferior con WS_EX_TOPMOST set, luego la ventana más alta sin WS_EX_TOPMOST, aunque en la ventana inferior sin WS_EX_TOPMOST. Tenga en cuenta que la visibilidad no es un factor determinante, por lo que una ventana invisible que sea más alta en el orden Z que una ventana visible seguirá apareciendo antes.

EDITAR:

Es muy poco probable que usted podría utilizar esto como desea, simplemente tomar la primera vuelta de EnumWindows. No solo es probable que su nueva ventana sea la primera devolución, sino que también tendría una condición de carrera en la que se podrían abrir otras ventanas 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 al 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 podría verificar que pertenece al proceso correcto con GetWindowThreadProcessID) que es no en su lista, entonces ha encontrado la nueva ventana.

Para sus propósitos, sin embargo, puede ser mejor si instala un gancho CBT y observa la notificación HCBT_CREATEWND. Consulte la ayuda de MSDN en SetWindowsHookEx() y the CBTProc callback para obtener más información.

nivel de certeza sobre el orden de enumeración:

Una serie de comentarios y otras respuestas a esta pregunta han mencionado la falta de documentación precisa en MSDN sobre el orden en el que se encarga de la ventana EnumWindows devoluciones. Y, de hecho, las páginas en EnumWindows y the EnumWindowsProc callback son bastante silenciosas sobre el tema.Ofrezco como prueba lo siguiente:

  1. Un C++ Q&A article in MSDN magazine sí declara específicamente:

    EnumWindows enumera las ventanas de arriba hacia abajo orden Z

  2. La página en EnumChildWindows alude a el orden en la sección de observaciones:

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

    Esto implica que la orden depende de Z. Y puesto que, en la descripción del parámetrohWndPrincipal, que dice lo siguiente:

    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 brusco alterarlo. En general, Microsoft ha sido muy bueno sobre no hacer cambios bruscos 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 reemplazada por otra versión "Ex" más que para descubrir que su comportamiento observable ha cambiado.

Por supuesto, todo esto es muy académica en este punto, ya que EnumWindows probablemente no es la mejor solución para el OP solución de al menos EnumThreadWindows sería probablemente un mejor ajuste, pero pensé que valía la pena mencionar para otras personas que puedan encontrar esta publicación.

+0

Eso suena razonable. ¿Tiene un enlace a la documentación de este comportamiento en alguna parte? Hubiera esperado esto en los documentos 'EnumWindows' ... –

+1

Tenga en cuenta que escribí" el primer identificador devuelto por EnumWindows * cuya clase y título coinciden con mis expectativas * ". Soy consciente de que otras ventanas que coinciden con los mismos criterios podrían abrirse mientras tanto, pero en este caso tengo un 95% de confianza en que esto es bastante hipotético. –

+1

el problema con mantener una lista de identificadores conocidos es que (hasta ahora) no tengo forma de saber cuándo se cierra una ventana para eliminarla de la lista nuevamente. esto podría volver a ser hipotético, pero ¿cómo sabría que el identificador (potencialmente liberado) no ha sido reasignado a una nueva ventana mientras tanto? –

1

La orden no se especifica en la API (MSDN link) por lo que no se garantiza que sea en particular; si existiera 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 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.

+0

no solo debo ser capaz de diferenciar entre ellos. Necesito saber cuál es el que acabo de activar en la vida ... –

0

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 enviar un mensaje de texto a sus ventanas secundarias.

+0

lo siento, no controlo el programa que crea la ventana, al menos no en el sentido de que puedo enviar mensajes. –

0

Si la documentación no dice nada sobre el orden de la enumeración, le recomiendo encarecidamente que se mantenga alejado de cualquier suposición. Un par de publicaciones en el blog de Raymond Chen (blogs.msdn.com/oldnewthing) le revelaría cuántas aplicaciones hay que confían en todas estas cosas/observaciones indocumentadas, y algo va terriblemente mal cuando sale una nueva versión de Windows (a menos que los desarrolladores de MS presenten otro complemento 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.

2

Las respuestas anteriores necesitan un refinamiento considerable. Enum-order = Orden Z solo si GetSystemMetrics (SM_IMMENABLED) = 0, es decir, las características 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 "MSI de MSCTFIME" se enumeran después de la ventana "Progman" ("Administrador de programas"), es decir, no en orden Z.

Cuestiones relacionadas