A elipse se movimenta de acordo com o temporizador SetTimer

main.html
#include <windows.h>

#define ID_TIMER 1

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) {
    static HBITMAP hBitmap;
    static int cxClient, cyClient, xCenter, yCenter,
               cxTotal, cyTotal, cxRadius, cyRadius,
               cxMove, cyMove, xPixel, yPixel;
    HBRUSH hBrush;
    HDC hdc, hdcMem;
    int iScale;
    
    switch(msg) {
        case WM_CREATE:
            hdc = GetDC(hwnd);
            xPixel = GetDeviceCaps(hdc, ASPECTX);
            yPixel = GetDeviceCaps(hdc, ASPECTY);
            ReleaseDC(hwnd, hdc);
            SetTimer(hwnd, ID_TIMER, 50, NULL);
            return 0;
        case WM_SIZE:
            xCenter = (cxClient = LOWORD (lP)) / 2;
            yCenter = (cyClient = HIWORD (lP)) / 2;
            iScale = min(cxClient*xPixel,cyClient*yPixel) / 16;
            cxRadius = iScale / xPixel;
            cyRadius = iScale / yPixel;
            cxMove = max(1, cxRadius / 2);
            cyMove = max(1, cyRadius / 2);
            cxTotal = 2 * (cxRadius + cxMove);
            cyTotal = 2 * (cyRadius + cyMove);
            if(hBitmap)
                DeleteObject(hBitmap);
            hdc = GetDC(hwnd);
            hdcMem = CreateCompatibleDC(hdc);
            hBitmap = CreateCompatibleBitmap(
                hdc, cxTotal, cyTotal
            );
            ReleaseDC(hwnd, hdc);
            SelectObject(hdcMem, hBitmap);
            Rectangle(hdcMem, -1, -1, cxTotal + 1, cyTotal + 1);
            hBrush = CreateHatchBrush(
                HS_DIAGCROSS/*Crosshatch de 45 graus*/,
                0L/*A cor de primeiro plano do pincel*/
            );
            SelectObject(hdcMem, hBrush);
            SetBkColor(hdcMem, RGB(255, 0, 52));
            Ellipse(
                hdcMem,
                cxMove,
                cyMove,
                cxTotal - cxMove,
                cyTotal - cyMove
            );
            DeleteDC(hdcMem);
            DeleteObject(hBrush);
            return 0;
        case WM_TIMER:
            if(!hBitmap)
                break;
            hdc = GetDC(hwnd);
            hdcMem = CreateCompatibleDC(hdc);
            SelectObject(hdcMem, hBitmap);
            /**
                A função BitBlt executa uma transferência
                de bloco de bits dos dados de cor
                correspondentes a um retângulo de pixels do
                contexto do dispositivo de origem especificado
                para um contexto de dispositivo de destino.
            */
            BitBlt (
                hdc, xCenter - cxTotal / 2,
                yCenter - cyTotal / 2, cxTotal, cyTotal,
                hdcMem, 0, 0, SRCCOPY
            );
            ReleaseDC(hwnd, hdc);
            DeleteDC(hdcMem);
            xCenter += cxMove;
            yCenter += cyMove;
            if((xCenter+cxRadius>=cxClient)||(xCenter-cxRadius<=0))
                cxMove = -cxMove;
            if((yCenter+cyRadius>=cyClient)||(yCenter-cyRadius<=0))
                cyMove = -cyMove;
            return 0;

        case WM_DESTROY: {
            if(hBitmap)
                DeleteObject(hBitmap);
            KillTimer(hwnd, ID_TIMER);
            PostQuitMessage(0);
            break;
        }
        
        default:
            return DefWindowProc(hwnd, msg, wP, lP);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hI, HINSTANCE hPI, LPSTR szCL, int iCS) {
    WNDCLASSEX wc; /* A properties struct of our window */
    HWND hwnd;
    MSG msg; /* A temporary location for all messages */

    /* zero out the struct and set the stuff we want to modify */
    memset(&wc,0,sizeof(wc));
    wc.cbSize      = sizeof(WNDCLASSEX);
    wc.lpfnWndProc = WndProc;
    wc.hInstance   = hI;
    wc.hCursor     = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszClassName = "WindowClass";
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc)) {
        MessageBox(
            NULL,
            "Window Registration Failed!",
            "Error!",
            MB_ICONEXCLAMATION | MB_OK
        );
        return 0;
    }

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        "WindowClass",
        "Ellipse em Movimento",
        WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        200, /* x */
        40, /* y */
        500, /* width */
        400, /* height */
        NULL,
        NULL,
        hI,
        NULL
    );

    if(hwnd == NULL) {
        MessageBox(
            NULL,
            "Window Creation Failed!",
            "Error!",
            MB_ICONEXCLAMATION|MB_OK
        );
        return 0;
    }

    while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
        TranslateMessage(&msg); /* Translate key codes to chars if present */
        DispatchMessage(&msg); /* Send it to WndProc */
    }
    return msg.wParam;
}

Comentários