2009-05-07 12 views
3

私はこの問題を持っている:私は、特定のアプリケーションのメインウィンドウへのハンドラを持っている、と私は、そのアプリケーション上のキーの押下をシミュレートしたい...アプリケーションのアクティブChildWindowを取得するにはどうすればよいですか?

私はのsendMessage /のpostMessage APIを使用していますが、これを行うために呼び出します。私が.Net SendKeys関数またはwin32 APIのkeybd_eventを使用しない理由は、それらがグローバルレベルでのキー押しをシミュレートしているからです。私の場合、ターゲットアプリケーションはトップアクティブではありません(他のアプリケーションはより高いzレベルで動作している可能性があり、ターゲットアプリケーションをカバーしている可能性があります)。

sendMessageとpostMessageの問題は、キーを押したい正確な子ウィンドウのハンドラを渡す必要があることです。たとえば、メモ帳でmainWindowのハンドラにキーを送信しても、何も起こりません。子ウィンドウのハンドラにキーを送信する必要があります。子ウィンドウは、基本的に書き込み可能な白いキャンバスから構成されています。

アクティブな子ウィンドウへのハンドラの取得が問題です。最初は、GetTopWindowまたはGetWindow(GW_CHILD)API呼び出しを使用していました。最もアクティブな子ウィンドウが返されるためです。私がやっていたことは、childWindowがなくなるまで、GetWindow(GW_CHILD)を呼び出すことでした。これは、メモ帳やペイントのようなアプリケーションでうまくいきます。しかし、場合によっては(例えばfirefoxのように)、動作しません。その理由は、親ウィンドウにはFirefox全体の領域があり、子ウィンドウには開かれたWebページ(Googleなど)があるからです。したがって、私がmainWindowの中で最もアクティブな子ウィンドウを要求すると、それはWebページ領域に対応する子ウィンドウのみを返します。これは、アクティブなウィンドウがそのウィンドウである場合にのみ機能します(ユーザーが特定のページのテキストボックスに何かを書いている場合など)。しかし、アクティブなウィンドウがアクティブなウィンドウではなく、実際には親ウィンドウであるため、アクティブなウィンドウがアドレスバーで動作しない場合、この情報はプログラムでは取得できません。

私は実際に次のコードを使用して、GetGUIThreadInfo API呼び出しを使用して、これを行う方法を見つけた:

// get thread of the main window handle of the process 
    var threadId = GetWindowThreadProcessId(firefox.MainWindowHandle, IntPtr.Zero); 

    // get gui info 
    var info = new GUITHREADINFO(); 
    info.cbSize = (uint)Marshal.SizeOf(info); 
    if (!GetGUIThreadInfo(threadId, out info)) 
     throw new Win32Exception(); 

    // send the letter W to the active window 
    PostMessage(info.hwndActive, WM_KEYDOWN, (IntPtr)Keys.W, IntPtr.Zero); 

をそして、それは非常によく動作します:アドレスバーがアクティブな場合、それは「W」を送信しますアドレスバーへの手紙。 googleの検索テキストボックスがアクティブな場合、それは "W"という文字を送信します...完璧!しかし、この方法は簡単な理由で私には使用できません。 ターゲットアプリケーションがオペレーティングシステムのアクティブなウィンドウでない場合、ThreadInfo構造体は空になります。たとえば、firefoxを対象としている場合、firefoxがアクティブな場合(最上位のアプリケーション、フォーカス/アクティブなもの)は動作しますが、メモ帳がFirefoxの上にある場合、動作しません。アクティブなウィンドウハンドラを取得できません。

私はこれを解決するには、setForegroundWindow API呼び出しを使用してターゲットアプリケーションをアクティブにし、アクティブな子ウィンドウのハンドラを取得することができますが、ターゲットアプリケーションをフォアグラウンドに持ってこないようにしたいと思います。

私はまた、AttachThreadInput()やGetFocus()API呼び出しなどの他のテクニックも試しました。これも動作しますが、同じ問題があります。ターゲットアプリケーションがアクティブなWindowsアプリケーションでない場合、動作しません。

基本的に、そのアプリケーションがアクティブな子ウィンドウでない場合でも、ハンドラをアクティブな子ウィンドウにする方法を見つける必要があります。

アイデア? ありがとう

答えて

0

他のすべてが失敗した場合は、別の考え方があります。WH_CBTまたはWH_CALLWNDPROCフックを使用して、ターゲットスレッドのどのウィンドウが最後にフォーカスされたかを監視することを検討します。

CBTフック(WH_CBT)をインストールし、HCBT_SETFOCUS通知を待ち受けます。 または、WH_CALLWNDPROCフックを使用して、WM_SETFOCUSメッセージを待ち受けます。

フックprocで大したことをしないと、システムリソースが枯渇します。必要な情報を保存し、後で処理するカスタムメッセージを投稿してください。

関連する問題