Gewusst wie: Simulieren von Maus- und Tastaturereignissen in Code
Windows Forms stellen mehrere Optionen zur programmgesteuerten Simulation von Maus- und Tastatureingaben bereit. Dieses Thema enthält eine Übersicht über diese Optionen.
Simulieren von Mauseingaben
Die beste Möglichkeit, Mauseingaben zu simulieren, ist ein Aufruf der OnEreignisname-Methode, die das gewünschte Mausereignis auslöst. Diese Möglichkeit besteht normalerweise nur bei benutzerdefinierten Steuerelementen und Formularen, da die Methoden, die Ereignisse auslösen, geschützt sind und außerhalb des Steuerelements oder Formulars nicht aufgerufen werden können. Die folgenden Schritte veranschaulichen beispielsweise, wie das Klicken mit der rechten Maustaste in Code simuliert wird.
So klicken Sie programmgesteuert mit der rechten Maustaste
Erstellen Sie ein MouseEventArgs, dessen Button-Eigenschaft auf den MouseButtons.Right-Wert festgelegt ist.
Rufen Sie die OnMouseClick-Methode mit diesem MouseEventArgs als Argument auf.
Weitere Informationen zu benutzerdefinierten Steuerelementen finden Sie unter Entwickeln von Windows Forms-Steuerelementen zur Entwurfszeit.
Mauseingaben können auch auf andere Weise simuliert werden. Beispielsweise können Sie programmgesteuert eine Steuerelementeigenschaft festlegen, die einen Zustand darstellt, der normalerweise per Mauseingabe festgelegt wird (z. B. die Checked-Eigenschaft des CheckBox-Steuerelements). Sie können aber auch direkt den Delegaten aufrufen, der mit dem Ereignis verknüpft ist, das Sie simulieren möchten.
Simulieren von Tastatureingaben
Tastatureingaben können mit denselben Strategien simuliert werden, die auch für Mauseingaben gelten. Dennoch stellt Windows Forms die SendKeys-Klasse bereit, um Tastatureingaben an die aktive Anwendung zu senden.
Warnung
Wenn die Anwendung für den internen Gebrauch mit verschiedenen Tastaturen vorgesehen ist, könnte die Verwendung von SendKeys.Send unvorhersehbare Ergebnisse hervorrufen und sollte vermieden werden.
Tipp
Die SendKeys-Klasse wurde für .NET Framework 3.0 aktualisiert, um die Verwendung in Anwendungen unter Windows Vista zu ermöglichen. Durch die erhöhte Sicherheit von Windows Vista (die Benutzerkontensteuerung) kann die vorherige Implementierung nicht erwartungsgemäß ausgeführt werden.
Die SendKeys-Klasse ist anfällig für Probleme bei der zeitlichen Steuerung, die einige Entwickler umgehen mussten. Die aktualisierte Implementierung ist noch immer anfällig für diese Probleme, ist jedoch etwas schneller und erfordert möglicherweise Änderungen an den Problemumgehungen. Die SendKeys-Klasse versucht zunächst, die vorherige Implementierung zu verwenden. Wenn dies nicht gelingt, wird die neue Implementierung verwendet. Infolgedessen verhält sich die SendKeys-Klasse auf verschiedenen Betriebssystemen möglicherweise unterschiedlich. Außerdem wartet bei Verwendung der neuen Implementierung durch die SendKeys-Klasse die SendWait-Methode nicht die Verarbeitung von Meldungen ab, wenn diese an einen anderen Prozess gesendet werden.
Wenn die Anwendung auf ein vom Betriebssystem unabhängiges, einheitliches Verhalten angewiesen ist, können Sie die Verwendung der neuen Implementierung durch die SendKeys-Klasse erzwingen, indem Sie der app.config-Datei die folgende Anwendungseinstellung hinzufügen.
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
Um die Verwendung der vorherigen Implementierung durch die SendKeys-Klasse zu erzwingen, verwenden Sie stattdessen den Wert "JournalHook".
So senden Sie eine Tastatureingabe an dieselbe Anwendung
Rufen Sie die Send-Methode oder die SendWait-Methode der SendKeys-Klasse auf. Die angegebenen Tastatureingaben werden vom aktiven Steuerelement der Anwendung empfangen. Im folgenden Codebeispiel wird mithilfe von Send das Drücken der EINGABETASTE simuliert, wenn der Benutzer auf die Oberfläche des Formulars doppelklickt. Für dieses Beispiel ist ein Form mit einem einzelnen Button-Steuerelement erforderlich, das über einen Registerkartenindex von 0 verfügt.
' 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}"); }
So senden Sie eine Tastatureingabe an eine andere Anwendung
Aktivieren Sie das Anwendungsfenster, das die Tastatureingaben empfängt, und rufen Sie dann die Send-Methode oder die SendWait-Methode auf. Da keine verwaltete Methode zum Aktivieren einer anderen Anwendung vorhanden ist, müssen Sie mit systemeigenen Windows-Methoden den Fokus auf andere Anwendungen erzwingen. Im folgenden Codebeispiel wird die Plattformaktivierung zum Aufrufen der FindWindow-Methode und der SetForegroundWindow-Methode verwendet, um das Anwendungsfenster Rechner zu aktivieren. Anschließend wird SendWait aufgerufen, um eine Reihe von Berechnungen in der Rechneranwendung auszugeben.
Tipp
Die richtigen Parameter des FindWindow-Aufrufs, der die Anwendung Rechner sucht, können auf Grundlage der Version von Windows unterschiedlich lauten. Im folgenden Code wird die Anwendung Rechner unter Windows 7 gesucht. Ändern Sie unter Windows Vista den ersten Parameter in "SciCalc". Sie können mit dem in Visual Studio enthaltenen Tool Spy++ die richtigen Parameter bestimmen.
' 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("CalcFrame", "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("CalcFrame","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("CalcFrame", "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("="); }
Beispiel
Das folgende Codebeispiel ist die vollständige Anwendung für die vorherigen Codebeispiele.
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("CalcFrame", "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("CalcFrame","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("CalcFrame", "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());
}
Kompilieren des Codes
Für dieses Beispiel ist Folgendes erforderlich:
- Verweise auf die Assemblys System, System.Drawing und System.Windows.Forms.
Informationen zum Erstellen dieses Beispiels über die Befehlszeile für Visual Basic oder Visual C# finden Sie unter Erstellen von der Befehlszeile aus (Visual Basic) oder unter Erstellen über die Befehlszeile mit csc.exe. Sie können dieses Beispiel auch in Visual Studio erstellen, indem Sie den Code in ein neues Projekt einfügen. Weitere Informationen finden Sie unter Gewusst wie: Kompilieren und Ausführen eines vollständigen Windows Forms-Codebeispiels mit Visual Studio und Gewusst wie: Kompilieren und Ausführen eines vollständigen Windows Forms-Codebeispiels mit Visual Studio und Gewusst wie: Kompilieren und Ausführen eines vollständigen Windows Forms-Codebeispiels mit Visual Studio und Gewusst wie: Kompilieren und Ausführen eines vollständigen Windows Forms-Codebeispiels mit Visual Studio und Gewusst wie: Kompilieren und Ausführen eines vollständigen Windows Forms-Codebeispiels mit Visual Studio.