2017-04-07 7 views
0

私はキーを押していくつかのキーを送信するコマンドSystem.Windows.Forms.SendKeys.Send()を見つけました。この機能は、メモ帳のような外部アプリケーションを開いてフォーカスを設定すると機能し、このテキストフィールドにキーが印刷されていることがわかります。どのように同じですが、キーダウンイベント、System.Windows.Forms.SendKeys.SendDown("A");、など?C# - アクティブなコントロールのためのトリガーキーダウンイベント

私はこのコマンドでSystem.Windows.Forms.SendKeys.Send()タイマーを呼び出そうとしましたが、非常に速いテープに関連付けられたランタイムエラーがあります。

答えて

3

残念ながら、SendKeysクラスを使用することはできません。下位レベルのAPIに移動する必要があります。 Windowsので

のkeydownメッセージを持つウィンドウを突っつい

は、キーボードイベントは、Windowsメッセージポンプを介してウィンドウやコントロールに送信されます。

[DllImport("user32.dll")] 
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); 

const uint WM_KEYDOWN = 0x0100; 

void SendKeyDownToProcess(string processName, System.Windows.Forms.Keys key) 
{ 
    Process p = Process.GetProcessesByName(processName).FirstOrDefault(); 
    if (p != null) 
    { 
     PostMessage(p.MainWindowHandle, WM_KEYDOWN, (int)key, 0); 
    } 
} 

注対応WM_KEYUPが受信されるまで、これらのイベントを受け取るアプリケーションは、それを何もしないこと:PostMessageを使用してコードの一部は、トリックを行うべきです。 hereから他のメッセージ定数を取得できます。

上記のコードはへのKeyDownを送信するメインウィンドウ

以外の制御を突く「MainWindowHandle。」他のもの(例えば、アクティブなコントロール)に送る必要がある場合はp.MainWindowHandle以外のハンドルでPostMessageに電話する必要があります。問題は、どうしたらそのハンドルを手に入れますか?

これは実際には非常に関与しています...スレッドをウィンドウのメッセージ入力に一時的に接続し、ハンドルを突き止める必要があります。これは、現在のスレッドがWindowsフォームアプリケーションに存在し、アクティブなメッセージループを持っている場合にのみ機能します。

説明はhereと同様に、この例を見つけることができます:

using System.Runtime.InteropServices; 

public partial class FormMain : Form 
{ 
    [DllImport("user32.dll")] 
    static extern IntPtr GetForegroundWindow(); 

    [DllImport("user32.dll")] 
    static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); 

    [DllImport("user32.dll")] 
    static extern IntPtr AttachThreadInput(IntPtr idAttach, 
         IntPtr idAttachTo, bool fAttach); 

    [DllImport("user32.dll")] 
    static extern IntPtr GetFocus(); 

    public FormMain() 
    { 
     InitializeComponent(); 
    } 

    private void timerUpdate_Tick(object sender, EventArgs e) 
    { 
     labelHandle.Text = "hWnd: " + 
          FocusedControlInActiveWindow().ToString(); 
    } 

    private IntPtr FocusedControlInActiveWindow() 
    { 
     IntPtr activeWindowHandle = GetForegroundWindow(); 

     IntPtr activeWindowThread = 
      GetWindowThreadProcessId(activeWindowHandle, IntPtr.Zero); 
     IntPtr thisWindowThread = GetWindowThreadProcessId(this.Handle, IntPtr.Zero); 

     AttachThreadInput(activeWindowThread, thisWindowThread, true); 
     IntPtr focusedControlHandle = GetFocus(); 
     AttachThreadInput(activeWindowThread, thisWindowThread, false); 

     return focusedControlHandle; 
    } 
} 

良いnews-- SendKeysがあなたのために働いていた場合、その後、あなたはすべてのthis-- SendKeysを行う必要がない可能性がありますもメッセージを送信しますメインウィンドウのハンドルに移動します。

+0

ありがとうございました。私は 'SendKeyDownToProcess(FocusedControlInActiveWindow()。ToString(); Keys.A);'を使用しますが、 'A'キーをタイプしていません。 –

+0

私は、郵便番号のPostMessage(FocusedControlInActiveWindow()、WM_KEYDOWN、(int)Keys.A、0);とそれは仕事です。私がノーデパッドのようなキーダウンをしたいのであれば、約10msの遅れでタイマーを動かす必要がありますか? –

+0

最適な時間間隔を決定するには、いくつかの試行錯誤が必要であると思ってください。あなたのO/Sがどの程度ビジーであるかによって異なります。 –

関連する問題