C# 2부 - 누구나 쉽게 할 수 있는 C# 매크로 만들기. (마우스 클릭하기.)
페이지 정보
본문
안녕하세요. 엔지엠소프트웨어입니다. 비개발자분들을 대상으로 작성하는 글이라서 아주~ 세세한 부분까지 다 스샷을 떠가면서 도움말을 작성하고 있습니다. 따라서, 개발자분들이 이 글을 보시면 상당히 답답할 수 있는데요. 사실 개발자라면... 굳이 이글을 안보더라도 매크로쯤은 뚝딱! 만들어 낼겁니다. 매크로 만들기 예제들은 인터넷에 널리고 널렸으니까요^^; 이전 1부 내용을 아직 안보신 분들은 [ 여기 ]를 클릭해서 개발 환경을 먼저 갖추고 이 글을 보셔야 합니다~ 비주얼 스튜디오를 실행하고, MyPlayer 프로젝트를 불러옵니다.
매크로를 실행하고, 중지할 수 있는 버튼을 만드는것부터 시작해야 합니다. 아래 동영상을 참고해서 버튼 2개를 추가하고, 각각 표시할 텍스트를 수정 해주세요.
각각의 버튼을 더블 클릭하면 버튼을 눌렀을 때 동작해야 하는 이벤트 처리기를 자동으로 추가 해줍니다.
C#에는 윈도우에 마우스 이벤트를 줄 수 있는 기능이 없습니다. 그래서, 윈도우 API인 win32 라이브러리를 이용해야 합니다. 다행스럽게도~ C나 C++처럼 윈도우 라이브러리를 쉽게 가져와서 사용할 수 있습니다. 이제 마우스 클릭에 대한 코드를 작성 해볼까요? 아래 2줄을 추가하세요.
const uint LBUTTONDOWN = 0x0002; // 왼쪽 마우스 버튼 누름
const uint LBUTTONUP = 0x0004; // 왼쪽 마우스 버튼 땜
전체 코드는 아래와 같습니다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MyPlayer
{
public partial class Form1 : Form
{
const uint LBUTTONDOWN = 0x0002; // 왼쪽 마우스 버튼 누름
const uint LBUTTONUP = 0x0004; // 왼쪽 마우스 버튼 땜
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
주석(// ...)에도 설명을 달아두었지만, 마우스 클릭은 기본적으로 마우스를 누르고 때는 동작을 말합니다. 그렇기 때문에 LBUTTONDOWN과 LBUTTONUP으로 윈도우에 신호를 줘야 합니다. 신호 값은 0x0002와 0x0004와 같은 16진수 값입니다. 이 값은 컴퓨터 언어로 우리가 외워서 사용하기는 쉽지 않습니다. 2개정도야 뭐 문제가 안되겠지만요^^; 매크로를 만들다보면 무수히 많은 비트 값을 처리해야 하는데요. 이런 값들을 사용하기 쉽게 하려고 이름을 지어준다고 생각하시면 이해하기 쉬울겁니다. 아래와 같이 win32 라이브러리를 추가 해줍니다.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MyPlayer
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
const uint LBUTTONDOWN = 0x0002; // 왼쪽 마우스 버튼 누름
const uint LBUTTONUP = 0x0004; // 왼쪽 마우스 버튼 땜
그냥 알아보기 쉽게 숫자를 사용하면 될텐데 왜 16진수를 사용하는지 약간 궁금할수도 있습니다. 16진수는 0부터 F까지 16개의 수를 가집니다.
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
대부분의 프로그래밍 언어에서 숫자(Integer)는 2바이트로 이루어져 있습니다. 1바이트는 8비트로 이루어져 있죠. 그래서 숫자형은 16비트입니다. 8비트를 반으로 나누면 4비트가 되는데 4비트는 1부터 16까지 표현이 가능합니다. 이는 컴퓨터의 CPU가 한번에 처리할 수 있는 최소 단위와 동일해서 2진수와 변환이 쉬운 16진수를 사용하게 되었습니다. 그래서 16비트의 숫자형에는 0xFFFF까지 넣을 수 있습니다. 요즘은 32비트, 64비트를 한번에 처리할 수 있습니다. 초창기에 컴퓨터 처리 단위가 지금까지 이어져서 사용된다고 이해하면 되겠습니다^^; 홈페이지 어딘가에... CPU, Memory, 컴퓨터에 대해 작성해둔 글이 있는데 한번 찾아보시면 좋을거 같네요.
위 코드에서 불필요한 using은 제거한 상태입니다. 일단, DllImport는 비관리 라이브러리에서 정적 메소드를 사용할 수 있도록 해주는 C# 특성(Attribute)입니다. 점점 어려운 용어들이 나오고 있어서... 설명해야 하나 말아야 하나 고민이 깊어집니다. 개발자라면 그냥 아는 이야기들인데요. 이걸 설명하려면 또 많은 시간을 잡아먹을듯 하군요. 여러분들은 단순히 비관리(C나 C++로 만들어진 동적 라이브러리) 기능을 가져다가 쓸 때 이 특성을 이용하면 된다고 이해하시면 됩니다. 바탕화면의 아이콘들의 좌표를 알아내기 위해 엔지엠 에디터를 실행하고, 마우스 액션을 하나 추가 해줍니다.
우측 속성창에서 마우스 좌표 속성을 선택하세요. 그러면, 우측에 "..." 버튼이 표시됩니다.
"..." 버튼을 클릭한 후 바탕화면의 "내 PC" 로 이동하세요. 그리고, F1을 누르면 해당 좌표를 확인할 수 있습니다. 제 모니터 해상도(1920x1080) 기준 "내 PC"의 좌표는 "40, 31"입니다. 이 값을 아래와 같이 마우스 클릭 좌표로 사용하면 됩니다. 완성된 전체 코드입니다.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MyPlayer
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
const uint LBUTTONDOWN = 0x0002; // 왼쪽 마우스 버튼 누름
const uint LBUTTONUP = 0x0004; // 왼쪽 마우스 버튼 땜
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Cursor.Position = new Point(40, 31); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
간단하죠? 이제 정상적으로 동작하는지 테스트를 해볼까요? 비주얼 스튜디오에서 F5(실행)를 누르거나 아래 동영상처럼 ▶ 버튼을 클릭해도 됩니다. 우리가 만든 프로그램이 컴파일된 후 아래와 같은 프로그램이 실행됩니다. 여기서 실행 버튼을 클릭하면 정확하게 내 PC를 클릭합니다.
순차적으로 바탕화면의 모든 아이콘을 클릭 해볼까요? 엔지엠 에디터에서 마우스 클릭 액션의 "..."을 눌러서 각각의 좌표를 알아냅니다. 그리고, 아래와 같이 코드를 3번 복사한 후 좌표 값만 변경 해줍니다. 이 때 X 좌표는 동일하므로 Y 좌표만 변경해주면 됩니다.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MyPlayer
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
const uint LBUTTONDOWN = 0x0002; // 왼쪽 마우스 버튼 누름
const uint LBUTTONUP = 0x0004; // 왼쪽 마우스 버튼 땜
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Cursor.Position = new Point(40, 31); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
Cursor.Position = new Point(40, 109); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
Cursor.Position = new Point(40, 195); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
Cursor.Position = new Point(40, 278); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
다시 실행 해보면, 아래 동영상처럼 동작 할겁니다. 그런데 마우스가 순차적으로 클릭한건지 잘 확인이 되지 않습니다. 너무 빠르기 때문인데요. 코드를 약간 수정해야 할듯 합니다.
마우스 클릭 사이에 System.Threading.Thread.Sleep(500); 을 추가해줬습니다. 이 코드는 0.5초(500) 쉰다는 뜻입니다.
private void button1_Click(object sender, EventArgs e)
{
Cursor.Position = new Point(40, 31); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
System.Threading.Thread.Sleep(500);
Cursor.Position = new Point(40, 109); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
System.Threading.Thread.Sleep(500);
Cursor.Position = new Point(40, 195); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
System.Threading.Thread.Sleep(500);
Cursor.Position = new Point(40, 278); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
}
수정된 코드를 확인 해볼까요? 여러분들도 아래 동영상처럼 0.5초 간격으로 바탕화면의 아이콘을 클릭할겁니다.
추가로, 이 동작을 5번 반복하려면 어떻게 해야 할까요? for문으로 감싼 후 조건을 5로 주면 됩니다. C# 반복문에 대한 자세한 설명은 [ 여기 ]를 참고하세요.
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 5; i++)
{
Cursor.Position = new Point(40, 31); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
System.Threading.Thread.Sleep(500);
Cursor.Position = new Point(40, 109); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
System.Threading.Thread.Sleep(500);
Cursor.Position = new Point(40, 195); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
System.Threading.Thread.Sleep(500);
Cursor.Position = new Point(40, 278); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
}
}
5번 반복하고 매크로가 중지 되었습니다.
마지막으로 중지 버튼을 누르면 매크로의 동작이 남아 있더라도 즉시 중지되도록 만들어보겠습니다. 마우스의 제어권을 사용자가 아닌 매크로가 가지고 있으므로, 중지 버튼을 누를 시간이 필요합니다. 그래서, "System.Threading.Thread.Sleep(500);" 값을 "System.Threading.Thread.Sleep(1000);" 으로 변경 했습니다. 사용자가 중지 버튼을 눌렀는지 확인하기 위한 상태 저장용 변수를 하나 추가 해줍니다.
bool isStop = true;
시작 버튼을 누르면 싱행중이니 이 값은 false로 바뀌고, 중지 버튼을 누르면 이 값은 true로 변경됩니다. 전체 코드는 아래와 같습니다.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace MyPlayer
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
const uint LBUTTONDOWN = 0x0002; // 왼쪽 마우스 버튼 누름
const uint LBUTTONUP = 0x0004; // 왼쪽 마우스 버튼 땜
bool isStop = true;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
isStop = false;
new System.Threading.Thread(new System.Threading.ThreadStart(delegate
{
for (int i = 0; i < 5; i++)
{
Cursor.Position = new Point(40, 31); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
if (isStop) break;
System.Threading.Thread.Sleep(1000);
Cursor.Position = new Point(40, 109); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
if (isStop) break;
System.Threading.Thread.Sleep(1000);
Cursor.Position = new Point(40, 195); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
if (isStop) break;
System.Threading.Thread.Sleep(1000);
Cursor.Position = new Point(40, 278); // 내 PC 좌표
mouse_event(LBUTTONDOWN, 0, 0, 0, 0);
mouse_event(LBUTTONUP, 0, 0, 0, 0);
if (isStop) break;
System.Threading.Thread.Sleep(1000);
}
})).Start();
}
private void button2_Click(object sender, EventArgs e)
{
isStop = true;
}
}
}
실행중에 재빠르게 중지 버튼을 눌러보세요. 5회 반복하지 않고 매크로가 중지됩니다.
이렇게해서 간단하게 마우스 매크로를 만들어 봤습니다. 사실, 여러가지 많은 테스트를 해보고 싶지만~ 가급적이면 C# 언어 강좌를 보고 직접 학습하면서 살을 붙여 나가는게 좋습니다. 어느정도 기초 지식과 응용력이 있어야 더 좋은 매크로를 만들 수 있거든요. 단순히 마우스 클릭만으로 이루어진 간단한 업무의 경우 이정도만 알아도 좌표를 가져다가 클릭으로 처리할 수 있기도 합니다. 복잡한 업무의 경우에는 더 좋은 도구를 사용하거나 더 많은 개발 지식이 필요하겠지만요^^;
개발자에게 후원하기
추천, 구독, 홍보 꼭~ 부탁드립니다.
여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~
감사합니다~
- 이전글3부 - 누구나 쉽게 할 수 있는 C# 매크로 만들기. (이미지 서치, ImageSearch) 22.01.25
- 다음글타입스크립트란? (Typescript) 22.01.20
댓글목록
등록된 댓글이 없습니다.