Практическое руководство. Имитация событий мыши и клавиатуры в кодеHow to: Simulate Mouse and Keyboard Events in Code

В Windows Forms предоставляется несколько возможностей для программной имитации ввода данных с помощью мыши и клавиатуры.Windows Forms provides several options for programmatically simulating mouse and keyboard input. В этом разделе приведен обзор этих возможностей.This topic provides an overview of these options.

Имитация ввода с помощью мышиSimulating Mouse Input

Наилучшим способом имитации событий мыши является вызов метода OnEventName , в результате чего происходит событие мыши, которое требуется имитировать.The best way to simulate mouse events is to call the OnEventName method that raises the mouse event you want to simulate. Этот вариант обычно возможен только в пределах пользовательских элементов управления и форм, так как методы, которые вызывают события, защищены и недоступны вне элемента управления или формы.This option is usually possible only within custom controls and forms, because the methods that raise events are protected and cannot be accessed outside the control or form. Например, ниже показано, как имитировать нажатие правой кнопки мыши в коде.For example, the following steps illustrate how to simulate clicking the right mouse button in code.

Чтобы нажать правую кнопку мыши программными средствами, выполните указанные ниже действия.To programmatically click the right mouse button

  1. Создайте объект MouseEventArgs и установите для его свойства Button значение MouseButtons.Right .Create a MouseEventArgs whose Button property is set to the MouseButtons.Right value.

  2. Вызовите метод OnMouseClick с этим объектом MouseEventArgs в качестве аргумента.Call the OnMouseClick method with this MouseEventArgs as the argument.

Дополнительные сведения о пользовательских элементах управления см. в разделе Создание элементов управления Windows Forms во время разработки.For more information on custom controls, see Developing Windows Forms Controls at Design Time.

Существуют другие способы имитировать ввод с помощью мыши.There are other ways to simulate mouse input. Например, можно программно установить свойство элемента управления, которое представляет состояние, обычно устанавливаемое с помощью ввода мыши (например, свойство Checked элемента управления CheckBox ), или напрямую вызвать делегат, связанный с событием, которое нужно имитировать.For example, you can programmatically set a control property that represents a state that is typically set through mouse input (such as the Checked property of the CheckBox control), or you can directly call the delegate that is attached to the event you want to simulate.

Имитация ввода с клавиатурыSimulating Keyboard Input

Хотя ввод данных с клавиатуры можно имитировать с помощью подходов, описанных выше для ввода с помощью мыши, Windows Forms также предоставляет класс SendKeys для отправки нажатий клавиш в активное приложение.Although you can simulate keyboard input by using the strategies discussed above for mouse input, Windows Forms also provides the SendKeys class for sending keystrokes to the active application.

Внимание!

Если приложение предназначено для международного использования с различными клавиатурами, применение метода SendKeys.Send может иметь непредсказуемые результаты и его следует избегать.If your application is intended for international use with a variety of keyboards, the use of SendKeys.Send could yield unpredictable results and should be avoided.

Примечание

Класс SendKeys был обновлен в .NET Framework 3.0, что позволило использовать его в приложениях, работающих в Windows Vista.The SendKeys class has been updated for the .NET Framework 3.0 to enable its use in applications that run on Windows Vista. Усиленная система безопасности Windows Vista (известная как контроль учетных записей или UAC) не позволяет предыдущей реализации работать должным образом.The enhanced security of Windows Vista (known as User Account Control or UAC) prevents the previous implementation from working as expected.

Класс SendKeys подвержен проблемам со временем, которые пришлось решать некоторым разработчикам.The SendKeys class is susceptible to timing issues, which some developers have had to work around. Обновленная реализация по-прежнему подвержена этим проблемам, но она работает немного быстрее, поэтому существующие решения может потребоваться переработать.The updated implementation is still susceptible to timing issues, but is slightly faster and may require changes to the workarounds. Класс SendKeys сначала пытается использовать предыдущую реализацию, и если это не удается, использует новую реализацию.The SendKeys class tries to use the previous implementation first, and if that fails, uses the new implementation. В результате класс SendKeys может работать по-разному в разных операционных системах.As a result, the SendKeys class may behave differently on different operating systems. Кроме того, при использовании новой реализации класса SendKeys метод SendWait не будет дожидаться обработки сообщений, если они отправляются другому процессу.Additionally, when the SendKeys class uses the new implementation, the SendWait method will not wait for messages to be processed when they are sent to another process.

Если необходимо обеспечить согласованное поведение приложения независимо от операционной системы, можно заставить класс SendKeys использовать новую реализацию, добавив указанный ниже параметр приложения в файл app.config.If your application relies on consistent behavior regardless of the operating system, you can force the SendKeys class to use the new implementation by adding the following application setting to your app.config file.

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

Для принудительного использования классом SendKeys предыдущей реализации задайте значение "JournalHook" .To force the SendKeys class to use the previous implementation, use the value "JournalHook" instead.

Отправка нажатия клавиши в то же приложениеTo send a keystroke to the same application

  1. Вызовите метод Send или SendWait класса SendKeys .Call the Send or SendWait method of the SendKeys class. Указанные нажатия клавиш будут получены активным элементом управления приложения.The specified keystrokes will be received by the active control of the application. В примере кода ниже метод Send используется для имитации нажатия клавиши ВВОД, когда пользователь дважды щелкает по поверхности формы.The following code example uses Send to simulate pressing the ENTER key when the user double-clicks the surface of the form. В этом примере используется форма Form с одним элементом управления Button , имеющим индекс перехода по клавише TAB, равный 0.This example assumes a Form with a single Button control that has a tab index of 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
    

Отправка нажатия клавиши в другое приложениеTo send a keystroke to a different application

  1. Активируйте окно приложения, которое будет получать нажатия клавиш, а затем вызовите метод Send или SendWait .Activate the application window that will receive the keystrokes, and then call the Send or SendWait method. Из-за отсутствия управляемого метода активации другого приложения необходимо использовать собственные методы Windows для принудительной установки фокуса на другие приложения.Because there is no managed method to activate another application, you must use native Windows methods to force focus on other applications. В примере кода ниже с помощью вызова неуправляемого кода вызываются методы FindWindow и SetForegroundWindow для активации окна приложения "Калькулятор", а затем вызывается метод SendWait для проведения ряда вычислений в этом приложении.The following code example uses platform invoke to call the FindWindow and SetForegroundWindow methods to activate the Calculator application window, and then calls SendWait to issue a series of calculations to the Calculator application.

    Примечание

    Параметры вызова FindWindow для определения положения Калькулятора зависят от версии Windows.The correct parameters of the FindWindow call that locates the Calculator application vary based on your version of Windows. Приведенный ниже код находит Калькулятор в Windows 7Windows 7.The following code finds the Calculator application on Windows 7Windows 7. В Windows VistaWindows Vistaизмените первый параметр на SciCalc.On Windows VistaWindows Vista, change the first parameter to "SciCalc". Для определения нужных параметров можно использовать средство Spy++, входящее в состав Visual Studio.You can use the Spy++ tool, included with Visual Studio, to determine the correct parameters.

        // 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
    

ПримерExample

В примере ниже полностью представлено приложение для предыдущих примеров кода.The following code example is the complete application for the previous code examples.

#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

Компиляция кодаCompiling the Code

Для этого примера требуются:This example requires:

  • ссылки на сборки System, System.Drawing и System.Windows.Forms.References to the System, System.Drawing and System.Windows.Forms assemblies.

См. такжеSee also