방법: 코드에서 마우스 및 키보드 이벤트 시뮬레이션
업데이트: 2007년 11월
Windows Forms에서는 마우스 및 키보드 입력을 프로그래밍 방식으로 시뮬레이션하는 여러 옵션을 사용할 수 있습니다. 이 항목에서는 이러한 옵션에 대해 간략하게 설명합니다.
마우스 입력 시뮬레이션
마우스 이벤트를 시뮬레이션하는 가장 좋은 방법은 시뮬레이션할 마우스 이벤트를 발생시키는 OnEventName 메서드를 호출하는 것입니다. 이벤트를 발생시키는 메서드가 보호되어 컨트롤이나 폼 외부에서 이에 액세스할 수 없기 때문에 일반적으로 사용자 지정 컨트롤 및 폼 내에서만 이 옵션을 사용할 수 있습니다. 예를 들어, 다음 단계에서는 코드의 오른쪽 마우스 단추 클릭을 시뮬레이션하는 방법을 보여 줍니다.
프로그래밍 방식으로 마우스 오른쪽 단추를 클릭하려면
Button 속성이 MouseButtons.Right 값으로 설정된 MouseEventArgs를 만듭니다.
만든 MouseEventArgs를 인수로 사용하여 OnMouseClick 메서드를 호출합니다.
사용자 지정 컨트롤에 대한 자세한 내용은 디자인할 때 Windows Forms 컨트롤 개발을 참조하십시오.
다른 방법으로 마우스 입력을 시뮬레이션할 수도 있습니다. 예를 들어, 일반적으로 마우스 입력을 통해 설정되는 상태를 나타내는 컨트롤 속성(예: CheckBox 컨트롤의 Checked 속성)을 프로그래밍 방식으로 설정하거나 시뮬레이션할 이벤트에 연결된 대리자를 직접 호출할 수 있습니다.
키보드 입력 시뮬레이션
마우스 입력에 대해 위에서 설명한 전략을 사용하여 키보드 입력을 시뮬레이션할 수 있지만 키 입력을 활성 응용 프로그램으로 보내는 Windows Forms SendKeys 클래스를 사용하여 시뮬레이션할 수도 있습니다.
주의: |
---|
다양한 키보드를 통해 국제적으로 사용하기 위한 응용 프로그램의 경우 예기치 않은 결과가 발생할 수 있으므로 SendKeys.Send를 사용해서는 안 됩니다. |
참고: |
---|
.NET Framework 3.0에서는 SendKeys 클래스가 Windows Vista에서 실행되는 응용 프로그램에서 사용할 수 있도록 업데이트되었습니다. Windows Vista에는 UAC(사용자 계정 컨트롤)라는 향상된 보안 기능이 있어 이전에 구현된 클래스가 예상대로 작동하지 않습니다. 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를 호출하여 계산기 응용 프로그램에 일련의 계산을 실행합니다.
' 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("SciCalc", "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("SciCalc", "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("SciCalc", "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("SciCalc", "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("SciCalc", "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("SciCalc", "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에서 코드를 새 프로젝트에 붙여넣어 이 예제를 빌드할 수도 있습니다.