Поделиться через


Практическое руководство. Имитация событий мыши и клавиатуры в коде

Windows Forms предоставляют несколько возможностей для программной имитации ввода мыши и клавиатуры. В этом разделе приведен обзор этих возможностей.

Имитация ввода мыши

Наилучшим способом имитации событий мыши является вызов метода OnИмяСобытия, в результате чего происходит событие мыши, которое требуется имитировать. Этот вариант обычно возможен только в пределах пользовательских элементов управления и форм, так как методы, которые вызывают события, защищены и недоступны вне элемента управления или формы. Например, следующие шаги показывают, как имитировать нажатие правой кнопки мыши в коде.

Чтобы нажать правую кнопку мыши программными средствами, выполните следующие действия.

  1. Создайте класс MouseEventArgs и установите для его свойства Button значение MouseButtons.Right.

  2. Вызовите метод OnMouseClick с этим классом MouseEventArgs в качестве аргумента.

Дополнительные сведения о пользовательских элементах управления см. в разделе Создание элементов управления Windows Forms во время разработки.

Существуют другие способы имитировать ввод мыши. Например, можно программно установить свойство элемента управления, которое представляет состояние, обычно устанавливаемое с помощью ввода мыши (такое как свойство Checked элемента управления CheckBox), или напрямую вызвать делегат, который присоединен к событию, которое требуется имитировать.

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

Хотя ввод данных с клавиатуры можно имитировать с помощью подходов, описанных выше для ввода мыши, Windows Forms также предоставляет класс SendKeys для отправки нажатий клавиш активному приложению.

Предупреждение

Если приложение предназначено для международного использования с различными клавиатурами, использование метода SendKeys.Send может вызвать непредсказуемые результаты и его следует избегать.

Примечание

Класс SendKeys был обновлен в .NET Framework версии 3.0, чтобы позволить использовать его в приложениях, работающих в Windows Vista.Улучшенная система безопасности Windows Vista (известная как контроль учетных записей) предотвращает ожидаемую работу описанной выше реализации.

Класс SendKeys уязвим со стороны проблем со временем, что пришлось преодолевать некоторым разработчикам.Обновленная реализация по-прежнему уязвима со стороны проблем со временем, но она работает немного быстрее, и для решения существующих проблем может потребоваться ее переработка.Класс SendKeys пытается сначала использовать предыдущую реализацию и, в случае неудачи, использует новую реализацию.В результате, класс SendKeys может работать по-разному в разных операционных системах.Кроме того, при использовании классом SendKeys новой реализации метод SendWait не будет дожидаться обработки сообщений, если они отправляются другому процессу.

Если работа приложения подразумевает одинаковое поведение вне зависимости от операционной системы, можно принудительно использовать новую реализацию класса SendKeys, добавив следующий параметр приложения в файл конфигурации app.config.

<appSettings>

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

</appSettings>

Чтобы принудительно использовать предыдущую реализацию класса SendKeys, используйте значение "JournalHook".

Чтобы отправить нажатие клавиши тому же приложению, выполните следующие действия.

  • Вызовите метод Send или SendWait класса SendKeys. Указанная клавиша будет получена активным элементом управления приложения. В следующем примере метод Send используется для имитации нажатия клавиши ВВОД, когда пользователь дважды щелкает по поверхности формы. В этом примере используется форма Form с одним элементом управления Button, имеющим порядок переходов по клавише TAB равный 0.

    ' 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. Из-за отсутствия управляемого способа активации другого приложения необходимо использовать собственные методы Windows для принудительной установки фокуса на другие приложения. В следующем примере используется платформозависимый вызов для вызова методов FindWindow и SetForegroundWindow для активизации окна приложения "Калькулятор", а затем вызывается метод SendWait для проведения ряда вычислений в приложении калькулятор.

    Примечание

    Правильные параметры вызова FindWindow, находящего приложение "Калькулятор", варьируются в зависимости от версии Windows.Следующий код находит приложение "Калькулятор" в Windows 7.В Windows Vista измените первый параметр на SciCalc.Можно использовать средство Spy++, входящее в Visual Studio, для определения правильных параметров.

    ' 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("=");
            }
    

Пример

В следующем примере полностью представлено приложение для предыдущих примеров кода.

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());
}

Компиляция кода

Для этого примера требуются следующие компоненты

  • Ссылки на сборки System, System.Drawing и System.Windows.Forms.

Дополнительные сведения о построении этого примера из командной строки для Visual Basic или Visual C# см. в разделе Построение из командной строки (Visual Basic) или Построение из командной строки с помощью csc.exe. Можно также построить этот пример в Visual Studio путем вставки кода в новый проект. Дополнительные сведения см. в следующем разделе. Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio и Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio и Практическое руководство. Компиляция и выполнение откомпилированного примера кода формы Windows Forms с помощью Visual Studio.

См. также

Другие ресурсы

Ввод данных пользователем в Windows Forms