Bagikan melalui


Menggambar pada Interval Berwakmata

Anda dapat menggambar pada interval berwaktu dengan membuat timer dengan fungsi SetTimer . Dengan menggunakan timer untuk mengirim WM_TIMER pesan ke prosedur jendela secara berkala, aplikasi dapat melakukan animasi sederhana di area klien sementara aplikasi lain terus berjalan.

Dalam contoh berikut, aplikasi memantulkan star dari sisi ke sisi di area klien. Setiap kali prosedur jendela menerima pesan WM_TIMER, prosedur menghapus star pada posisi saat ini, menghitung posisi baru, dan menarik star dalam posisi baru. Prosedur memulai timer dengan memanggil SetTimer saat memproses pesan 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); 
} 

Aplikasi ini menggunakan konteks perangkat privat untuk meminimalkan waktu yang diperlukan untuk menyiapkan konteks perangkat untuk menggambar. Prosedur jendela mengambil dan menginisialisasi konteks perangkat privat saat memproses pesan WM_CREATE, mengatur mode operasi raster biner untuk memungkinkan star dihapus dan digambar menggunakan panggilan yang sama ke fungsi Polyline. Prosedur jendela juga mengatur asal viewport untuk memungkinkan star digambar menggunakan set titik yang sama terlepas dari posisi star di area klien.

Aplikasi ini menggunakan pesan WM_PAINT untuk menggambar star setiap kali jendela harus diperbarui. Prosedur jendela menarik star hanya jika tidak terlihat; yaitu, hanya jika telah dihapus oleh pesan WM_ERASEBKGND. Prosedur jendela mencegat pesan WM_ERASEBKGND untuk mengatur variabel fVisible , tetapi meneruskan pesan ke DefWindowProc sehingga sistem dapat menggambar latar belakang jendela.

Aplikasi menggunakan pesan WM_SIZE untuk menghentikan timer ketika jendela diminimalkan dan untuk memulai ulang timer ketika jendela yang diminimalkan dipulihkan. Prosedur jendela juga menggunakan pesan untuk memperbarui posisi star saat ini jika ukuran jendela telah berkurang sehingga star tidak lagi berada di area klien. Aplikasi ini melacak posisi star saat ini dengan menggunakan struktur yang ditentukan oleh rcCurrent, yang menentukan persegi panjang pembatas untuk star. Menjaga semua sudut persegi panjang di area klien menjaga star di area tersebut. Prosedur jendela awalnya berpusat pada star di area klien saat memproses pesan WM_CREATE.