2017-04-07 60 views
0

我發現命令System.Windows.Forms.SendKeys.Send()用於發送按鍵一些按鍵。如果打開外部應用程序(如記事本並設置焦點),此功能將起作用,並且我將看到我的密鑰打印在此文本字段中。如何做到這一點,但關鍵事件System.Windows.Forms.SendKeys.SendDown("A");,例如?C# - 主動控制的觸發按鍵事件

我試圖在定時器這個命令System.Windows.Forms.SendKeys.Send()電話,但有非常快的錄音相關的運行錯誤。

回答

3

不能使用SendKeys類,很遺憾。您將需要轉到較低級別的API。

戳一個窗口,其中一個的keydown消息

在Windows中,鍵盤事件通過Windows消息泵送到窗口和控件。一塊使用PostMessage應該做的伎倆代碼:

[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被接收。您可以從here獲得其他消息常量。

戳比主窗口

其他的控制上面的代碼將在keyDown發送到「MainWindowHandle」。如果您需要將其發送給其他人(例如主動控制器),則需要撥打PostMessage,使用p.MainWindowHandle以外的其他手柄。問題是...你如何得到這個句柄?

這實際上是非常複雜的...你需要將你的線程暫時附加到窗口的消息輸入,並捅它弄清楚手柄是什麼。這隻能在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);'這是工作。如果我想要像nodepad那樣做keydown,那麼我需要延遲大約10ms來運行Timer嗎? –

+0

認爲您需要一些試驗和錯誤來確定最佳的工作時間間隔;它可能會有所不同,這取決於您的操作系統的繁忙程度。 –