2009-04-05 21 views
9

キーボード入力を別のプロセスのウィンドウに送りたいが、そのウィンドウをフォアグラウンドにする必要はない。私はPostMessageを使ってWM_KEYDOWNWM_KEYUPを偽造することができます。私が知る必要があるのは、どのウィンドウハンドルがキーボード入力を受け取るべきか、つまりGetFocusのようなものですが、別の非アクティブなアプリケーションのためです。P/Invoke経由でGetGUIThreadInfoを呼び出す

GetGUIThreadInfo APIは有望です - 別のアプリ用にhwndFocusを返します。しかし、私は64ビットOS上でC#を動かすことはできませんでした。私はpinvoke.netからの宣言をコピーしてから調整しましたが、私が返すのはジェネリックエラーコードです(詳細は下記参照)。

私はGetGUIThreadInfoを呼び出す前にcbSizeを設定していますので、最も明らかな潜在的な問題は避けています。

私は64ビットVistaを使用しているため、問題がAPIを正しく使用していないか、または64ビットで動作が異なるかどうかわかりません。具体的にWin64でうまく動作することを示すコードサンプル。

ここにサンプルコードがあります。私はGetWindowThreadProcessId as recommendedを使用していますので、私はこの問題は、スレッドとスレッドIDをハンドル混合に関係しているとは思わない:

[StructLayout(LayoutKind.Sequential)] 
internal struct Rect 
{ 
    public int Left; 
    public int Top; 
    public int Right; 
    public int Bottom; 
} 

[StructLayout(LayoutKind.Sequential)] 
internal class GuiThreadInfo 
{ 
    public int cbSize; 
    public uint flags; 
    public IntPtr hwndActive; 
    public IntPtr hwndFocus; 
    public IntPtr hwndCapture; 
    public IntPtr hwndMenuOwner; 
    public IntPtr hwndMoveSize; 
    public IntPtr hwndCaret; 
    public Rect rcCaret; 
} 

[DllImport("user32.dll")] 
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); 
[DllImport("user32.dll", SetLastError = true)] 
internal static extern bool GetGUIThreadInfo(uint idThread, ref GuiThreadInfo lpgui); 

IntPtr GetFocusedHandleFromProcessWithWindow(IntPtr window) 
{ 
    var threadId = GetWindowThreadProcessId(window, IntPtr.Zero); 
    var info = new GuiThreadInfo(); 
    info.cbSize = Marshal.SizeOf(info); 
    if (!GetGUIThreadInfo(threadId, ref info)) 
     throw new Win32Exception(); 
    return info.hwndFocus; 
} 

windowは、有効なウィンドウハンドルです。 GetWindowThreadProcessIdは、非ゼロのスレッドハンドルを返します。しかし、GetGUIThreadInfoの呼び出しは常にfalseを返し、例外メッセージは常に「パラメータが正しくありません」です。

は、念のために問題がGetGUIThreadInfoは何とか64ビットバージョンを持っていないことを、私は4バイトint sのGuiThreadInfo宣言で全て8バイトIntPtr Sを変える試みたが、私はまだ同じですエラー。

Win64で動作するC#サンプルがGetGUIThreadInfoの人はいますか?または、そのアプリをアクティブにせずに、別のアプリでフォーカスされた子ウィンドウハンドルを見つける方法がありますか?

答えて

4

私はそれをあまりにも厳しく見ていないが、1つのことが飛び出す。あなたのGetGUIThreadInfo呼び出しでは、GUIThreadInfo構造体をrefで渡しますが、それをクラスとして定義しているので、refによる参照、つまりポインタへのポインタを送ります。 GUIThreadInfoを構造体に変更するか、パラメータのrefを削除して[In、Out]属性を追加してください。

+1

あなたは正しい - 私はそれを逃したとは思わない。 礼儀のポイント:これは直近の問題を解決しましたが、別の問題が発生しました。私の最終目標である「他のプロセスに焦点を当てる」はまだ開かれています。この質問を編集するか、この回答を受け入れて新しい質問を書くべきですか? –

+0

この場合、質問は実際にはGetGUIThreadInfoをpInvokingすることです。だから、おそらくそれを参考に投票して回答としてマークするべきです。また、タイトルを編集して、この質問を詳しく説明することもできます。そして、より一般的な問題について新しい質問を追加してください。 –

+0

...あなたの根底にある要件は、これまでに試したことです。一般的には、質問を編集して情報を追加するか、尋ねられている内容を変更しないようにする必要があります。 –

関連する問題