Zeichnen in Zeitintervallen
Sie können in Zeitintervallen zeichnen, indem Sie einen Timer mit der SetTimer-Funktion erstellen. Durch die Verwendung eines Zeitgebers, um in regelmäßigen Abständen WM_TIMER Nachrichten an die Fensterprozedur zu senden, kann eine Anwendung eine einfache Animation im Clientbereich ausführen, während andere Anwendungen weiterhin ausgeführt werden.
Im folgenden Beispiel wird von der Anwendung ein star im Clientbereich von einer Seite nach der anderen abgeprallt. Jedes Mal, wenn die Fensterprozedur eine WM_TIMER Nachricht empfängt, löscht die Prozedur den star an der aktuellen Position, berechnet eine neue Position und zeichnet die star innerhalb der neuen Position. Die Prozedur startet den Timer, indem SetTimer aufgerufen wird, während die WM_CREATE Nachricht verarbeitet wird.
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);
}
Diese Anwendung verwendet einen privaten Gerätekontext, um die Zeit zu minimieren, die zum Vorbereiten des Gerätekontexts für das Zeichnen erforderlich ist. Die Fensterprozedur ruft den privaten Gerätekontext ab und initialisiert ihn beim Verarbeiten der WM_CREATE-Nachricht. Dabei wird der Binäre Raster-Vorgangsmodus so festgelegt, dass der star gelöscht und mit demselben Aufruf der Polyline-Funktion gezeichnet werden kann. Die Fensterprozedur legt auch den Viewportursprung fest, damit der star mit demselben Satz von Punkten gezeichnet werden kann, unabhängig von der Position des star im Clientbereich.
Die Anwendung verwendet die WM_PAINT-Nachricht, um die star zu zeichnen, wenn das Fenster aktualisiert werden muss. Die Fensterprozedur zeichnet die star nur, wenn sie nicht sichtbar ist, d. h. nur, wenn sie von der WM_ERASEBKGND Nachricht gelöscht wurde. Die Fensterprozedur fängt die WM_ERASEBKGND Nachricht ab, um die fVisible-Variable festzulegen, übergibt die Nachricht jedoch an DefWindowProc , damit das System den Fensterhintergrund zeichnen kann.
Die Anwendung verwendet die WM_SIZE Meldung, um den Timer zu beenden, wenn das Fenster minimiert wird, und um den Timer neu zu starten, wenn das minimierte Fenster wiederhergestellt wird. Die Fensterprozedur verwendet die Meldung auch, um die aktuelle Position des star zu aktualisieren, wenn die Größe des Fensters reduziert wurde, sodass sich das star nicht mehr im Clientbereich befindet. Die Anwendung verfolgt die aktuelle Position des star mithilfe der von rcCurrent angegebenen Struktur, die das umgebende Rechteck für das star definiert. Wenn Sie alle Ecken des Rechtecks im Clientbereich beibehalten, bleibt die star im Bereich. Die Fensterprozedur zentrisiert zunächst die star im Clientbereich, wenn die WM_CREATE Nachricht verarbeitet wird.