Dessin à intervalles temporels

Vous pouvez dessiner à intervalles réguliers en créant un minuteur avec la fonction SetTimer . En utilisant un minuteur pour envoyer des messages WM_TIMER à la procédure de fenêtre à intervalles réguliers, une application peut effectuer une animation simple dans la zone cliente pendant que d’autres applications continuent à s’exécuter.

Dans l’exemple suivant, l’application rebondit un star d’un côté à l’autre dans la zone cliente. Chaque fois que la procédure de fenêtre reçoit un message WM_TIMER, la procédure efface le star à la position actuelle, calcule une nouvelle position et dessine les star dans la nouvelle position. La procédure démarre le minuteur en appelant SetTimer lors du traitement du message WM_CREATE .

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); 
} 

Cette application utilise un contexte d’appareil privé pour réduire le temps nécessaire à la préparation du contexte de l’appareil pour le dessin. La procédure de fenêtre récupère et initialise le contexte de l’appareil privé lors du traitement du message WM_CREATE, en définissant le mode d’opération raster binaire pour permettre l’effacement et le dessin du star à l’aide du même appel à la fonction Polyline. La procédure de fenêtre définit également l’origine de la fenêtre d’affichage pour permettre au star d’être dessiné à l’aide du même ensemble de points, quelle que soit la position du star dans la zone cliente.

L’application utilise le message WM_PAINT pour dessiner les star chaque fois que la fenêtre doit être mise à jour. La procédure de fenêtre dessine le star uniquement s’il n’est pas visible, c’est-à-dire uniquement s’il a été effacé par le message WM_ERASEBKGND. La procédure de fenêtre intercepte le message WM_ERASEBKGND pour définir la variable fVisible , mais transmet le message à DefWindowProc afin que le système puisse dessiner l’arrière-plan de la fenêtre.

L’application utilise le message WM_SIZE pour arrêter le minuteur lorsque la fenêtre est réduite et pour redémarrer le minuteur lorsque la fenêtre réduite est restaurée. La procédure de fenêtre utilise également le message pour mettre à jour la position actuelle de l’star si la taille de la fenêtre a été réduite de sorte que le star ne se trouve plus dans la zone cliente. L’application effectue le suivi de la position actuelle du star à l’aide de la structure spécifiée par rcCurrent, qui définit le rectangle englobant pour le star. Le fait de conserver tous les coins du rectangle dans la zone cliente conserve le star dans la zone. La procédure de fenêtre centre initialement la star dans la zone cliente lors du traitement du message WM_CREATE.