19

いくつかの予備テストから、EnumWindows常に逆のインスタンス化順序でウィンドウが返されるようです。つまり、最近インスタンス化されたウィンドウが最初に返されます。それは有効な観察ですか?もしそうなら、それはWindowsのすべてのバージョンに当てはまりますか?そして、これは信頼できる仮定ですか、つまり、その動作はどこかに文書化されていますか?


コンテキスト:サードパーティのアプリケーションをトリガーしていくつかの非モーダルウィンドウを開き、開いたらそれらのウィンドウにウィンドウメッセージを送信する必要がある状況に対処していますが、確実な方法はありませんそれらをウィンドウクラスでもキャプションでもないものとして識別することは異なり、私もそれらの予想される座標を知りません。ただし、上記の動作に依存できる場合は、クラスとキャプションが期待どおりEnumWindowsに返される最初のハンドルを使用するだけで済みます。EnumWindowsそれでもいくつかの仮想的な抜け穴が残っていますが、それで十分だと思います。それでも、別の提案を歓迎します。

4

5 に答える 5

28

Zオーダーで返します。最初にがWS_EX_TOPMOST設定された一番上のウィンドウ、次にが付いた一番下のウィンドウWS_EX_TOPMOST set、次にが付いていない一番上のウィンドウまで、。WS_EX_TOPMOSTがない一番下のウィンドウまでWS_EX_TOPMOST。可視性は決定要因ではないため、可視ウィンドウよりもZオーダーが高い不可視ウィンドウがその前に表示されることに注意してください。

編集

から最初のリターンを取得するだけで、これを希望どおりに使用できる可能性はほとんどありませんEnumWindows。新しいウィンドウが最初に戻る可能性が低いだけでなく、その間に他のウィンドウを開くことができる競合状態が発生する可能性があります。ただし、アプリケーションのすべての既知のウィンドウのリストを保持することはできます。新しく開いたウィンドウを見つける必要がある場合は、ウィンドウハンドルを呼び出しEnumWindowsて、リスト内のウィンドウハンドルと比較します。リストにない正しいクラスとキャプション(で正しいプロセスに属していることを確認することもできますGetWindowThreadProcessID)を持つものを見つけると、新しいウィンドウが見つかります。

ただし、あなたの目的のために、CBTフックをインストールし、HCBT_CREATEWND通知を監視することで、さらに良いサービスが提供される場合があります。詳細については、 MSDNヘルプSetWindowsHookEx()コールバックを参照してください。CBTProc

列挙順序に関する確実性のレベル

この質問に対する多くのコメントやその他の回答では、EnumWindowsウィンドウハンドルを返す順序に関するMSDNの正確なドキュメントが不足していると述べています。そして確かに、上のページEnumWindowsコールバックは両方ともこの問題について非常に沈黙していますEnumWindowsProc私は証拠として以下を提供します:

  1. MSDNマガジンのC++Q&A記事には、具体的に次のように記載されています。

    EnumWindowsは、ウィンドウをトップダウンのZオーダーで列挙します

  2. のページEnumChildWindowsは、備考セクションの順序をほのめかしています。

    列挙プロセス中にZオーダーで移動または再配置された子ウィンドウは、適切に列挙されます。

    これは、順序がZオーダーに依存することを意味します。そして、hWndParentパラメータの説明では、次のようになっています。

    このパラメーターがNULLの場合、この関数はEnumWindowsと同等です。

    同じ論理と順序がに適用されると想定できますEnumWindows

  3. これは、この関数の観察可能な動作であり、それを変更するための重大な変更になります。一般に、Microsoftは、観察可能な動作に重大な変更を加えないことについて非常に優れています。これは保証ではありませんが、かなり安全な方法です。次のバージョンでは、使用している関数が非推奨になり、さらに別の「Ex」バージョンに置き換えられていることに気付く可能性が高くなります。観察可能な動作が変更されていることがわかります。

もちろん、これは現時点ではすべて非常に学術的EnumWindowsです。OPの問題に対する最善の解決策ではない可能性があり、少なくともEnumThreadWindowsより適切である可能性がありますが、これに遭遇する可能性のある他の人々にとっては言及する価値があると思いました。役職。

于 2008-11-17T16:15:31.913 に答える
2

以前の回答にはかなりの改良が必要です。Enum-order = Z-order は、GetSystemMetrics(SM_IMMENABLED)=0 の場合のみです。つまり、Input Method Manager/Input Method Editor 機能が無効になっています。すべてのウィンドウ クラス "IME" (タイトル "Default IME") と "MSCTFIME UI" はウィンドウ "Progman" ("Program Manager") の後に列挙されるため、つまり Z オーダーではありません。

于 2014-02-15T10:02:02.103 に答える
1

順序は API ( MSDN リンク) で指定されていないため、特に保証されているわけではありません。保証がある場合は、API で明示的に指定されます。たとえば、列挙の途中でウィンドウが作成された場合、列挙に含まれますか? これにより、ウィンドウ マネージャは、より効率的に実装を変更できるようになります。

ただし、ウィンドウを区別するために使用できる一意の値、つまりウィンドウ ハンドル自体があります。メソッドで、一致する各ウィンドウのウィンドウ ハンドルを保存しますEnumWindowProc。いずれにせよ、メッセージをウィンドウに送信するために必要です。

于 2008-11-17T16:24:32.847 に答える
0

両方のプロセスを制御する場合、最初のパラメータから「HWND_BROADCAST」を使用して SendMessage を送信できます。

次に、メッセージを受信すると、他のプログラムは子ウィンドウに SendMessage を実行できます。

于 2008-11-17T16:40:30.007 に答える
0

ドキュメントが列挙の順序について何も述べていない場合は、仮定を避けることを強くお勧めします。Raymond Chen のブログ (blogs.msdn.com/oldnewthing) に投稿されたいくつかの記事から、この文書化されていない情報や観察結果に依存しているアプリがどれだけあるかがわかります。 MS の開発者は、動作の悪いさらに別のアプリに対して、さらに別の shim を導入しています)。

目的に関しては、GetWindowThreadProcessID、GetParent、EnumThreadWindows、EnumWindows など、タスクの達成に役立つ関数がいくつかあります。

于 2008-11-17T16:42:49.423 に答える