- 마우스 드래그해서 사각형 그리기
#include <vector>
using std::vector;
struct tObjInfo
{
POINT curPos;
POINT curSize;
};
vector<tObjInfo> g_vecInfo;
POINT g_ptLT;
POINT g_ptRB;
bool bLbtnDown = false;
사각형의 정보를 저장할 구조체 타입과 해당 정보를 배열로 저장할 벡터를 전역변수로 선언해줌.
또 전역변수로 좌상단, 우하단 지점을 저장할 변수를 선언해놓고
마우스를 눌렀다 뗐을 때 사각형을 저장하도록 bool 타입도 만들어줌.
case WM_LBUTTONDOWN:
{
g_ptLT.x = LOWORD(lParam);
g_ptLT.y = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
bLbtnDown = true;
}
break;
case WM_MOUSEMOVE:
{
g_ptRB.x = LOWORD(lParam);
g_ptRB.y = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case WM_LBUTTONUP:
{
g_ptRB.x = LOWORD(lParam);
g_ptRB.y = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
tObjInfo info{};
info.curPos = { (g_ptLT.x + g_ptRB.x) / 2, (g_ptLT.y + g_ptRB.y) / 2 };
info.curSize = { abs(g_ptRB.x - g_ptLT.x), abs(g_ptRB.y - g_ptLT.y) };
g_vecInfo.push_back(info);
bLbtnDown = false;
}
마우스 눌렀을 때 좌상단 포인트를 기록하고 bool 값도 true 로 함.
마우스를 움질일 때 우하단 포인트를 계속 업데이트하고
마우스를 뗐을 때 우하단 포인트를 한 번 더 업데이트하고
구조체 지역변수 만들어서 사각형의 중앙 위치와 크기를 계산한 뒤 벡터에 추가한다.
또한 bool 값도 false 로 해줘서 클릭하기 전까지 다시 그리지 않도록 함.
if(bLbtnDown)
Rectangle(hdc,
g_ptLT.x, g_ptLT.y,
g_ptRB.x, g_ptRB.y);
for (vector<tObjInfo>::iterator itr = g_vecInfo.begin();
itr != g_vecInfo.end(); itr++)
{
Rectangle(hdc,
itr->curPos.x - itr->curSize.x / 2,
itr->curPos.y - itr->curSize.y / 2,
itr->curPos.x + itr->curSize.x / 2,
itr->curPos.y + itr->curSize.y / 2);
}
WM_PAINT 블럭에서 사각형을 그려준다.

그럼 이렇게 마우스를 드래그하면 사각형이 늘어나고
떼면 사각형이 생성되는 것을 확인.
사각형이 늘어날수록 전체 픽셀들이 깜빡거리는 현상이 심해지는데,
이는 하나의 화면에 반복적으로
그렸다 지웠다를 반복하면서 우리 눈에는 미처 다 그리지 못한 중간 화면이 스쳐 지나가기 때문이다.
해결 방법은 그래픽스에서 더블 버퍼링, 스왑 체인이라고 함.
- 타이머 사용
입력을 아무것도 하지 않으면 아무 메시지가 발생하지 않는다.
타이머를 이용해서 강제로 WM_TIMER 메시지를 발생시킬 수 있음.
// 타이머 설정
SetTimer(g_hWnd, 0, 0, nullptr);
// 기본 메시지 루프입니다:
// GetMessage: 메시지 큐에서 메시지를 가져옵니다. (큐에 메시지가 없으면 대기)
// msg.message == WM_QUIT 이면 0을 반환하여 루프를 종료합니다.
while (GetMessage(&msg, nullptr, 0, 0))
{
// 단축키 테이블 확인.
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// 타이머 제거.
KillTimer(g_hWnd, 0);
타이머를 생성하고 프로그램 종료될 때 다시 제거해줌.
'Win32 api' 카테고리의 다른 글
| Win32 api 강의 7화. (0) | 2025.09.11 |
|---|---|
| Win32 api 강의 6화. (0) | 2025.09.11 |
| Win32 api 강의 4화. (0) | 2025.09.10 |
| Win32 api 강의 3화. (0) | 2025.09.10 |
| Win32 api 강의 2화. (0) | 2025.09.09 |