Zamanlanmış Aralıklarla Çizim
SetTimer işleviyle bir zamanlayıcı oluşturarak zamanlanmış aralıklarla çizim yapabilirsiniz. Düzenli aralıklarla pencere yordamına WM_TIMER iletileri göndermek için zamanlayıcı kullanarak, diğer uygulamalar çalışmaya devam ederken uygulama istemci alanında basit animasyonlar gerçekleştirebilir.
Aşağıdaki örnekte, uygulama istemci alanında bir yıldızı yanlara doğru zıplatmaktadır. Pencere yordamı her WM_TIMER iletisi aldığında, yordam geçerli konumdaki yıldızı siler, yeni bir konum hesaplar ve yıldızı yeni konumda çizer. Yordam, WM_CREATE iletisini işlerken SetTimer çağırarak zamanlayıcıyı başlatır.
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);
}
Bu uygulama, cihaz bağlamını çizime hazırlamak için gereken süreyi en aza indirmek için özel bir cihaz bağlamı kullanır. Pencere yordamı işlevi, WM_CREATE iletisini işlerken özel cihaz bağlamını alır ve başlatır, ardından Polyline işlevine aynı çağrıyı kullanarak yıldızın silinmesine ve çizilmesine izin vermek için ikili rasterizasyon işlem modunu ayarlar. Pencere yordamı ayrıca, yıldızın istemci alanındaki konumundan bağımsız olarak aynı nokta kümesi kullanılarak yıldızın çizilmesine izin vermek için görünüm penceresi çıkış noktasını ayarlar.
Uygulama, pencerenin güncelleştirilebilmesi gerektiğinde yıldızı çizmek için WM_PAINT iletisini kullanır. Pencere prosedürü, yıldızı yalnızca görünmüyorsa çizer; yani, yalnızca WM_ERASEBKGND mesajı tarafından silindiyse. Pencere yordamı, fVisible değişkenini ayarlamak için WM_ERASEBKGND iletisini durdurur, ancak sistemin pencere arka planını çizebilmesi için iletiyi DefWindowProc iletir.
Uygulama, pencere simge durumuna küçültüldüğünde zamanlayıcıyı durdurmak ve simge durumuna küçültülmüş pencere geri yüklendiğinde zamanlayıcıyı yeniden başlatmak için WM_SIZE iletisini kullanır. Pencere prosedürü, ayrıca pencerenin boyutu küçültüldüyse ve yıldız artık istemci alanında değilse yıldızın geçerli konumunu güncellemek için de iletiyi kullanır. Uygulama, yıldız için sınırlayıcı dikdörtgeni tanımlayan rcCurrent tarafından belirtilen yapıyı kullanarak yıldızın geçerli konumunu izler. Dikdörtgenin köşelerini tüm müşteri alanında tutmak, yıldızın bölgede kalmasını sağlar. Pencere prosedürü, başlangıçta WM_CREATE iletisini işlerken yıldızı istemci alanının ortasına yerleştirir.