C#에서 마우스 매크로 만드는 것을 차례대로 진행 해보겠습니다. (코드는 맨 마지막에 있습니다!)
만들어본 후엔 필요한 기능을 추가하셔서 사용하시면 되겠습니다. (어렵지 않아요~)
먼저 Visual Studio에서 Windows Form 만들기를 해줍니다.

전 .NET Framework 를 사용하였는데 .NET Core를 선택하셔도 상관 없습니다.
.NET Framework는 Windows 에서만 사용 가능하고
.NET Core는 다른 운영체제에서도 사용 가능합니다. 점차 .NET Core를 밀고 있는 추세입니다만
전 윈도우로 하니깐 그냥 프레임워크로 가겠슴돠

이름은 MouseMacro 입니다. ㄱㄱ

다른 기능 다 필요없습니다. 일단 폼 크기를 마음대로 줄여줍니다.
그리고 오른쪽 하단에 있는 속성 창에서 딱 두가지만 세팅해줍니다. (폼 클릭하고도 속성창이 안보이면 F4 누르세요)
FormBorderStyle = FixedToolWindow
Text = Mouse Macro
로 설정해주겠습니다. 훌륭한 UI 세팅으로 여기까지 따라하셨다면 벌써 70% 완성했습니다.
이제 F7을 눌러서 (혹은 마우스 오른쪽 클릭-> 코드 보기) 코드 보기로 갑시다.

MouseMacro를 오른쪽 클릭하면 사진처럼 새 항목을 추가할 수 있게 됩니다. 눌러줍시다.

클래스를 새로 만들겁니다. 이름은 HookManager로 결정하겠습니다.
Win32 API 를 사용할 것이기 때문에 코드를 복사 붙여넣기 하면 됩니다.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MouseMacro
{
//C:\Windows\System32\user32.dll 참조
public class HookManager
{
#region WindowsAPI_Mouse Event
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
//Microsoft MouseEvent Document
//https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mouse_event
const uint MOUSEEVENTF_MOVE = 0x0001; // 마우스 이동
const uint MOUSEEVENTF_ABSOLUTE = 0x8000; // 전역 위치
const uint MOUSEEVENTF_LEFTDOWN = 0x0002; // 왼쪽 마우스 버튼 눌림
const uint MOUSEEVENTF_LEFTUP = 0x0004; // 왼쪽 마우스 버튼 떼어짐
const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; // 오른쪽 마우스 버튼 눌림
const uint MOUSEEVENTF_RIGHTUP = 0x00010; // 오른쪽 마우스 버튼 떼어짐
const uint MOUSEEVENTF_WHEEL = 0x0800; // 마우스 휠 (dwData 값으로 조정)
#endregion
#region WindowsAPI_Key Hook
//Microsoft Hook Document
//https://docs.microsoft.com/en-us/windows/win32/winmsg/hooks
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hInstance);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string lpFileName);
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private LowLevelKeyboardProc lowLevelKeyboardProc = HookProc;
//WM_Keydown
//https://wiki.winehq.org/List_Of_Windows_Messages
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 256;
const int WM_KEYUP = 257;
const int WM_SYSKEYDOWN = 260; //Alt Key Down
private static IntPtr hookId = IntPtr.Zero;
#endregion
//Custom Variables
private static Point preMousePosition;
private static int leftControl = 1;
private static int controlKey = 0;
private static uint wheel = 120;
private static uint backWheel = unchecked((uint)-120);
public void SetHook()
{
IntPtr hInstance = LoadLibrary("User32");
hookId = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, hInstance, 0);
}
public void UnHook()
{
UnhookWindowsHookEx(hookId);
}
public static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code >= 0)
{
if (wParam == (IntPtr)WM_KEYDOWN)
{
Keys key = (Keys)Marshal.ReadInt32(lParam);
switch (key)
{
case Keys.NumPad0:
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
return (IntPtr)1;
case Keys.NumPad1:
Cursor.Position = new Point(preMousePosition.X, preMousePosition.Y);
return (IntPtr)1;
case Keys.NumPad4:
preMousePosition = Cursor.Position;
return (IntPtr)1;
case Keys.LControlKey:
controlKey |= leftControl;
break;
case Keys.Up:
if (controlKey > 0)
{
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, wheel, 0);
return (IntPtr)1;
}
break;
case Keys.Down:
if (controlKey > 0)
{
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, backWheel, 0);
return (IntPtr)1;
}
break;
}
}
else if (wParam == (IntPtr)WM_KEYUP)
{
Keys key = (Keys)Marshal.ReadInt32(lParam);
switch (key)
{
case Keys.LControlKey:
controlKey &= ~leftControl;
break;
}
}
}
return CallNextHookEx(hookId, code, (int)wParam, lParam);
}
}
}
코드가 좀 길지만 다른 곳은 보지 말고 (관심 있다면 살펴봐도 좋습니다.)
public static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam)
이 곳만 보고 입 맛에 맞게 수정하면 됩니다.
로직을 설명해보면
if (code >= 0) // 무언가 키 이벤트가 발생했다.
if (wParam == (IntPtr)WM_KEYDOWN) //ㅇㅇ 키가 눌렸다고!
Keys key = (Keys)Marshal.ReadInt32(lParam)
key == Keys.???
이제 key가 무엇인지에 따라 동작을 해주면 됩니다.
(참고로 Alt 키는 wParam == WM_SYSKEYDOWN)
(Label 또는 MessageBox에 출력해서 값을 봐보는 것도 좋습니당)
위의 샘플 코드는 numpad4 : 현재 마우스 위치를 저장하고
numpad1 : 저장 된 마우스 위치로 마우스 커서 이동
numpad0 : 마우스 클릭 발생
ctrl + 마우스 위/아래 : ctrl + wheel을 구현한 것으로 확대, 축소 기능입니다.
자세한 것은 코드를 분석해보시면 되겠습니다. 친절하게 마우스와 키 값에 대한 링크도 해두었습니다!
이제 마무리로 HookManager를 인스턴스화 해서 사용하면 됩니다.
이벤트 두 개만 추가해봅시다. 다시 폼 뷰로 돌아와서 속성 창의 번개 모양을 클릭해줍니다.

그러면 이벤트를 등록할 수 있게 됩니다.
Load를 더블 클릭하면 코드가 자동으로 생성되는데 다시 폼뷰로 돌아와
FormClosing도 더블 클릭해줍니다.
이제 마지막 코드입니다. 간단해유
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MouseMacro
{
public partial class Form1 : Form
{
private HookManager hookManager;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//화면 가장 오른쪽에 띄우도록 합니다.
int x = Screen.PrimaryScreen.Bounds.Width - this.Size.Width;
int y = 0;
this.Location = new Point(x, y);
hookManager = new HookManager();
hookManager.SetHook();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
hookManager.UnHook();
}
}
}
로드 될 때 폼을 오른쪽 상단에 배치하고 훅을 시작합니다.
폼이 꺼질 때 훅을 해제 해주며 마무리 합니다.
여기까지 다 만드셨다면 간단한 마우스 매크로 성공입니다! 실행해서 확인해 보시고..
추가 기능은 HookManager의 HookProc 를 수정해서 사용해보세요~
'C# > Windows Form' 카테고리의 다른 글
[C# Windows Form] ListView 기본 사용법 (1) 컬럼 및 아이템 (0) | 2022.06.15 |
---|---|
[C#] .ini 파일 개념 및 사용 방법 ( GetPrivateProfileString, WritePrivateProfileString ) (0) | 2022.05.09 |
[C# Windows Form] 이미지 회전 시키기 (Image, Graphics) (0) | 2022.05.05 |
[C# Windows Form] 화면 캡쳐하기 (Bitmap .png) (0) | 2022.03.05 |
[C# Windows Form] 키보드 후킹 (0) | 2022.03.01 |