Home C로 매크로를 만들어보자
포스트
취소

C로 매크로를 만들어보자

안녕하세요.

오늘은 Windows에 C 개발환경 설치와 Windows.h 라이브러리를 사용하여 마우스 매크로를 만들어 보려고 합니다.

C 개발환경 구성하기

제일 좋은 방법은 역시 Visual Studio를 이용해서 개발하는 것 입니다.

Visual Studio

그렇지만 우리는 단순히 C 개발만 할 것이고, Visual Studio를 쓰기엔 지나치게 무겁고 느립니다.

그래서 오늘은 MinGW를 이용해서 개발환경을 구성해 볼 예정입니다.

MinGW 설치

MinGW는 마이크로소프트 윈도우로 포팅한 GNU 소프트웨어 도구 모음입니다.

Source Forge에서 설치파일을 다운로드 받을 수 있습니다.

sourceforge

다운로드 받아서 설치 하면 아래와 같이 패키지 설치 매니저가 뜹니다.

mingw install manager

Basic Setup항목들을 모두 선택한 후에 상단 Installation > Apply Changes를 누르시면 GCC 컴파일러가 설치 되게 됩니다.

엄밀히 말해, 모든 패키지가 필요하지는 않습니다. Description을 읽어보시고 필요한 항목만 설치 하셔도 무방합니다.

Visual Studio Code 에 C 개발환경 세팅하기

우선 Visual Studio Code에서 C 파일을 하나 생성한 후 파일을 열어봅시다.

VSCode

아래처럼 기본적인 하이라이팅은 지원되지만, 빌드도 안되고 인덱싱도 안되어 있어서 개발 환경이라고 하기엔 많이 부족합니다.

아래 Extention 3가지만 추가로 설치 해 주면 모든 설정이 끝납니다.

Extention

이제 파일을 다시 열어보면 아래와 같이 우측 상단에 뭔가 생긴것을 볼 수 있습니다.

After Extention

그 중 실행 버튼을 눌러보시면 아래와 같이 자동으로 빌드가 됩니다.

Visual Studio 와 동일하게 F5 키를 눌러도 동작합니다!

Compile

소스코드가 있는 디렉터리에 가 보시면 ~~~.exe라는 파일이 생성 되어있습니다. ~~~에는 파일명이 쓰이게 됩니다.

실행해 보시면 아래와 같이 우리가 작성한 코드 그대로 실행 되는것을 볼 수 있습니다.

play

이제 개발환경 설정은 끝입니다! 참 쉽죠? 예전 같았으면 PATH 설정이라던지, 여러가지 번거로운 작업들을 해주었어야 했을테지만, 요즘엔 Visual Studio Code에서 알아서 설정 해 주어서 참 쉽게 설정할 수 있었던것 같습니다.

windows.h 사용해보기

windows.h는 윈도우 개발자들이 필요한 모든 매크로들, 다양한 함수들과 서브시스템에서 사용되는 모든 데이터 타입들 그리고 윈도우 API의 함수들을 위한 정의를 포함하는 윈도우의 C 및 C++ 헤더 파일입니다.

Wikipedia를 보면 알겠지만 정말 엄청나게 많은 Windows용 기능들을 가지고 있는 헤더 파일인데요.

오늘 만들어볼 매크로는 여기에 있는 함수 몇가지를 이용해 만들어볼 예정입니다.

GetPrivateProfileString

GetPrivateProfileString함수는 ini 파일을 읽기 위해 사용할 수 있는 함수입니다.

아래와 같은 구조의 ini 파일이 있을 때

[Title1]
Name=test.cpp 
Path=C:\temp\test.cpp
Version=2.1.0.1

아래와 같이 사용할 수 있습니다.

1
2
3
4
5
char  ret[256];
memset(ret, 0, sizeof(ret));
GetPrivateProfileString( "Title1", "Name", "-", ret, sizeof(ret), "C:\\temp\\test.ini" );
// ret에는 'test.cpp'가 담기게 됨
// Name이 없을 경우 '-'가 담기게 됨

GetKeyState

GetKeyState 함수는 키가 눌려있는지를 체크할 수 있는 함수입니다.

키 코드는 Microsoft 공식 문서에서 확인 해 주세요

아래와 같이 사용할 수 있습니다.

1
2
3
4
if (GetKeyState(VK_F10) < 0) { // F10키를 누르면
    printf("프로그램을 종료합니다.\n");
    return 0; // 프로그램 종료
}

GetCursorPos

GetCursorPos 함수는 현재 커서의 위치를 가져오는 함수입니다.

아래와 같이 사용할 수 있습니다.

1
2
3
4
5
6
POINT pt;             // 마우스 포인터

// ...

GetCursorPos(&pt); // 마우스 좌표값들 받아옴
printf("%d, %d\n", pt.x, pt.y);

SetCursorPos, mouse_event

SetCursorPos함수는 마우스 커서를 움직이는 함수입니다.

mouse_event함수는 마우스 이벤트를 발생 시키는 함수이구요.

이 둘을 조합해서 아래와 같이 자동 클릭 매크로를 만들 수 있습니다.

1
2
3
4
SetCursorPos(x[i],y[i]); // 지정한 곳의 좌표로 마우스 이동
mouse_event(MOUSEEVENTF_LEFTDOWN, x[i], y[i], 0, 0); // 좌표에 맞게 왼쪽버튼 누르기
Sleep(1); // 1ms 쉬기
mouse_event(MOUSEEVENTF_LEFTUP, x[i], y[i], 0, 0);   // 좌표에 맞게 왼쪽버튼 떼기

매크로 전체 코드

제가 만든 전체 코드는 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <windows.h>
#include <stdio.h>
#include <sys/time.h>

void home();
int main(void) {
   char *cBuf = NULL;
   int delay = 0;
   int milliseconds = 0;
   struct timeval stop, start;

   cBuf = (char *)malloc(sizeof(char) * 256);
   memset(cBuf, 0x00, sizeof(cBuf));
   GetPrivateProfileString("Section_1", "Delay", "-", cBuf, 256, "./setting.ini");
   delay = atoi(cBuf);
   memset(cBuf, 0x00, sizeof(cBuf));
   GetPrivateProfileString("Section_1", "Milliseconds", "-", cBuf, 256, "./setting.ini");
   milliseconds = atoi(cBuf);
   memset(cBuf, 0x00, sizeof(cBuf));

   POINT pt;             // 마우스 포인터
   int x[50000];         // 매크로 x좌표
   int y[50000];         // 매크로 y좌표
   int check_mouse = 2;  // 마우스 관련 변수
   int check_mouse2 = 2; // 마우스 관련 변수
   int i = 0;            // 매크로 녹화시 이용
   // int n = 0; // 메크로 진행시 이용
   system("mode con: cols=30 lines=13"); // 화면 고정
   // printf("%d\n", milliseconds);
   home();                               // home이라는 이름을 가진 함수
   for (i = 0; i <= 50000; i++)          //초기화
   {
      x[i] = 0;
      y[i] = 0; // 초기화 과정 다 0으로 초기화해줌
   }
   i = 0;

   while (1) //무한반복 break문이나 return문으로 나가야됨.
   {
      if (GetKeyState(VK_F10) < 0) // F10키 누르면
      {
         printf("프로그램을 종료합니다.\n");
         return 0; // 프로그램 종료
      }

      else if (GetKeyState(0x5A) < 0) // z 키를 누를 경우 해당 좌표 기록
      {
         GetCursorPos(&pt); // 마우스 좌표값들 받아옴
         x[i] = pt.x;       // x좌표값 저장
         y[i] = pt.y;       // y좌표값 저장
         i++;               // i는 프레임을 의미
         printf("%d, %d\n", pt.x, pt.y);
         Sleep(1000);
      }

      else if (GetKeyState(VK_F8) < 0) // 매크로 재생
      {
         i = 0; // 프레임 처음으로 돌아가서 재생하기 위한 n
         printf("macro started. \n");
         gettimeofday(&start, NULL);
         while (1)
         {

            if (GetKeyState(VK_F7) < 0) // 0.01초마다 조건문 확인
            {
               printf("macro stoped.\n");
               break;
            }
            if (GetKeyState(VK_F10) < 0)
            {
               printf("program exit.\n");
               return 0;
            }
      
            gettimeofday(&stop, NULL);
            printf("took %lu us\n", (stop.tv_sec - start.tv_sec) * 1000000 + stop.tv_usec - start.tv_usec);
            SetCursorPos(x[i],y[i]); // 지정한 곳의 좌표로 마우스 이동
            mouse_event(MOUSEEVENTF_LEFTDOWN, x[i], y[i], 0, 0); // 좌표에 맞게 왼쪽버튼 누르기
            Sleep(1); // 1ms 쉬기
            mouse_event(MOUSEEVENTF_LEFTUP, x[i], y[i], 0, 0);   // 좌표에 맞게 왼쪽버튼 떼기

            i++;
            if (x[i] == 0 || y[i] == 0)
            {
               printf("program end.\n");
               break;
            }
            
            gettimeofday(&start, NULL);
            Sleep(delay-1); // 100ms마다 한번씩 쉬고


         }
      }
      Sleep(10); // Sleep(1000)은 1초임. 즉, 0.01초를 기다린후 위로 올라가 반복문을 다시 실행
   }
   return 0; //메인문을 나감.
}
void home()
{
   //홈화면
   puts("    ----------------------"); // puts함수는 자동으로 줄바꿈 처리를 한다.
   puts("    |                    |");
   puts("    |     Mouse Macro    |");
   puts("    |                    |");
   puts("    | z : location save  |");
   puts("    |  F7 : macro stop   |");
   puts("    |  F8 : macro start  |");
   puts("    |     F10 : exit     |");
   puts("    |                    |");
   puts("    ----------------------");
}

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

코드 없이 웹 구축하기

deno로 웹 사이트 만들기 1