시간 간격으로 그리기
SetTimer 함수를 사용하여 타이머를 만들어 시간 간격으로 그릴 수 있습니다. 타이머를 사용하여 일정한 간격으로 창 프로시저에 WM_TIMER 메시지를 보내면 애플리케이션은 다른 애플리케이션이 계속 실행되는 동안 클라이언트 영역에서 간단한 애니메이션을 수행할 수 있습니다.
다음 예제에서 애플리케이션은 클라이언트 영역에서 star 좌우로 반송합니다. 창 프로시저가 WM_TIMER 메시지를 받을 때마다 프로시저는 현재 위치에서 star 지우고, 새 위치를 계산하고, 새 위치 내에 star 그립니다. 프로시저는 WM_CREATE 메시지를 처리하는 동안 SetTimer를 호출하여 타이머를 시작합니다.
RECT rcCurrent = {0,0,20,20};
POINT aptStar[6] = {10,1, 1,19, 19,6, 1,6, 19,19, 10,1};
int X = 2, Y = -1, idTimer = -1;
BOOL fVisible = FALSE;
HDC hdc;
LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
RECT rc;
switch (message)
{
case WM_CREATE:
// Calculate the starting point.
GetClientRect(hwnd, &rc);
OffsetRect(&rcCurrent, rc.right / 2, rc.bottom / 2);
// Initialize the private DC.
hdc = GetDC(hwnd);
SetViewportOrgEx(hdc, rcCurrent.left,
rcCurrent.top, NULL);
SetROP2(hdc, R2_NOT);
// Start the timer.
SetTimer(hwnd, idTimer = 1, 10, NULL);
return 0L;
case WM_DESTROY:
KillTimer(hwnd, 1);
PostQuitMessage(0);
return 0L;
case WM_SIZE:
switch (wParam)
{
case SIZE_MINIMIZED:
// Stop the timer if the window is minimized.
KillTimer(hwnd, 1);
idTimer = -1;
break;
case SIZE_RESTORED:
// Move the star back into the client area
// if necessary.
if (rcCurrent.right > (int) LOWORD(lParam))
{
rcCurrent.left =
(rcCurrent.right =
(int) LOWORD(lParam)) - 20;
}
if (rcCurrent.bottom > (int) HIWORD(lParam))
{
rcCurrent.top =
(rcCurrent.bottom =
(int) HIWORD(lParam)) - 20;
}
// Fall through to the next case.
case SIZE_MAXIMIZED:
// Start the timer if it had been stopped.
if (idTimer == -1)
SetTimer(hwnd, idTimer = 1, 10, NULL);
break;
}
return 0L;
case WM_TIMER:
// Hide the star if it is visible.
if (fVisible)
Polyline(hdc, aptStar, 6);
// Bounce the star off a side if necessary.
GetClientRect(hwnd, &rc);
if (rcCurrent.left + X < rc.left ||
rcCurrent.right + X > rc.right)
X = -X;
if (rcCurrent.top + Y < rc.top ||
rcCurrent.bottom + Y > rc.bottom)
Y = -Y;
// Show the star in its new position.
OffsetRect(&rcCurrent, X, Y);
SetViewportOrgEx(hdc, rcCurrent.left,
rcCurrent.top, NULL);
fVisible = Polyline(hdc, aptStar, 6);
return 0L;
case WM_ERASEBKGND:
// Erase the star.
fVisible = FALSE;
return DefWindowProc(hwnd, message, wParam, lParam);
case WM_PAINT:
// Show the star if it is not visible. Use BeginPaint
// to clear the update region.
BeginPaint(hwnd, &ps);
if (!fVisible)
fVisible = Polyline(hdc, aptStar, 6);
EndPaint(hwnd, &ps);
return 0L;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
이 애플리케이션은 프라이빗 디바이스 컨텍스트를 사용하여 그리기 위해 디바이스 컨텍스트를 준비하는 데 필요한 시간을 최소화합니다. 창 프로시저는 WM_CREATE 메시지를 처리할 때 개인 디바이스 컨텍스트를 검색하고 초기화하여 Polyline 함수에 대한 동일한 호출을 사용하여 star 지우고 그릴 수 있도록 이진 래스터 작업 모드를 설정합니다. 또한 창 프로시저는 클라이언트 영역에서 star 위치에 관계없이 동일한 점 집합을 사용하여 star 그릴 수 있도록 뷰포트 원본을 설정합니다.
애플리케이션은 WM_PAINT 메시지를 사용하여 창을 업데이트해야 할 때마다 star 그립니다. 창 프로시저는 표시되지 않는 경우에만 star 그립니다. 즉, WM_ERASEBKGND 메시지에 의해 지워진 경우에만 그려집니다. 창 프로시저는 WM_ERASEBKGND 메시지를 가로채 fVisible 변수를 설정하지만 시스템에서 창 배경을 그릴 수 있도록 메시지를 DefWindowProc 에 전달합니다.
애플리케이션은 WM_SIZE 메시지를 사용하여 창이 최소화될 때 타이머를 중지하고 최소화된 창이 복원될 때 타이머를 다시 시작합니다. 창 프로시저는 또한 메시지를 사용하여 star 더 이상 클라이언트 영역에 있지 않도록 창 크기가 줄어드는 경우 star 현재 위치를 업데이트합니다. 애플리케이션은 star 경계 사각형을 정의하는 rcCurrent에 지정된 구조를 사용하여 star 현재 위치를 추적합니다. 클라이언트 영역에 사각형의 모든 모서리를 유지하면 영역에 star 유지됩니다. 창 프로시저는 처음에 WM_CREATE 메시지를 처리할 때 클라이언트 영역의 star 가운데에 옵니다.