閱讀英文

共用方式為


在限定時間間隔內繪圖

您可以使用 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 訊息時,視窗程式一開始會在工作區中置中星號。