Dibujo a intervalos con tiempo
Puede dibujar en intervalos de tiempo mediante la creación de un temporizador con la función SetTimer . Mediante el uso de un temporizador para enviar mensajes WM_TIMER al procedimiento de ventana a intervalos regulares, una aplicación puede llevar a cabo una animación sencilla en el área cliente mientras otras aplicaciones continúan ejecutándose.
En el ejemplo siguiente, la aplicación rebota un star de lado a lado en el área cliente. Cada vez que el procedimiento de ventana recibe un mensaje de WM_TIMER, el procedimiento borra el star en la posición actual, calcula una nueva posición y dibuja el star dentro de la nueva posición. El procedimiento inicia el temporizador llamando a SetTimer mientras procesa el mensaje de 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);
}
Esta aplicación usa un contexto de dispositivo privado para minimizar el tiempo necesario para preparar el contexto del dispositivo para dibujar. El procedimiento de ventana recupera e inicializa el contexto del dispositivo privado al procesar el mensaje de WM_CREATE, estableciendo el modo de operación de trama binaria para permitir que el star se borre y dibuje mediante la misma llamada a la función Polyline. El procedimiento de ventana también establece el origen de la ventanilla para permitir que el star se dibuje con el mismo conjunto de puntos, independientemente de la posición del star en el área cliente.
La aplicación usa el mensaje WM_PAINT para dibujar el star cada vez que se debe actualizar la ventana. El procedimiento de ventana dibuja el star solo si no está visible; es decir, solo si el mensaje WM_ERASEBKGND ha borrado. El procedimiento de ventana intercepta el mensaje WM_ERASEBKGND para establecer la variable fVisible , pero pasa el mensaje a DefWindowProc para que el sistema pueda dibujar el fondo de la ventana.
La aplicación usa el mensaje WM_SIZE para detener el temporizador cuando se minimiza la ventana y reiniciar el temporizador cuando se restaura la ventana minimizada. El procedimiento de ventana también usa el mensaje para actualizar la posición actual del star si se ha reducido el tamaño de la ventana para que el star ya no esté en el área cliente. La aplicación realiza un seguimiento de la posición actual del star mediante la estructura especificada por rcCurrent, que define el rectángulo delimitador para el star. Mantener todas las esquinas del rectángulo en el área cliente mantiene el star en el área. El procedimiento de ventana centra inicialmente el star en el área cliente al procesar el mensaje WM_CREATE.