質問

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


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

役に立ちましたか?

解決

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

編集

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

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

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

この質問に対する多くのコメントおよびその他の回答では、 EnumWindows がウィンドウハンドルを返す順序について、MSDNに正確なドキュメントがないことに言及しています。実際、 EnumWindows のページおよび EnumWindowsProc コールバックはどちらもこの問題について非常に静かです。私は証拠として以下を提供します:

  1. A MSDNマガジンのC ++ Q& Aの記事具体的に述べています:

      

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

  2. EnumChildWindows は、備考セクションの順序を暗示しています:

      

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

    これは、オーダーがZオーダーに依存することを意味します。また、 hWndParent パラメータの説明では、次のように記述されています。

      

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

    同じロジックと順序が EnumWindows に適用されると想定できます。

  3. これは、この関数の観察可能な動作であり、変更するための重大な変更になります。一般に、Microsoftは、観測可能な動作に重大な変更を加えないことについて非常に優れています。それは保証ではありませんが、かなり安全な賭けです。次のバージョンでは、使用している関数が廃止され、さらに別の" Ex"に置き換えられている可能性が高くなります。バージョン—その観察可能な動作が変更されていることを確認するまで。

もちろん、これは現時点では非常にアカデミックです。これは、 EnumWindows はおそらくOPの問題に対する最善の解決策ではないからです。少なくとも EnumThreadWindows はおそらく

他のヒント

以前の回答にはかなりの改良が必要です。 Enum-order = GetSystemMetrics(SM_IMMENABLED)= 0の場合のみZオーダー、つまり、Input Method Manager / Input Method Editor機能が無効になります。 すべてのウィンドウクラス" IME" (タイトル「デフォルトIME」)および「MSCTFIME UI」ウィンドウ「Progman」の後に列挙されます("プログラムマネージャー")、-つまり、Zオーダーではありません。

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

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

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

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

ドキュメントに列挙の順序について何も記載されていない場合は、前提から離れることを強くお勧めします。 Raymond Chenのブログ(blogs.msdn.com/oldnewthing)のいくつかの投稿から、この文書化されていないものや観察に依存しているアプリの数が明らかになり、Windowsの新しいバージョンがリリースされたときに何かがひどく間違っているMS開発者は、動作がさらに悪い別のアプリ用に別のシムを導入します。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top