영어로 읽기

다음을 통해 공유


시간 간격으로 그리기

SetTimer 함수를 사용하여 타이머를 만들어 정해진 간격으로 그릴 수 있습니다. 타이머를 사용하여 WM_TIMER 메시지를 정기적으로 창 프로시저로 보내면 애플리케이션은 다른 애플리케이션이 계속 실행되는 동안 클라이언트 영역에서 간단한 애니메이션을 수행할 수 있습니다.

다음 예제에서 애플리케이션은 클라이언트 영역에서 별을 좌우로 반송합니다. 창 프로시저가 WM_TIMER 메시지를 받을 때마다 프로시저는 현재 위치에서 별을 지우고, 새 위치를 계산하고, 새 위치 내에 별을 그립니다. 프로시저는 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 함수에 대한 동일한 호출을 사용하여 별을 지우고 그릴 수 있도록 이진 래스터 작업 모드를 설정합니다. 또한 창 프로시저는 뷰포트 원점을 설정하여 클라이언트 영역에서 별의 위치에 관계없이 동일한 점 집합을 사용하여 별을 그릴 수 있도록 합니다.

애플리케이션은 WM_PAINT 메시지를 사용하여 창을 업데이트해야 할 때마다 별을 그립니다. 창 프로시저는 별이 보이지 않을 때만, 즉 WM_ERASEBKGND 메시지에 의해 지워졌을 때만 별을 그립니다. 창 프로시저는 WM_ERASEBKGND 메시지를 가로채 fVisible 변수를 설정하지만 시스템에서 창 배경을 그릴 수 있도록 DefWindowProc 메시지를 전달합니다.

애플리케이션은 WM_SIZE 메시지를 사용하여 창이 최소화될 때 타이머를 중지하고 최소화된 창이 복원될 때 타이머를 다시 시작합니다. 창 프로시저는 창의 크기가 줄어들어 별이 더 이상 클라이언트 영역에 있지 않을 때 메시지를 사용하여 별의 현재 위치를 업데이트합니다. 애플리케이션은 별의 경계 사각형을 정의하는 rcCurrent로 지정된 구조를 사용하여 별의 현재 위치를 추적합니다. 클라이언트 영역에서 사각형의 모든 모서리를 유지하면 해당 영역의 별표가 유지됩니다. 창 프로시저는 처음에 WM_CREATE 메시지를 처리할 때 클라이언트 영역의 별을 중심에 맞춥니다.