컴퓨터/Win32-API
지난 글에서 MoveToEx와 LineTo 2개의 함수를 이용해서 선을 그려봤습니다.
본문에서는 이 두 함수와 마우스 동작에 따른 처리를 하면서 마우스 동작에 따른 처리방법을 알아보고, 다양한 형태로 선을 그려보도록 합시다.
참조 - 이전 글
마우스의 동작에 따라 윈도에서는 다양한 알 림메 세지가 발생하게 됩니다. 자세한 내용은 MSDN의 마우스 내용을 살펴보시면 좋을 것 같습니다. 본문에서는 대표적으로 사용할 몇 가지 내용에 알림 메시지에 대하여 알아보겠습니다.
우선 콜백함수 안에 마우스 동작에 따른 메세지 처리하기 위한 소스코드를 작성합시다.
//마우스 동작에 따른 처리
//움직일 때
case WM_MOUSEMOVE:
break;
//좌클릭 눌렀을 때
case WM_LBUTTONDOWN:
break;
//좌클릭 해제할 때
case WM_LBUTTONUP:
break;
이제 해당 메시지에서 알맞게 선을 그리는 작업을 처리한다면 다양한 방법으로 선을 그려볼 수 있습니다.
몇 가지 예제를 작성해보며 실습해보도록 합시다.
좌클릭을 하면 클릭한 위치에 가로 100픽셀의 선을 그려보도록 합시다.
case WM_LBUTTONDOWN:
//예제 1을 위한 소스코드
//WM_PAINT가 아닌 곳에서 DC를 불러오는 방법
hdc = GetDC(hWnd);
MoveToEx(hdc, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),NULL);
LineTo(hdc, (GET_X_LPARAM(lParam)+100), GET_Y_LPARAM(lParam));
ReleaseDC(hWnd, hdc);
break;
간단하게 WM_LBUTTONDOWN 알림 메시지 발생 시 DC핸들을 얻어와 처리할 수 있습니다. 하지만 무효화 영역이 발생하여 WM_PAINT 알 림메 세지가 발생하면 그림을 그렸던 데이터는 사라지게 됩니다.
이런 문제는 다음 글에서 다시 극복해 보도록 합시다. 본문에서는 마우스 동작에 따른 그리기 처리를 하는 응용을 이해하는데 중점을 두었으면 좋겠습니다.
GET_X_LPARAM, GET_Y_LPARAM은 windowsx.h에 포함되어 있는 안전하게 마우스 좌표를 얻어오는 함수입니다.
이제 마우스 좌클릭을 하고 클릭을 때는 위치에 두 좌표를 얻어와서 직선을 그려보도록 합시다.
두 좌표를 기억하기 위해서 전역 변수를 통해 좌표를 기억하도록 하겠습니다.
//전역변수
POINT start_pos;
POINT end_pos;
POINT는 구조체의 형태로 x, y좌표를 담을 수 있습니다.
이제 알림 메시지에서 처리를 해보도록 합시다.
case WM_LBUTTONDOWN:
//예제 2를 위한 소스코드
start_pos.x = GET_X_LPARAM(lParam);
start_pos.y = GET_Y_LPARAM(lParam);
break;
//좌클릭 해제할 때
case WM_LBUTTONUP:
//예제 2를 위한 소스코드
end_pos.x = GET_X_LPARAM(lParam);
end_pos.y = GET_Y_LPARAM(lParam);
hdc = GetDC(hWnd);
MoveToEx(hdc, start_pos.x, start_pos.y, NULL);
LineTo(hdc, end_pos.x, end_pos.y);
ReleaseDC(hWnd, hdc);
break;
이제 드래그의 처럼 이용해서 직선을 그릴 수 있게 됐습니다.
예제 2의 경우에는 드래그를 하는 동안 그리기 과정을 볼 수 없습니다. 마우스가 움직이는 동작의 알 림메 세지에 약간의 소스코드를 추가하면 그리기 과정을 눈으로 볼 수 있습니다.
우선, 마우스 클릭을 한 시점부터 그리기를 해야 되니 클릭을 한 시점을 알 수 있도록 전역 변수를 하나 설정합니다.
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
POINT start_pos,end_pos;
//그리기를 상태를 파악하기 위한변수
int status;
이후 status변수를 가지고 제어하도록 하면 됩니다.
//마우스 동작에 따른 처리
//움직일 때
case WM_MOUSEMOVE:
//예제 3을 위한 소스코드
if (status == 1)
{
end_pos.x = GET_X_LPARAM(lParam);
end_pos.y = GET_Y_LPARAM(lParam);
hdc = GetDC(hWnd);
MoveToEx(hdc, start_pos.x, start_pos.y, NULL);
LineTo(hdc, end_pos.x, end_pos.y);
ReleaseDC(hWnd, hdc);
}
break;
//좌클릭 눌렀을 때
case WM_LBUTTONDOWN:
/*
//예제 1을 위한 소스코드
//WM_PAINT가 아닌 곳에서 DC를 불러오는 방법
hdc = GetDC(hWnd);
MoveToEx(hdc, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),NULL);
LineTo(hdc, (GET_X_LPARAM(lParam)+100), GET_Y_LPARAM(lParam));
ReleaseDC(hWnd, hdc);
*/
//예제 2,3를 위한 소스코드
start_pos.x = GET_X_LPARAM(lParam);
start_pos.y = GET_Y_LPARAM(lParam);
//예제 3을 위한 소스코드
status = 1;
break;
//좌클릭 해제할 때
case WM_LBUTTONUP:
//예제 2,3를 위한 소스코드
end_pos.x = GET_X_LPARAM(lParam);
end_pos.y = GET_Y_LPARAM(lParam);
hdc = GetDC(hWnd);
MoveToEx(hdc, start_pos.x, start_pos.y, NULL);
LineTo(hdc, end_pos.x, end_pos.y);
ReleaseDC(hWnd, hdc);
//예제 3을 위한 소스코드
status = 0;
break;
여기서 몇 가지 문제점이 발생하게 됩니다 예제 1과는 상반되는 문제가 발생하여 계속해서 그리기를 진행하기 때문에 아래와 같은 현상이 생깁니다.
계속해서 그림을 그리기 때문입니다.
문제를 해결하기 위해서는 어떻게 해야 될까요?
이번 예제에서는 지난 글들에서 서술한 내용들과 같이 무효화 영역과 WM_PAINT를 활용하여 극복해보도록 하겠습니다.
case WM_PAINT:
{
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps);
//예제 4를 위한 소스코드
if (status == 1)
{
MoveToEx(hdc, start_pos.x, start_pos.y, NULL);
LineTo(hdc, end_pos.x, end_pos.y);
}
EndPaint(hWnd, &ps);
}
break;
//마우스 동작에 따른 처리
//움직일 때
case WM_MOUSEMOVE:
//예제 4를 위한 소스코드
if (status == 1)
{
end_pos.x = GET_X_LPARAM(lParam);
end_pos.y = GET_Y_LPARAM(lParam);
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
break;
//좌클릭 눌렀을 때
case WM_LBUTTONDOWN:
//예제 4를 위한 소스코드
start_pos.x = GET_X_LPARAM(lParam);
start_pos.y = GET_Y_LPARAM(lParam);
status = 1;
break;
//좌클릭 해제할 때
case WM_LBUTTONUP:
//예제 4를 위한 소스코드
end_pos.x = GET_X_LPARAM(lParam);
end_pos.y = GET_Y_LPARAM(lParam);
status = 0;
break;
이처럼 동작을 하면 마우스가 움직일 때마다 무효화 영역을 발생시키고, WM_PAINT에서 마우스 좌표를 확인하여 계속해서 그리는 동작을 하는 것을 확인할 수 있습니다.
사용자가 직선이 그러지는 모습을 실시간으로 확인할 수 있죠.
하지만 다시 클릭을 이용해 다른 직선을 그리면 기존에 그렸던 직선을 사라지는 문제가 발생하게 되었습니다.
이 해결방법은 다음 글에서 다시 서술하도록 하겠습니다.
Win32_API - GDI 선그리기4(Vector 활용해서 여러 선 저장하기) (0) | 2022.03.23 |
---|---|
Win32_API - GDI로 선그리기3(연속해서 여러 선 그리기) (0) | 2022.03.18 |
Win32_API - GDI로 선그리기1 (0) | 2022.03.14 |
Win32_API - 색상표 만들기(스크롤 바 추가하기) (0) | 2022.03.13 |
Win32_API - 막대바 컨트롤(Scroll Bar) (0) | 2022.03.07 |
91년생 공학엔지니어의 개발일지
TODAY :
YESTER DAY :
TOTAL :
Commnet