私は Delphi やそのライブラリを知らないので、純粋に C と Win32 の観点からこれに答えるつもりです。これを C# に変換するには p/invoke を使用しますが、一部の部分はアンマネージする必要がある場合があります。
まず、保証はありません。ターゲット アプリケーションがウィンドウなしのコントロールを実行している場合 (HWND
すべてのオンスクリーン コントロールの下に がない場合)、ほとんど運がありません。これはそれほど珍しいことではありません。
ステップ 1、ターゲット プロセスによって作成された新しいウィンドウをリッスンするウィンドウ フックを登録します*:
//dllHMod is an HMODULE that refers to the DLL containing ShellHookProc
HHOOK hook = SetWindowsHookEx(WH_SHELL, ShellHookProc, dllHMod, 0);
// error handling, stashing hook away for unregistering later, etc...
LRESULT CALLBACK ShellHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(nCode < 0) return CallNextHookEx(NULL, nCode, wParam, lParam);
if(nCode == HSHELL_WINDOWCREATED)
{
WindowCreate((HWND)wParam);
}
return 0;
}
WindowCreated(HWND)
GetWindowThreadProcessId
正しいプロセス (で決定) がそれを所有している場合、HWND を隠しておく必要があります。この時点で、ターゲット プロセスが所有するすべてのトップレベル ウィンドウを取得できます。グローバルフックを登録すると、パフォーマンスが大幅に低下することに注意してください。実際には問題ではありませんが、予想する必要があります。
さて、楽しい部分です。ウィンドウがいつ完全に構築されたか、いつレンダリングが完了したかを知る信頼できる方法はありません (いつレンダリングを開始するかを知る方法はありますが、それは実際には役に立ちません)。私のアドバイス、推測します。そこに任意の待機を投げてから、すべての子ウィンドウを列挙してみてください。
子ウィンドウを列挙するには (ターゲット ウィンドウについて十分に知っている場合は、これを行うためのより良い方法があります。ただし、検索が最も簡単であると想定しています)。
//targetHWND is an HWND of one of the top-level windows you've found
EnumChildWindows(targetHWND, ChildWindowCallback, NULL);
//more code...
BOOL ChildWindowCallback(HWND window, LPARAM ignored)
{
if(IsTargetWindow(window)) { /* Do something */ }
return TRUE;
}
実装IsTargetWindow
は、もう 1 つのトリッキーな部分です。そうするための信頼できるテストが見つかることを願っています (クラス名、ウィンドウ名、スタイルなどをチェックするなど。 を参照してくださいGetWindowInfo
)。
監視したいウィンドウを取得したら、 と を使用して、ウィンドウが受信するすべてのメッセージを監視できSetWindowLongPtr
ますGWLP_WNDPROC
。これにはコード インジェクション (したがってアンマネージ コード) が必要であり、非常に低レベルです。あなたがそれを避けることができるなら、私はそれに反対することをお勧めしますが、ソースがありません...
この回答は適切な出発点だと思いますが、これが可能であったとしても、これは信じられないほど苦痛になるでしょう。幸運を。
*または、ターゲット アプリが起動時 (または検出可能/予測可能な時点) 以外にウィンドウを作成しないことがわかっている場合は、EnumWindows
.