Question

D'après quelques tests préliminaires, il semble que EnumWindows renvoie toujours les fenêtres dans l'ordre d'instanciation inverse, c'est-à-dire d'abord la dernière fenêtre instanciée. Est-ce une observation valable? Si oui, est-ce vrai pour toutes les versions de Windows? Et s’agit-il d’une hypothèse fiable, c’est-à-dire que ce comportement est documenté quelque part?

Contexte: Je fais face à une situation dans laquelle je déclenche une application tierce pour qu'elle ouvre plusieurs fenêtres non modales et que je dois envoyer des messages à ces fenêtres une fois qu'elles sont ouvertes. Je n'ai aucun moyen infaillible de les identifier car ni leurs classes de fenêtres ni leurs légendes ne seront différentes et je ne connais pas non plus leurs coordonnées attendues. Cependant, si je pouvais me fier au comportement ci-dessus de EnumWindows , je pourrais simplement utiliser le premier descripteur renvoyé par EnumWindows dont la classe et la légende correspondent à mes attentes. Cela laisse encore quelques trous hypothétiques, mais je pense que cela suffira. Des suggestions alternatives sont néanmoins les bienvenues.

Était-ce utile?

La solution

Il les retourne dans l’ordre Z. Commencez par la fenêtre supérieure avec WS_EX_TOPMOST définie, jusqu'à la fenêtre inférieure avec WS_EX_TOPMOST définie , puis par la fenêtre supérieure sans WS_EX_TOPMOST , dans la fenêtre du bas sans WS_EX_TOPMOST . Notez que la visibilité n’est pas un facteur déterminant. Par conséquent, une fenêtre invisible dont la position dans l’ordre Z est supérieure à celle d’une fenêtre visible apparaît toujours avant.

MODIFIER :

Il est très peu probable que vous puissiez utiliser cela à votre guise, en prenant simplement le premier retour de EnumWindows . Non seulement il est peu probable que votre nouvelle fenêtre soit le premier retour, mais vous auriez une situation de concurrence critique dans laquelle d'autres fenêtres pourraient être ouvertes entre-temps. Vous pouvez toutefois conserver une liste de toutes les fenêtres connues de l'application et, lorsque vous devez rechercher une fenêtre récemment ouverte, appelez EnumWindows et comparez les descripteurs de fenêtre à ceux de votre liste. Lorsque vous en trouvez un qui a la classe et la légende correctes (vous pouvez même vérifier qu'il appartient au bon processus avec GetWindowThreadProcessID ) et que ne le soit pas dans votre liste, vous ' avons trouvé la nouvelle fenêtre.

Pour vos besoins, cependant, vous serez peut-être encore mieux servi en installant un point d'ancrage CBT et en surveillant la notification HCBT_CREATEWND. Consultez l'aide de MSDN sur SetWindowsHookEx () et le CBTProc rappel pour plus d'informations.

Niveau de certitude concernant l'ordre de recensement :

Un certain nombre de commentaires et d’autres réponses à cette question ont signalé un manque de documentation précise dans MSDN concernant l’ordre dans lequel EnumWindows renvoie les descripteurs de fenêtre. Et en effet, les pages sur EnumWindows et le EnumWindowsProc callback sont assez silencieux sur la question. Je présente comme preuve les éléments suivants:

  1. Un Q & amp; C ++ article dans le magazine MSDN indique-t-il spécifiquement:

      

    EnumWindows énumère les fenêtres dans l'ordre Z descendant

  2. La page sur EnumChildWindows fait référence à l'ordre dans la section des remarques:

      

    Une fenêtre enfant déplacée ou repositionnée dans l'ordre Z pendant le processus d'énumération sera correctement énumérée.

    Cela implique que l'ordre dépend de l'ordre Z. Et puisque, dans la description du paramètre hWndParent , il est écrit ceci:

      

    Si ce paramètre est NULL, cette fonction est équivalente à EnumWindows.

    on peut supposer que la même logique et le même ordre s'appliquent à EnumWindows .

  3. C’est le comportement observable de cette fonction, ce qui en fait un changement radical de la modifier. En général, Microsoft a très bien fait de ne pas apporter de modifications majeures au comportement observable. Ce n'est pas une garantie, mais c'est une valeur sûre. Vous aurez plus de chances de constater que la fonction que vous utilisez est obsolète dans la version suivante et remplacée par un autre "Ex". version - que de constater que son comportement observable a changé.

Bien sûr, tout cela est très théorique à ce stade-ci, car EnumWindows n'est probablement pas la meilleure solution au problème du PO, à tout le moins EnumThreadWindows serait probablement une

Autres conseils

Les réponses précédentes nécessitent un raffinement considérable. Enum-order = Z-order uniquement si GetSystemMetrics (SM_IMMENABLED) = 0, c’est-à-dire que les fonctionnalités du gestionnaire de méthodes de saisie / éditeur de méthodes de saisie sont désactivées. Parce que toutes les fenêtres de classe " IME " (le titre "Default IME") et "MSCTFIME UI" sont énumérés après la fenêtre " Progman " ("Gestionnaire de programme"), - c’est-à-dire pas dans l’ordre Z.

La commande n'est pas spécifiée dans l'API ( lien MSDN . ), il n’est donc pas garanti qu’il s’agisse de quelque chose en particulier - s’il existait une garantie, elle serait explicitement spécifiée dans l’API. Que se passe-t-il, par exemple, si une fenêtre est créée à mi-chemin de l'énumération - est-elle incluse dans l'énumération? Cela laisse au gestionnaire de fenêtres la liberté de changer d’implémentation s’il devenait plus efficace.

Cependant, il existe une valeur unique qui peut être utilisée pour différencier les fenêtres: le descripteur de fenêtre lui-même. Dans votre méthode EnumWindowProc , enregistrez le descripteur de fenêtre pour chaque fenêtre correspondante. Vous en avez néanmoins besoin pour envoyer des messages à la fenêtre.

Si vous contrôlez les deux processus, vous pouvez envoyer à partir du premier un SendMessage avec " HWND_BROADCAST " comme premier paramètre.

Ensuite, lorsqu’il reçoit le message, l’autre programme peut envoyer un message à ses fenêtres enfants.

Si la documentation ne dit rien sur l’ordre de recensement, je vous suggère FORTEMENT d’éviter toute hypothèse. Quelques articles sur le blog de Raymond Chen (blogs.msdn.com/oldnewthing) vous indiqueraient le nombre d'applications qui reposent sur toutes ces informations non documentées, et quelque chose ne va pas du tout lorsqu'une nouvelle version de Windows est publiée (à moins que Les développeurs MS introduisent encore une autre solution pour une autre application qui se comporte mal).

En ce qui concerne votre objectif, plusieurs fonctions, telles que GetWindowThreadProcessID, GetParent, EnumThreadWindows et EnumWindows, pourraient vous aider à accomplir cette tâche.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top