Porady: 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 Onmetody EventName , która wywołuje 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

  1. Utwórz właściwość, której MouseEventArgsButton właściwość jest ustawiona MouseButtons.Right na wartość.

  2. Wywołaj metodę za OnMouseClick pomocą tej MouseEventArgs metody jako argument.

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 Checked właściwość CheckBox kontrolki) lub bezpośrednio wywołać delegata dołączonego do zdarzenia, które chcesz symulować.

Symulowanie danych wejściowych klawiatury

Chociaż można symulować wprowadzanie klawiatury przy użyciu strategii opisanych powyżej dla wprowadzania myszy, formularze systemu Windows udostępniają również klasę SendKeys wysyłania naciśnięć klawiszy do aktywnej aplikacji.

Uwaga

Jeśli aplikacja jest przeznaczona do użytku międzynarodowego z różnymi klawiaturami, użycie SendKeys.Send metody 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 jego użycia w aplikacjach uruchamianych w systemie Windows Vista. Zwiększone bezpieczeństwo systemu Windows Vista (nazywanego kontrolą konta użytkownika lub kontrola konta użytkownika) uniemożliwia poprzedniej implementacji działanie zgodnie z oczekiwaniami.

Klasa jest podatna SendKeys na problemy z chronometrażem, które niektórzy deweloperzy musieli obejść. Zaktualizowana implementacja jest nadal podatna na problemy z chronometrażem, ale jest nieco szybsza i może wymagać zmian w obejściach. Klasa SendKeys próbuje najpierw użyć poprzedniej implementacji i jeśli zakończy się to niepowodzeniem, użyj nowej implementacji. W związku z tym SendKeys klasa może zachowywać się inaczej w różnych systemach operacyjnych. Ponadto, gdy SendKeys klasa używa nowej implementacji, SendWait metoda 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ć SendKeys użycie nowej implementacji przez dodanie następującego ustawienia aplikacji do pliku app.config.

<appSettings>
 <add key="SendKeys" value="SendInput"/>
</appSettings>

Aby wymusić SendKeys użycie poprzedniej implementacji klasy, użyj wartości "JournalHook" .

Aby wysłać naciśnięcie klawiszy do tej samej aplikacji

  1. Wywołaj metodę SendSendKeys or SendWait klasy . Określone naciśnięcia klawiszy zostaną odebrane przez aktywną kontrolę aplikacji. Poniższy przykład kodu używa Send metody do symulowania naciśnięcia klawisza ENTER, gdy użytkownik dwukrotnie kliknie powierzchnię formularza. W tym przykładzie przyjęto Form założenie, że element z pojedynczą Button kontrolką 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 klawiszy do innej aplikacji

  1. Aktywuj okno aplikacji, które otrzyma naciśnięcia klawiszy, a następnie wywoła metodę Send or 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 platformy w celu wywołania FindWindow metody i SetForegroundWindow w celu aktywowania okna aplikacji Kalkulator, a następnie wywołuje wywołania SendWait w celu wystawienia serii obliczeń w aplikacji Kalkulator.

    Uwaga

    Prawidłowe parametry FindWindow wywołania, 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ż