Instrukcje: symulowanie zdarzeń myszy i klawiatury w kodzie
Windows Forms oferuje kilka opcji programowego symulowania myszy i wprowadzania klawiatury. Ten temat zawiera omówienie tych opcji.
Symulowanie danych wejściowych myszy
Najlepszym sposobem symulowania zdarzeń myszy jest wywołanie metody On
EventName, która zgłasza zdarzenie myszy, które chcesz symulować. Ta opcja jest zwykle możliwa tylko w ramach niestandardowych kontrolek i formularzy, ponieważ metody, które zgłaszają zdarzenia, są chronione i nie mogą być dostępne poza kontrolką lub formularzem. Na przykład poniższe kroki ilustrują sposób symulowania kliknięcia prawego przycisku myszy w kodzie.
Aby programowo kliknąć prawym przyciskiem myszy
Utwórz MouseEventArgs, którego właściwość Button jest ustawiona na wartość MouseButtons.Right.
Wywołaj metodę OnMouseClick przy użyciu tej MouseEventArgs jako argumentu.
Aby uzyskać więcej informacji na temat kontrolek niestandardowych, zobacz Tworzenie kontrolek formularzy systemu Windows w czasie projektowania.
Istnieją inne sposoby symulowania danych wejściowych myszy. Można na przykład programowo ustawić właściwość kontrolki reprezentującą stan, który jest zwykle ustawiany za pomocą danych wejściowych myszy (takich jak właściwość Checked kontrolki CheckBox) lub bezpośrednio wywołać delegata dołączonego do zdarzenia, które chcesz symulować.
Symulowanie danych wejściowych klawiatury
Chociaż można symulować wprowadzanie z klawiatury przy użyciu strategii opisanych powyżej dla pracy myszy, Windows Forms również udostępnia klasę SendKeys do wysyłania naciśnięć klawiszy do aktywnej aplikacji.
Ostrożność
Jeśli aplikacja jest przeznaczona do użytku międzynarodowego z różnymi klawiaturami, użycie SendKeys.Send może przynieść nieprzewidywalne wyniki i należy unikać.
Uwaga
Klasa SendKeys została zaktualizowana dla programu .NET Framework 3.0 w celu włączenia jej użycia w aplikacjach uruchamianych w systemie Windows Vista. Zwiększone bezpieczeństwo systemu Windows Vista (znane jako Kontrola Konta Użytkownika, UAC) uniemożliwia poprzedniej implementacji działanie zgodnie z oczekiwaniami.
Klasa SendKeys jest podatna na problemy z synchronizacją, które zmusiły niektórych deweloperów do znalezienia obejścia. Zaktualizowana implementacja jest nadal podatna na problemy z synchronizacją czasu, ale jest nieco szybsza i może wymagać zmian w rozwiązaniach obejściowych. Klasa SendKeys próbuje najpierw użyć poprzedniej implementacji, a jeśli zakończy się to niepowodzeniem, użyje nowej implementacji. W związku z tym klasa SendKeys może zachowywać się inaczej w różnych systemach operacyjnych. Ponadto, gdy klasa SendKeys używa nowej implementacji, metoda SendWait nie będzie czekać na przetworzenie komunikatów podczas ich wysyłania do innego procesu.
Jeśli aplikacja opiera się na spójnym zachowaniu niezależnie od systemu operacyjnego, możesz wymusić użycie nowej implementacji klasy SendKeys przez dodanie następującego ustawienia aplikacji do pliku app.config.
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
Aby wymusić użycie poprzedniej implementacji klasy SendKeys, użyj wartości "JournalHook"
.
Aby wysłać naciśnięcie klawisza do tej samej aplikacji
Wywołaj metodę Send lub SendWait klasy SendKeys. Określone naciśnięcia zostaną odebrane przez aktywną kontrolę aplikacji. Poniższy przykład kodu używa Send do symulowania naciśnięcia ENTER, gdy użytkownik dwukrotnie kliknie powierzchnię formularza. W tym przykładzie przyjęto, że Form ma pojedynczą kontrolkę Button, która ma indeks tabulacji 0.
// 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 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 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
Aby wysłać naciśnięcie klawisza do innej aplikacji
Aktywuj okno aplikacji, które otrzyma naciśnięcie, a następnie wywołaj metodę Send lub SendWait. Ponieważ nie ma metody zarządzanej do aktywowania innej aplikacji, należy użyć natywnych metod systemu Windows, aby wymusić skupienie się na innych aplikacjach. Poniższy przykład kodu używa wywołania platformowego do wywoływania metod
FindWindow
iSetForegroundWindow
w celu aktywowania okna aplikacji Kalkulator, a następnie wywołuje SendWait w celu wykonania serii obliczeń w aplikacji Kalkulator.Notatka
Prawidłowe parametry wywołania
FindWindow
, które lokalizuje aplikację Kalkulator, różnią się w zależności od używanej wersji systemu Windows. Poniższy kod znajduje aplikację Kalkulator w systemie Windows 7. W systemie Windows Vista zmień pierwszy parametr na "SciCalc". Aby określić prawidłowe parametry, możesz użyć narzędzia Spy++, dołączonego do programu Visual Studio.// 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("="); }
// 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. 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
Przykład
Poniższy przykład kodu to kompletna aplikacja dla poprzednich przykładów kodu.
#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());
}
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}");
}
}
}
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
Kompilowanie kodu
Ten przykład wymaga:
- Odwołania do zestawów System, System.Drawing i System.Windows.Forms.
Zobacz też
.NET Desktop feedback