Share via


방법: 코드에서 마우스 및 키보드 이벤트 시뮬레이션

Windows Forms에서는 마우스 및 키보드 입력을 프로그래밍 방식으로 시뮬레이션하는 여러 옵션을 사용할 수 있습니다. 이 항목에서는 이러한 옵션에 대해 간략하게 설명합니다.

마우스 입력 시뮬레이션

마우스 이벤트를 시뮬레이션하는 가장 좋은 방법은 시뮬레이션할 마우스 이벤트를 발생시키는 OnEventName 메서드를 호출하는 것입니다. 이벤트를 발생시키는 메서드가 보호되어 컨트롤이나 폼 외부에서 이에 액세스할 수 없기 때문에 일반적으로 사용자 지정 컨트롤 및 폼 내에서만 이 옵션을 사용할 수 있습니다. 예를 들어, 다음 단계에서는 코드의 오른쪽 마우스 단추 클릭을 시뮬레이션하는 방법을 보여 줍니다.

프로그래밍 방식으로 마우스 오른쪽 단추를 클릭하려면

  1. Button 속성이 MouseButtons.Right 값으로 설정된 MouseEventArgs를 만듭니다.

  2. 만든 MouseEventArgs를 인수로 사용하여 OnMouseClick 메서드를 호출합니다.

사용자 지정 컨트롤에 대한 자세한 내용은 디자인할 때 Windows Forms 컨트롤 개발를 참조하십시오.

다른 방법으로 마우스 입력을 시뮬레이션할 수도 있습니다. 예를 들어, 일반적으로 마우스 입력을 통해 설정되는 상태를 나타내는 컨트롤 속성(예: CheckBox 컨트롤의 Checked 속성)을 프로그래밍 방식으로 설정하거나 시뮬레이션할 이벤트에 연결된 대리자를 직접 호출할 수 있습니다.

키보드 입력 시뮬레이션

마우스 입력에 대해 위에서 설명한 전략을 사용하여 키보드 입력을 시뮬레이션할 수 있지만 키 입력을 활성 응용 프로그램으로 보내는 Windows Forms SendKeys 클래스를 사용하여 시뮬레이션할 수도 있습니다.

경고

다양한 키보드를 통해 국제적으로 사용하기 위한 응용 프로그램의 경우 예기치 않은 결과가 발생할 수 있으므로 SendKeys.Send를 사용해서는 안 됩니다.

참고

.NET Framework 3.0에서는 SendKeys 클래스가 Windows Vista에서 실행되는 응용 프로그램에서 사용할 수 있도록 업데이트되었습니다. 이전 구현은 UAC(사용자 계정 컨트롤)라는 Windows Vista의 향상된 보안 기능으로 인해 예상대로 작동하지 않습니다.

SendKeys 클래스는 일부 개발자들이 해결하려고 노력했던 타이밍 문제를 발생시킬 수 있습니다. 업데이트된 구현은 타이밍 문제를 발생시킬 수도 있지만 약간 빠르므로 해당 타이밍 문제를 해결할 때 이전 방법과 다소 다른 방법이 필요할 수 있습니다. SendKeys 클래스는 먼저 이전 구현을 사용해 보고 해당 구현이 실패하면 새 구현을 사용합니다. 따라서 운영 체제에 따라 SendKeys 클래스가 다르게 동작할 수 있습니다. 또한 SendKeys 클래스가 새 구현을 사용할 경우 SendWait 메서드는 다른 프로세스로 메시지 전송 시 메시지가 처리될 때까지 기다리지 않습니다.

응용 프로그램이 운영 체제에 관계없이 일관된 동작을 기반으로 하는 경우 app.config 파일에 다음 응용 프로그램 설정을 추가하여 SendKeys 클래스가 새 구현을 사용하게 할 수 있습니다.

<appSettings>

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

</appSettings>

SendKeys 클래스에서 항상 이전 구현을 사용하도록 지정하려면 "JournalHook" 값을 대신 사용합니다.

동일한 응용 프로그램으로 키 입력을 보내려면

  • SendKeys 클래스의 Send 또는 SendWait 메서드를 호출합니다. 응용 프로그램의 활성 컨트롤이 지정된 키 입력을 받습니다. 다음 코드 예제에서는 Send를 사용하여 사용자가 폼 화면을 두 번 클릭할 때 Enter 키를 누르는 작업을 시뮬레이션합니다. 이 예제에서는 탭 인덱스가 0인 단일 Button 컨트롤이 포함된 Form이 있다고 가정합니다.

    ' 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"로 변경합니다. 올바른 매개 변수를 결정하기 위해 Visual Studio에 포함된 Spy++ 도구를 사용할 수 있습니다.

    ' 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에서 코드를 새 프로젝트에 붙여넣어 이 예제를 빌드할 수도 있습니다. 자세한 내용은 다음을 참조하십시오. 방법: Visual Studio를 사용하여 전체 Windows Forms 코드 예제 컴파일 및 실행방법: Visual Studio를 사용하여 전체 Windows Forms 코드 예제 컴파일 및 실행방법: Visual Studio를 사용하여 전체 Windows Forms 코드 예제 컴파일 및 실행방법: Visual Studio를 사용하여 전체 Windows Forms 코드 예제 컴파일 및 실행방법: Visual Studio를 사용하여 전체 Windows Forms 코드 예제 컴파일 및 실행.

참고 항목

기타 리소스

Windows Forms에 사용자 입력