HOW TO:以程式碼模擬滑鼠和鍵盤事件
更新:2007 年 11 月
Windows Form 提供了幾個選項,用於以程式設計方式模擬滑鼠和鍵盤輸入。本說明主題將概要說明這些選項。
模擬滑鼠輸入
模擬滑鼠事件的最佳方式是呼叫 OnEventName 方法,此方法會引發您要模擬的滑鼠事件。通常只有在自訂控制項和表單內才能使用這個選項,因為引發事件的方法會受到保護,而且無法在控制項或表單外進行存取。例如,下列步驟說明了如何在程式碼中模擬按一下滑鼠右鍵的動作。
若要以程式設計方式按一下滑鼠右鍵
建立 MouseEventArgs,將它的 Button 屬性設為 MouseButtons.Right 值。
使用這個 MouseEventArgs 做為引數以呼叫 OnMouseClick 方法。
如需自訂控制項的詳細資訊,請參閱在設計階段開發 Windows Form 控制項。
還有其他方式可以模擬滑鼠輸入。例如,您可以使用程式設計方式設定代表狀態的控制項屬性,而此狀態通常是經由滑鼠輸入來設定 (例如 CheckBox 控制項的 Checked 屬性),或者是直接呼叫附加至您要模擬的事件的委派。
模擬鍵盤輸入
雖然您也可以使用上述用於滑鼠輸入的策略來模擬鍵盤輸入,Windows Form 還是提供了 SendKeys 類別,以便將按鍵動作傳送至使用中的應用程式。
警告: |
---|
如果應用程式是設計成可搭配國際上現有的各種鍵盤來使用,則使用 SendKeys.Send 可能會產生無法預期的結果,應該要避免。 |
注意事項: |
---|
SendKeys 類別已針對 .NET Framework 3.0 進行更新,以便能夠在 Windows Vista 上執行的應用程式中使用。Windows Vista 的增強型安全性 (稱為使用者帳戶控制項或 UAC) 會讓之前的實作無法如預期般運作。 SendKeys 類別容易受到時間問題的影響,而某些開發人員必須解決這些問題。更新的實作仍然容易受到時間問題的影響,但是速度會稍微快一些,而且可能需要解決方法有一些變更。SendKeys 類別會先嘗試使用之前的實作,而如果失敗,則會使用新的實作。因此,SendKeys 類別在不同的作業系統上可能會有不同的行為方式。此外,當 SendKeys 類別使用新的實作時,SendWait 方法將不會在訊息傳送給另一個處理序時等候處理這些訊息。 如果應用程式倚賴一致的行為,而不論作業系統為何,您可以強制 SendKeys 類別使用新的實作,其方式是將下列應用程式設定加入至 app.config 檔中。 <appSettings> <add key="SendKeys" value="SendInput"/> </appSettings> 若要強制 SendKeys 類別使用之前的實作,請改用 "JournalHook" 這個值。 |
若要將按鍵動作傳送至相同的應用程式
呼叫 SendKeys 類別的 Send 或 SendWait 方法。應用程式目前使用中的控制項就會接收指定的按鍵動作。當使用者按兩下表單表面時,下列程式碼範例是使用 Send,以模擬按下 ENTER 鍵的動作。這個範例是假設 Form 含有一個定位點索引為 0 的 Button 控制項。
' Send a key to the button when the user double-clicks anywhere ' on the form. Private Sub Form1_DoubleClick(ByVal sender As Object, _ ByVal e As EventArgs) Handles Me.DoubleClick ' Send the enter key to the button, which raises the click ' event for the button. This works because the tab stop of ' the button is 0. SendKeys.Send("{ENTER}") End Sub
// Send a key to the button when the user double-clicks anywhere // on the form. private void Form1_DoubleClick(object sender, EventArgs e) { // Send the enter key to the button, which raises the click // event for the button. This works because the tab stop of // the button is 0. SendKeys.Send("{ENTER}"); }
// Send a key to the button when the user double-clicks anywhere // on the form. private: void Form1_DoubleClick(Object^ sender, EventArgs^ e) { // Send the enter key to the button, which triggers the click // event for the button. This works because the tab stop of // the button is 0. SendKeys::Send("{ENTER}"); }
若要將按鍵動作傳送至不同的應用程式
啟動會接收按鍵動作的應用程式視窗,然後呼叫 Send 或 SendWait 方法。因為沒有 Managed 方法可用來啟動另一個應用程式,所以您必須使用原生 Windows 方法強制將焦點放在其他應用程式上。下列程式碼範例是使用平台叫用以呼叫 FindWindow 和 SetForegroundWindow 方法而啟動 [小算盤] 應用程式視窗,然後再呼叫 SendWait 將一系列的計算發送至 [小算盤] 應用程式。
' Get a handle to an application window. Declare Auto Function FindWindow Lib "USER32.DLL" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As IntPtr ' Activate an application window. Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _ (ByVal hWnd As IntPtr) As Boolean ' Send a series of key presses to the Calculator application. Private Sub button1_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles button1.Click ' Get a handle to the Calculator application. The window class ' and window name were obtained using the Spy++ tool. Dim calculatorHandle As IntPtr = FindWindow("SciCalc", "Calculator") ' Verify that Calculator is a running process. If calculatorHandle = IntPtr.Zero Then MsgBox("Calculator is not running.") Return End If ' Make Calculator the foreground application and send it ' a set of calculations. SetForegroundWindow(calculatorHandle) SendKeys.SendWait("111") SendKeys.SendWait("*") SendKeys.SendWait("11") SendKeys.SendWait("=") End Sub
// Get a handle to an application window. [DllImport("USER32.DLL", CharSet = CharSet.Unicode)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); // Activate an application window. [DllImport("USER32.DLL")] public static extern bool SetForegroundWindow(IntPtr hWnd); // Send a series of key presses to the Calculator application. private void button1_Click(object sender, EventArgs e) { // Get a handle to the Calculator application. The window class // and window name were obtained using the Spy++ tool. IntPtr calculatorHandle = FindWindow("SciCalc", "Calculator"); // Verify that Calculator is a running process. if (calculatorHandle == IntPtr.Zero) { MessageBox.Show("Calculator is not running."); return; } // Make Calculator the foreground application and send it // a set of calculations. SetForegroundWindow(calculatorHandle); SendKeys.SendWait("111"); SendKeys.SendWait("*"); SendKeys.SendWait("11"); SendKeys.SendWait("="); }
// Get a handle to an application window. public: [DllImport("USER32.DLL", CharSet = CharSet::Unicode)] static IntPtr FindWindow(String^ lpClassName, String^ lpWindowName); public: // Activate an application window. [DllImport("USER32.DLL")] static bool SetForegroundWindow(IntPtr hWnd); // Send a series of key presses to the Calculator application. private: void button1_Click(Object^ sender, EventArgs^ e) { // Get a handle to the Calculator application. The window class // and window name were obtained using the Spy++ tool. IntPtr calculatorHandle = FindWindow("SciCalc", "Calculator"); // Verify that Calculator is a running process. if (calculatorHandle == IntPtr::Zero) { MessageBox::Show("Calculator is not running."); return; } // Make Calculator the foreground application and send it // a set of calculations. SetForegroundWindow(calculatorHandle); SendKeys::SendWait("111"); SendKeys::SendWait("*"); SendKeys::SendWait("11"); SendKeys::SendWait("="); }
範例
下列程式碼範例是先前程式碼範例的完整應用程式。
Imports System
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Windows.Forms
Namespace SimulateKeyPress
Class Form1
Inherits Form
Private WithEvents button1 As New Button()
<STAThread()> _
Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
Public Sub New()
button1.Location = New Point(10, 10)
button1.TabIndex = 0
button1.Text = "Click to automate Calculator"
button1.AutoSize = True
Me.Controls.Add(button1)
End Sub
' Get a handle to an application window.
Declare Auto Function FindWindow Lib "USER32.DLL" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
' Activate an application window.
Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean
' Send a series of key presses to the Calculator application.
Private Sub button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles button1.Click
' Get a handle to the Calculator application. The window class
' and window name were obtained using the Spy++ tool.
Dim calculatorHandle As IntPtr = FindWindow("SciCalc", "Calculator")
' Verify that Calculator is a running process.
If calculatorHandle = IntPtr.Zero Then
MsgBox("Calculator is not running.")
Return
End If
' Make Calculator the foreground application and send it
' a set of calculations.
SetForegroundWindow(calculatorHandle)
SendKeys.SendWait("111")
SendKeys.SendWait("*")
SendKeys.SendWait("11")
SendKeys.SendWait("=")
End Sub
' Send a key to the button when the user double-clicks anywhere
' on the form.
Private Sub Form1_DoubleClick(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.DoubleClick
' Send the enter key to the button, which raises the click
' event for the button. This works because the tab stop of
' the button is 0.
SendKeys.Send("{ENTER}")
End Sub
End Class
End Namespace
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
namespace SimulateKeyPress
{
class Form1 : Form
{
private Button button1 = new Button();
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
public Form1()
{
button1.Location = new Point(10, 10);
button1.TabIndex = 0;
button1.Text = "Click to automate Calculator";
button1.AutoSize = true;
button1.Click += new EventHandler(button1_Click);
this.DoubleClick += new EventHandler(Form1_DoubleClick);
this.Controls.Add(button1);
}
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
// Send a series of key presses to the Calculator application.
private void button1_Click(object sender, EventArgs e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("SciCalc", "Calculator");
// Verify that Calculator is a running process.
if (calculatorHandle == IntPtr.Zero)
{
MessageBox.Show("Calculator is not running.");
return;
}
// Make Calculator the foreground application and send it
// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");
}
// Send a key to the button when the user double-clicks anywhere
// on the form.
private void Form1_DoubleClick(object sender, EventArgs e)
{
// Send the enter key to the button, which raises the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys.Send("{ENTER}");
}
}
}
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Drawing;
using namespace System::Windows::Forms;
namespace SimulateKeyPress
{
public ref class Form1 : public Form
{
public:
Form1()
{
Button^ button1 = gcnew Button();
button1->Location = Point(10, 10);
button1->TabIndex = 0;
button1->Text = "Click to automate Calculator";
button1->AutoSize = true;
button1->Click += gcnew EventHandler(this, &Form1::button1_Click);
this->DoubleClick += gcnew EventHandler(this,
&Form1::Form1_DoubleClick);
this->Controls->Add(button1);
}
// Get a handle to an application window.
public:
[DllImport("USER32.DLL", CharSet = CharSet::Unicode)]
static IntPtr FindWindow(String^ lpClassName, String^ lpWindowName);
public:
// Activate an application window.
[DllImport("USER32.DLL")]
static bool SetForegroundWindow(IntPtr hWnd);
// Send a series of key presses to the Calculator application.
private:
void button1_Click(Object^ sender, EventArgs^ e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("SciCalc", "Calculator");
// Verify that Calculator is a running process.
if (calculatorHandle == IntPtr::Zero)
{
MessageBox::Show("Calculator is not running.");
return;
}
// Make Calculator the foreground application and send it
// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys::SendWait("111");
SendKeys::SendWait("*");
SendKeys::SendWait("11");
SendKeys::SendWait("=");
}
// Send a key to the button when the user double-clicks anywhere
// on the form.
private:
void Form1_DoubleClick(Object^ sender, EventArgs^ e)
{
// Send the enter key to the button, which triggers the click
// event for the button. This works because the tab stop of
// the button is 0.
SendKeys::Send("{ENTER}");
}
};
}
[STAThread]
int main()
{
Application::EnableVisualStyles();
Application::Run(gcnew SimulateKeyPress::Form1());
}
編譯程式碼
這項範例需要:
- System、System.Drawing 和 System.Windows.Forms 組件的參考。
如需從 Visual Basic 或 Visual C# 的命令列建置這個範例的詳細資訊,請參閱從命令列建置 (Visual Basic) 或使用 csc.exe 建置命令列。您也可以透過將程式碼貼入新的專案,在 Visual Studio 中建置此範例。