윈도우 프로그래밍 ( MFC 프로그래밍 제어 메시지 (키보드,마우스 입출력)처리 및 예제 )
저번에는 MFC의 구조 및 간단한 입출력에 대해서 알아보았습니다.
이번에는 MFC 프로그래밍의 제어 메시지를 처리하는 방법에 대해서 알아보도록 하겠습니다.
.
.
.
키보드 입력
.
.
.
MFC 프로그래밍에서 키보드로 입력을 받기 위해서는 우선 WM_KEYDOWN 을 이용하여 메시지로 방향키를 받을 수 있습니다. 여기서 입력하게 되는 값들은 wParam에 가상 키의 값으로 저장이 되어있으며,
방향키의 가상키로는 아래와 같이 있습니다.
.
.
.
위에서 말하는 wParam 은 윈도가 어떻게 변했는지 알려주는 상수로
SIZE_MAXIMIZED : 윈도우 최대화
SIZE_MINIMIZED : 윈도우 최소화
SIZE_RESTORED : 윈도우 크기가 변경됨
등이 있습니다.
.
.
.
IParam은 변경된 윈도우 클라이언트의 크기를 나타내며
HIWORD : 변경된 윈도우 높이
LOWORD : 변경된 윈도우 너비
등이 있습니다.
.
.
.
타이머 메시지
.
.
.
타이머 메시지는 말그대로 컴퓨터에 시간 간격을 설정하여 WM_TIMER 메시지를 프로그램에 보내도록 하는 기능을 합니다.
.
.
타이머 메시지의 설정함수로는 SetTimer() 함수 가 있으며 그 구조는 아래와 같습니다.
UINT_PTR SetTimer(
HWND hwnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC IpTimerFunc
);
매개변수
.
hwnd : 윈도우 핸들
nIDEvent : 타이머 ID, 여러 개의 타이머를 구분하기 위한 정수
uElapse : 시간 간격 milisec(1000/1초)
IpTimerFunc : 시간 간격마다 수행할 함수(NULL이라고 쓰면 WndProc()가 타이머 메시지(WM_TIMER)를 처리합니다.)
.
.
처리방법
.
case WM_CREATE:
SetTimer(hwnd,1,80,NULL);
SetTimer(hwnd,2,100,NULL);
break;
case WM_TIMER:
switch (wParam) {
case 1 : // 0.08 초 간격으로 실행
case 2 : // 0.1 초 간격으로 실행
.
.
.
}
.
.
.
마우스 이벤트
.
.
.
키보드 이벤트와 비슷한 형식이며,
마우스 이벤트를 처리하기 위해서는
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_MOUSEMOVE
가 있습니다.
.
.
마우스를 이용하여 이벤트를 처리하게 되면 윈도우 클라이언트 창에서 좌표를 이용하여 처리하게 될 경우가 많이 있습니다. 그럴 때 마우스의 좌표를 구하기 위해서는
int x = LOWORD(IParam)
int y = HIWORD(IParam)
등이 있습니다.
.
.
.
래스터 연산
.
.
.
래스터 연산은 윈도우의 배경색과 그리는 색을 연산한 결과 색상으로 그림을 그려주는 연산을 수행합니다.
.
.
래스터 연산의 종류
.
.
R2_COPYPEN
R2_XORPEN
R2_NOT
R2_NOTCOPYPEN
R2_NOTXORPEN
등이 있습니다.
.
.
.
위에서 배운 개녕을 더 잘 이해하기 위해서 간단한 예제를 수행해보도록 하겠습니다.
.
.
.
간단하게 방향키를 활용하여 사각형 안에서만 원이 이동되도록 해보겠습니다.
#include <windows.h>
#include <TCHAR.H>
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
// UNICODE 사용시 wWinMain() 형태
// hPrevInstance 이전 인스턴스 항상 0값
// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
// nCmdShow 윈도우 출력 형태에 관련한 값
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW; //height, vertical redraw
WndClass.lpfnWndProc = WndProc; // Proc 설정
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 형변환
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass); // WndClass 등록
hwnd = CreateWindow(_T("Window Class Name"),
_T("Jung-story"),
WS_OVERLAPPEDWINDOW, // 윈도우 스타일
600, 400, // 창출력좌표 x, y
600, 400, // 창크기 x, y축
NULL, // 부모 윈도우
NULL, // 메뉴바 핸들
hInstance, // 인스턴스
NULL // 여분, NULL
);
ShowWindow(hwnd, nCmdShow); // 윈도우 출력, WM_PAINT 출력내용 가져옴
UpdateWindow(hwnd); // WM_PAINT 출력내용 발생해서 출력하도록
// hwnd 핸들을 통해 보여주고 갱신
//ShowWindow(hwnd, SW_SHOW); // 위와 같음
//UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) // 메시지 큐의 메시지를 가져옴
{
TranslateMessage(&msg); // 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
DispatchMessage(&msg); // WndProc() 함수 호출과 WndProc()으로 메세지 전달
} // 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
return (int)msg.wParam; // wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
// WinDef.h 에서 정의
// wPram > unsigned ptr, lParam > long ptr
{
HDC hdc;
PAINTSTRUCT ps;
static int x, y;
static RECT rectView;
HPEN hPen, oldPen;
switch (iMsg)
{
case WM_CREATE:
x = 20; y = 20;
return 0;
case WM_KEYDOWN:
if (wParam == VK_RIGHT) { // 오른쪽 직접입력
x += 40;
if (x + 20 > rectView.right) {
x -= 40;
}
}
else if (wParam == VK_LEFT) {
x -= 40;
if (x - 20 < rectView.left) {
x += 40;
}
}
else if (wParam == VK_UP) {
y -= 40;
if (y - 20 < rectView.top) {
y += 40;
}
}
else if (wParam == VK_DOWN) {
y += 40;
if (y + 20 > rectView.bottom) {
y -= 40;
}
}
else if (wParam == VK_HOME) { // 홈키를 입력하면 원위치로 이동
x = 20;
y = 20;
}
InvalidateRgn(hwnd, NULL, TRUE);
break;
case WM_PAINT:
GetClientRect(hwnd, &rectView); // 위에서 설정한 윈도우크기만큼 만들어짐
hdc = BeginPaint(hwnd, &ps);
hPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
oldPen = (HPEN)SelectObject(hdc, hPen); // 새로운 펜 사용 선언
Rectangle(hdc, 0, 0, 40 * (int)(rectView.right / 40), 40 * (int)(rectView.bottom / 40));
SelectObject(hdc, oldPen); // 이전의 펜으로 돌아감
DeleteObject(hPen);
Ellipse(hdc, x - 20, y - 20, x + 20, y + 20);
EndPaint(hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
.
.
이 코드에서 포인트라면 rectView를 이용하여 원이 사각형밖으로 이동하지 못하도록 값을 계산해 주었습니다.
.
.
.
.
.
.
간단한 방향키를 이용하여 에벌레를 움직이기
#include <windows.h>
#include <TCHAR.H>
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
// UNICODE 사용시 wWinMain() 형태
// hPrevInstance 이전 인스턴스 항상 0값
// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
// nCmdShow 윈도우 출력 형태에 관련한 값
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW; //height, vertical redraw
WndClass.lpfnWndProc = WndProc; // Proc 설정
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 형변환
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass); // WndClass 등록
hwnd = CreateWindow(_T("Window Class Name"),
_T("Jung-story"), // 타이틀바,
WS_OVERLAPPEDWINDOW, // 윈도우 스타일
600, 400, // 창출력좌표 x, y
600, 400, // 창크기 x, y축
NULL, // 부모 윈도우
NULL, // 메뉴바 핸들
hInstance, // 인스턴스
NULL // 여분, NULL
);
ShowWindow(hwnd, nCmdShow); // 윈도우 출력, WM_PAINT 출력내용 가져옴
UpdateWindow(hwnd); // WM_PAINT 출력내용 발생해서 출력하도록
// hwnd 핸들을 통해 보여주고 갱신
//ShowWindow(hwnd, SW_SHOW); // 위와 같음
//UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) // 메시지 큐의 메시지를 가져옴
{
TranslateMessage(&msg); // 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
DispatchMessage(&msg); // WndProc() 함수 호출과 WndProc()으로 메세지 전달
} // 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
return (int)msg.wParam; // wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
// WinDef.h 에서 정의
// wPram > unsigned ptr, lParam > long ptr
{
HDC hdc;
PAINTSTRUCT ps;
static int x[2], y[2],xStep,yStep,flag;
static RECT rectView;
HPEN hPen, oldPen;
int tmpx, tmpy;
switch (iMsg)
{
case WM_CREATE:
x[0] = 20; y[0] = 20;
x[1] = 60; y[1] = 20;
xStep = 40; yStep = 0;
return 0;
case WM_KEYDOWN:
switch (wParam) {
case VK_RETURN:
flag = 1-flag;
if (flag) SetTimer(hwnd, 1, 100, NULL); // 움직임 시작
else KillTimer(hwnd, 1); // 움직임 중지
break;
case VK_RIGHT: //오른쪽 이동
xStep = 40;
yStep = 0;
break;
case VK_LEFT: // 왼쪽 이동
xStep = -40;
yStep = 0;
break;
case VK_UP: // 위쪽 이동
xStep = 0;
yStep = -40;
break;
case VK_DOWN: // 아래쪽 이동
xStep = 0;
yStep = 40;
break;
InvalidateRgn(hwnd, NULL, TRUE);
break;
}
case WM_PAINT:
GetClientRect(hwnd, &rectView); // 위에서 설정한 윈도우크기만큼 만들어짐
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, CreatePen(PS_SOLID, 1, RGB(255, 255, 255)));
Rectangle(hdc, 0, 0, 40 * (int)(rectView.right / 40), 40 * (int)(rectView.bottom / 40));
SelectObject(hdc, CreatePen(PS_SOLID,2,RGB(255,0,0))); // 빨간색 원 그리기 0,0에
Ellipse(hdc, x[0] - 20, y[0] - 20, x[0] + 20, y[0] + 20);
SelectObject(hdc, CreatePen(PS_SOLID, 2, RGB(0, 0, 255))); // 파란색 원 그리기 0,0에
Ellipse(hdc, x[1] - 20, y[1] - 20, x[1] + 20, y[1] + 20);
EndPaint(hwnd, &ps);
break;
case WM_TIMER:
GetClientRect(hwnd, &rectView);
tmpx = x[0];
tmpy = y[0];
x[0] += xStep; y[0] += yStep;
if (x[0] - 20 < rectView.left || x[0] + 20 > rectView.right) {
x[0] = tmpx;
y[0] = tmpy;
}
else x[1] = tmpx;
if (y[0] - 20 < rectView.top || y[0] + 20 > rectView.bottom) {
x[0] = tmpx;
y[0] = tmpy;
}
else y[1] = tmpy;
InvalidateRgn(hwnd, NULL, true);
break;
case WM_DESTROY:
KillTimer(hwnd, 1);
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
.
.
.
.
.
.
이 코드에서 포인트는 flag를 설정하여 Enter키를 입력하였을 때 값이 스위칭돼서 움직임과 정지를 계산해 주었으며,
WM_TIMER 부분에서 각원의 지름을 이용하여 계산해주었습니다.
.
.
.
마우스 클릭 시 이미지 변화
#include <windows.h>
#include <TCHAR.H>
#include <math.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
// UNICODE 사용시 wWinMain() 형태
// hPrevInstance 이전 인스턴스 항상 0값
// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
// nCmdShow 윈도우 출력 형태에 관련한 값
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW; //height, vertical redraw
WndClass.lpfnWndProc = WndProc; // Proc 설정
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 형변환
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass); // WndClass 등록
hwnd = CreateWindow(_T("Window Class Name"),
_T("Jung-story"), //
WS_OVERLAPPEDWINDOW, // 윈도우 스타일
600, 400, // 창출력좌표 x, y
600, 400, // 창크기 x, y축
NULL, // 부모 윈도우
NULL, // 메뉴바 핸들
hInstance, // 인스턴스
NULL // 여분, NULL
);
ShowWindow(hwnd, nCmdShow); // 윈도우 출력, WM_PAINT 출력내용 가져옴
UpdateWindow(hwnd); // WM_PAINT 출력내용 발생해서 출력하도록
// hwnd 핸들을 통해 보여주고 갱신
//ShowWindow(hwnd, SW_SHOW); // 위와 같음
//UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) // 메시지 큐의 메시지를 가져옴
{
TranslateMessage(&msg); // 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
DispatchMessage(&msg); // WndProc() 함수 호출과 WndProc()으로 메세지 전달
} // 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
return (int)msg.wParam; // wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값
}
float LengthPts(int x1, int y1, int x2, int y2) {
return (sqrt((float)((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))));
}
int BSIZE = 20;
BOOL InCircle(int x, int y, int mx, int my) {
if (LengthPts(x, y, mx, my) < BSIZE) return TRUE;
else return FALSE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
// WinDef.h 에서 정의
// wPram > unsigned ptr, lParam > long ptr
{
HDC hdc;
PAINTSTRUCT ps;
static int x, y;
static BOOL Selection;
HBRUSH hBrush, oldBrush;
HPEN hPen, oldPen;
int mx, my;
switch (iMsg)
{
case WM_CREATE:
x = 20; y = 20;
Selection = FALSE;
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
if(Selection) { // 원이 선택 되었을시
hBrush = CreateSolidBrush(RGB(0,255, 0)); // 면색
oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); // 선색
oldPen = (HPEN)SelectObject(hdc, hPen);
}
Ellipse(hdc, x - 20, y - 20, x + 20, y + 20);
EndPaint(hwnd, &ps);
break;
case WM_LBUTTONDOWN: // 왼쪽 마우스 버튼 클릭시
mx = LOWORD(lParam); // 마우스 x좌표
my = HIWORD(lParam); // 마우스 y좌표
if (InCircle(x, y, mx, my)) {
Selection = TRUE; // 마우스 클릭시 TRUE로 토글
}
InvalidateRgn(hwnd, NULL, TRUE);
break;
case WM_LBUTTONUP: // 왼쪽 마우스 버튼은 떼면
Selection = FALSE;
InvalidateRgn(hwnd, NULL, TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
.
.
.
.
.
.
이 코드에서 포인트는 math.h를 이용하여 InCircle함수에서 원의 내부의 크기를 계산해주는 것과
Selection을 두어 마우스의 클릭을 조절하는 것입니다.
.
.
.
위의 예제에 이어서 래스터 연산 및 Drag 예제
#include <windows.h>
#include <TCHAR.H>
#include <math.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
// UNICODE 사용시 wWinMain() 형태
// hPrevInstance 이전 인스턴스 항상 0값
// lpszCmdLine > 외부에서 (내부로) 입력받는 변수
// nCmdShow 윈도우 출력 형태에 관련한 값
{
HWND hwnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW | CS_VREDRAW; //height, vertical redraw
WndClass.lpfnWndProc = WndProc; // Proc 설정
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 형변환
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = _T("Window Class Name");
RegisterClass(&WndClass); // WndClass 등록
hwnd = CreateWindow(_T("Window Class Name"),
_T("Jung-story"), //
WS_OVERLAPPEDWINDOW, // 윈도우 스타일
600, 400, // 창출력좌표 x, y
600, 400, // 창크기 x, y축
NULL, // 부모 윈도우
NULL, // 메뉴바 핸들
hInstance, // 인스턴스
NULL // 여분, NULL
);
ShowWindow(hwnd, nCmdShow); // 윈도우 출력, WM_PAINT 출력내용 가져옴
UpdateWindow(hwnd); // WM_PAINT 출력내용 발생해서 출력하도록
// hwnd 핸들을 통해 보여주고 갱신
//ShowWindow(hwnd, SW_SHOW); // 위와 같음
//UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) // 메시지 큐의 메시지를 가져옴
{
TranslateMessage(&msg); // 키입력에 반응하는 메시지 변환, WM_KEYDOWN (키가 눌릴때) WM_CHAR 메시지 발생
DispatchMessage(&msg); // WndProc() 함수 호출과 WndProc()으로 메세지 전달
} // 종료는 WM_QUIT 발생할때 FALSE 리턴하면서 종료
return (int)msg.wParam; // wParam, lParam 윈도우 크기가 어떻게 변했는지, 변경된 클라이언트, 키보드, 마우스 값
}
float LengthPts(int x1, int y1, int x2, int y2) {
return (sqrt((float)((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))));
}
int BSIZE = 20;
BOOL InCircle(int x, int y, int mx, int my) {
if (LengthPts(x, y, mx, my) < BSIZE) return TRUE;
else return FALSE;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
// WinDef.h 에서 정의
// wPram > unsigned ptr, lParam > long ptr
{
HDC hdc;
PAINTSTRUCT ps;
static int x, y;
static BOOL Selection,Drag;
HBRUSH hBrush, oldBrush;
HPEN hPen, oldPen;
int mx, my;
static int oldX, oldY;
int endX=0, endY=0;
switch (iMsg)
{
case WM_CREATE:
x = 20; y = 20;
oldX = 20; oldY = 20;
Selection = FALSE;
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
if (Selection) { // 원이 선택 되었을시
hBrush = CreateSolidBrush(RGB(0, 255, 0)); // 면색
oldBrush = (HBRUSH)SelectObject(hdc, hBrush);
hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); // 선색
oldPen = (HPEN)SelectObject(hdc, hPen);
}
Ellipse(hdc, x - 20, y - 20, x + 20, y + 20);
EndPaint(hwnd, &ps);
break;
case WM_LBUTTONDOWN: // 왼쪽 마우스 버튼 클릭시
mx = LOWORD(lParam); // 마우스 x좌표
my = HIWORD(lParam); // 마우스 y좌표
if (InCircle(x, y, mx, my)) {
Selection = TRUE; // 마우스 클릭시 TRUE로 토글
Drag = TRUE;
}
InvalidateRgn(hwnd, NULL, TRUE);
break;
case WM_LBUTTONUP: // 왼쪽 마우스 버튼은 떼면
Selection = FALSE;
Drag = FALSE;
oldX = x; // static 으로 남아있기 때문에 초기화를 해야함
oldY = y;
InvalidateRgn(hwnd, NULL, TRUE);
break;
case WM_MOUSEMOVE:
hdc = GetDC(hwnd);
if (Drag && Selection) {
SetROP2(hdc, R2_XORPEN); // 펜의 XOR 연산 예) 흰바탕일때 검정색
SelectObject(hdc, (HPEN)GetStockObject(WHITE_PEN));
endX = LOWORD(lParam);
endY = HIWORD(lParam);
MoveToEx(hdc, x, y, NULL); // 지우기 : 흰 바탕 XOR 검은 펜 = 흰 선
LineTo(hdc, oldX, oldY);
MoveToEx(hdc, x, y, NULL); // 그리기 : 흰 바탕 XOR 흰 펜 = 검은 선
LineTo(hdc, endX, endY);
oldX = endX; oldY = endY; // 현 지점을 이전 지점으로 설정
}
ReleaseDC(hwnd, hdc);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
.
.
.
.
.
.
이 코드에서 포인트는 WM_MOUSEMOVE를 이용하여 직선을 그려주고 지워주는 작업을 하는 부분이라고 생각합니다.
.
.
.
이렇게 오늘은 MFC 프로그래밍의 제어 메시지 처리의 개념과 예제에 대해서 알아보았습니다.