3강 - 도형그리기 및 마우스
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
BeginPain는 HDC를 반환하고 H가 맨 앞에 있는걸로 보아 handle을 의미한다. dc는 클라이언트 화면에 그리기(출력하기) 위한 도구이다.
dc를 사용해 문자를 출력해보자.
샘플 코드
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
/* 마우스의 위치 출력*/
TCHAR mouse[64] = {};
// wsprintf : 유니코드 문자열을 만들어주는 함수
wsprintf(mouse, TEXT("x : %d y : %d"), _area.start.x, _area.start.y);
// lstrlen(변수) : 유니코드 문자열의 길이를 구하는 함수
TextOut(hdc, 600, 30, mouse, lstrlen(mouse));
/* 텍스트 출력 */
// 핸들, 좌표x, 좌표y, 유니코드문자열, 글자 갯수
// 유니코드 문자열을 작성할 때, 따옴표 앞에 L을 붙이거나 TEXT 매크로를 이용한다.
// L을 쓰는 것 보다 TEXT를 사용하는 것이 좋다. 왜냐하면 TEXT가 알아서
// 멀티바이트인 경우에도 처리해주기 때문
TextOut(hdc, 50, 50, TEXT("win32"), 5);
TextOut(hdc, 55, 55, TEXT("win32"), 5);
/* 도형 출력 */
/* 사각형 그리기 */
// 핸들, 사각형 왼쪽 상단 좌표x,y , 사격형 오른쪽 하단 좌표x,y,
Rectangle(hdc, 45, 45, 200, 200);
// ! 사각형을 텍스트 위에 출력하면 텍스트를 위로 덮어서 텍스트가 보이지 않는다.
TextOut(hdc, 60, 60, TEXT("win32"), 5);
/* 선 그리기 */
// 시작점과 끝점을 설정
// 선의 시작점 설정
MoveToEx(hdc, 70, 100, NULL);
// 끝점
LineTo(hdc, 400, 150);
// 끝점을 한번더 호출하면 끝점이 시작점이 되어 연결가능
LineTo(hdc, 500, 100);
// 시작점을 다시 지정해서 새로 그리기 가능
MoveToEx(hdc, 600, 300, NULL);
LineTo(hdc, 700, 400);
/* 원 */
// 45,45,200,200 사각형에 딱 맞는 원이 생성된다.
Ellipse(hdc, 45, 45, 200, 200);
/* 마우스 드래그하면 사각형이 그려지는 기능을 만들어보자 */
if (_area.isStarted)
{
Rectangle(hdc, _area.start.x, _area.start.y, _area.end.x, _area.end.y);
}
EndPaint(hWnd, &ps);
}
break;
// 키가 눌러졌을때 들어오는 메세지
// 마우스 좌클릭
case WM_MOUSEMOVE:
// 마우스가 움직일 때 들어오는 메시지
if (_area.isStarted)
{
_area.end.x = lParam & 0x0000ffff;
_area.end.y = lParam >> 16;
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case WM_LBUTTONUP:
// 마우스 왼쪽버튼이 떼질 때 발생하는 메시지
if (_area.isStarted)
{
_area.isStarted = false;
_area.end.x = lParam & 0x0000ffff;
_area.end.y = lParam >> 16;
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case WM_LBUTTONDOWN:
// 마우스 위치는 lParam에 들어오게 되는데 16비트로 쪼개서 x,y값이
// 32비트에 들어오게 된다. LOWORD, HIWORD 매크로를 이용해서 하위, 상위 16비트 값을 얻어온다.
if (!_area.isStarted)
{
_area.isStarted = true;
// 만약 lParam이 0x12345678 >> 16일때 결과는? 1234
_area.start.x = lParam & 0x0000ffff;
_area.start.y = lParam >> 16;
_area.end.x = _area.start.x;
_area.end.y = _area.start.y;
// InvalidateRect 함수는 강제로 WM_PAINT 메시지를
// 호출해주는 함수... 1번 인자 : 윈도우 핸들, 2번 인자 : 초기화할 영역
// NULL을 넣어줄 경우 전체화면을 대상으로 갱신 진행
// 3번 인자 : TRUE일 경우 현재 화면을 지우고 갱신, FALSE일 경우 안지우고 갱신
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case WM_KEYDOWN:
// 이 메시지가 들어올 경우 wParam에 어떤 키를 눌렀는지가 들어온다.
switch (wParam)
{
case VK_ESCAPE:
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
마우스 드래그 사각형 정리
처음에 구조체를 생성
struct _tagArea
{
bool isStarted;
POINT start;
POINT end;
};
마우스 움직이면
- 현재 마우스의 위치가 끝점이다.
- 즉, 움직일때 계속 위치가 갱신되어서 드래그 사각형이 계속 생성된다.
누르면
- bool 변수에 true를 넣는다.
- 시작점 저장
- 끝점을 초기화 해준다.
떼면
- bool 변수에 false를 넣는다.
- 끝점 저장
'WinAPI 튜토리얼' 카테고리의 다른 글
WinAPI 1강 : 기본 윈도우창 [어소트락 유튜브] (0) | 2019.05.30 |
---|