본문 바로가기

API

그리기 모드(코드)

반전모드를 사용하는 예제를 만들어 보자. 마우스가 이동하는 대로 선을 그리되 선이 그려지는 과정을 보여준다.

즉 마우스 버튼을 누른 위치에서부터 시작해서 마우스 버튼을 놓는 자리까지 선을 긋되 버튼을 누른 채로 마우스를 움직이면 중간에 그려질 선의 모양을 보여주는 것이다.


코드는 다음과 같다.


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
	HDC hdc;
	static bool bNowDraw = false;
	static int sx, sy, oldx, oldy;

	switch (iMessage) {
	case WM_LBUTTONDOWN:
		sx = LOWORD(lParam);
		sy = HIWORD(lParam);
		oldx = sx;
		oldy = sy;
		bNowDraw = true;
		return 0;
	case WM_MOUSEMOVE:
		if (bNowDraw) {
			hdc = GetDC(hWnd);
			SetROP2(hdc, R2_NOT);
			MoveToEx(hdc, sx, sy, NULL);
			LineTo(hdc, oldx, oldy);
			oldx = LOWORD(lParam);
			oldy = HIWORD(lParam);
			MoveToEx(hdc, sx, sy, NULL);
			LineTo(hdc, oldx, oldy);
			ReleaseDC(hWnd, hdc);
		}
		return 0;
	case WM_LBUTTONUP:
		bNowDraw = false;
		hdc = GetDC(hWnd);
		MoveToEx(hdc, sx, sy, NULL);
		LineTo(hdc, oldx, oldy);
		ReleaseDC(hWnd, hdc);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}


이 예제를 실행해 놓고 마우스로 선을 그으면 복수 개의 선이 그려지는데 마우스 이동중에도 이미 그려진 선이 지워지지 않는다.



WndProc의 선두부터 분석해 보도록 하자.


이 프로그램에서 사용하는 변수들은 다음과 같다.


변수 

설명 

sx,sy 

처음 마우스를 누른 위치를 가진다. 

oldx,oldy 

지워져야 할 선의 끝 좌표를 가진다. 

bNowDraw 

현재 선을 그리고 있는 중인가에 대한 정보를 가진다. 


이 변수들은 계속 값을 보관해야 하므로 static 기억 부류로 선언되었다. 마우스 왼쪽 버튼을 누르면 bNowDraw를 TRUE로 만들어 선 그리기를 시작하며 버튼이 눌러진 좌표를 시작점, 끝점에 모두 대입한다.

즉 처음 선을 그리기 시작할 때는 시작점과 끝점이 같은 상태에서 시작하며 이 상태에서 마우스를 움직이면 끝점이 움직이면서 선이 마우스를 따라 늘어나게 된다.


선이 늘어나는 처리는 WM_MOUSEMOVE에서 처리한다. SetROP2 함수를 호출하여 그리기 모드를 R2_NOT으로 변경하고 (sx,sy)에서부터 (oldx,oldy)까지 그려진 선을 먼저 지운다. 이 좌표에 선을 그을 때 왜 선이 지워지는가 하면 이미 그려진 그림위에 반 모드로 똑같은 그림을 다시 출력하면 지워지는 반전 연산의 특수성 때문이다. 검정색이 있는 위치를 반전시키면 이 점은 흰색이 되어 버리는 것이다.

이전 선을 지운 후 현 마우스 좌표를 구해 oldx,oldy에 대입하고 다시 새로운 선을 그린다. 

oldx,oldy에 현재의 끝점을 대입해 놓았으므로 다음 마우스 이동시에 이 선을 지울 수 있다.


마우스 버튼을 놓으면 확정된 선을 다시 그리게 된다. 선을 다시 그리지 않으면 아래와 같은 상황이 발생한다.


선의 중간이 지워지게 되므로, 꼭 다시 한번 그려야한다.


WM_MOUSEMOVE 메세지의 SetROP2 함수 호출문을 삭제해 보면 왜 그리기 모드를 변경해야 하며, 그리기 모드가 왜 필요한가를 알 수 있을 것이다.



이 코드에서 주의하여 살펴볼 것은 새 위치에 선이 그려진 후 oldx, oldy가 현재 그려진 선의 끝 좌표를 대입 받음으로써 다음 번 마우스가 움직일 때 이 선을 지울 수 있도록 한다는 점이다.

'API' 카테고리의 다른 글

컨트롤 - 체크 박스  (0) 2018.02.04
컨트롤 - 푸시 버튼  (0) 2018.02.04
그리기 모드  (0) 2018.01.24
Old의 의미  (0) 2018.01.22
브러쉬 만들기  (0) 2018.01.22