마우스와 키보드를 조작

출처 : http://blog.empas.com/poucotm/4253466

가끔 자동적으로 마우스와 키보드를 조작(?)하고 싶을 때가 있을 것이다. 마우스 버튼을 일정시간 계속 누르고 싶다거나, 키보드의 특정 값을 계속 입력하고 싶다거나 …. 등등. 암튼 이런걸 위해서 Windows API 는 ::SendInput 이란 함수를 제공한다. MSDN의 내용을 기초로 몇가지 예제만 살펴보자.

일단 원형을 보자.
UINT SendInput(
UINT nInputs,
LPINPUT pInputs,
int cbSize
);
nInputs 는 pInputs 안의 구조체 수를 정하여 넣을 수 있다.
pInputs 는 INPUT 구조체 배열의 pointer 이다. 각 구조체는 키보드 혹은 마우스 입력 스트림으로 삽입될 Event 이다.
cbSize 는 INPUT 구조체의 Bytes를 Count 한 값이다.
INPUT Structure는 다음과 같다.
typedef struct tagINPUT {
DWORD type;
union {MOUSEINPUT mi;
KEYBOARDINPUT ki;
HARDWAREINPUT hi;
};
}INPUT, *PINPUT;
와 Union 이다.~~ ^^;
type은 input event의 type을 결정하며 다음 셋 중 하나이다.
INPUT_MOUSE
마우스 이벤트로 mi 구조체를 사용한다.
INPUT_KEYBOARD
키보드 이벤트로 ki 구조체를 사용한다.
Windows 2000/XP: INPUT_KEYBOARD 는 키보드가 아닌 다른 입력 장치, 음성 입력 등, 을 지원한다.
INPUT_HARDWARE
Windows 95/98/Me: 키보드나 마우스 이외 입력 장치를 위한 이벤트로 hi 구조체를 사용한다.

각 구조체는 다음과 같다.

typedef struct tagMOUSEINPUT {
LONG dx;
LONG dy;
DWORD mouseData;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} MOUSEINPUT, *PMOUSEINPUT;
typedef struct tagKEYBDINPUT {
WORD wVk;
WORD wScan;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;
typedef struct tagHARDWAREINPUT {
DWORD uMsg;
WORD wParamL;
WORD wParamH;
} HARDWAREINPUT, *PHARDWAREINPUT;
이외 자세한 사항은 MSDN을 참고하자. ㅡㅡ;
첫번째 예제는 CAPS 키를 Toggle 시키는 것이다. (from www.codeproject.com)
//
#include <WinAble.h> // Required for the ::SendInput function
//…
// Toggle Caps Lock key:
INPUT input[2];
::ZeroMemory(input, sizeof(input));
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki.wVk  = input[1].ki.wVk = VK_CAPITAL;
input[1].ki.dwFlags = KEYEVENTF_KEYUP;  // THIS IS IMPORTANT
::SendInput(2, input, sizeof(INPUT));
//
2 개의 입력을 사용하였고, keyboard의 pressed 와 released 상태를 다 쓸수 있기 때문에 첫번째는 pressed 로 두번째는 released 로 사용하였다. 만약 pressed 하나를 사용하게 되면 Toggle 이 불가능하고 한번 pressed 된 효과만을 얻을 것이다.
두번째 예제는 마우스를 컨트롤 하는 것이다.
 // Get Screen Resolution
DEVMODE mode;
::EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS, &mode);
 INPUT in;
ZeroMemory(&in, sizeof(in));
in.type = INPUT_MOUSE;
 in.mi.dx = 800 * (65535 / mode.dmPelsWidth);
in.mi.dy = 700 * (65535 / mode.dmPelsHeight)

in.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;
::SendInput(1, &in, sizeof(in));

DEVMODE는 스크린 해상도를 얻기 위함이다. dwFlags 를 이용하여 이동, 왼쪽 버튼 Up, Down 모두 할 수 있다. 주의 할 것은 mi 구조체에서 dx, dy 멤버이다. 해상도와 상관없이 0 ~ 65535 까지가 범위이다. 그렇기 때문에 해상도에 따라서 조절해주어야한다.

Author: yyjksw