Desenho em intervalos cronometrado
Você pode desenhar em intervalos cronometrados criando um temporizador com a função SetTimer . Usando um temporizador para enviar mensagens WM_TIMER para o procedimento de janela em intervalos regulares, um aplicativo pode realizar animação simples na área do cliente enquanto outros aplicativos continuam em execução.
No exemplo a seguir, o aplicativo recupera um star de um lado para o outro na área do cliente. Cada vez que o procedimento de janela recebe uma mensagem WM_TIMER, o procedimento apaga o star na posição atual, calcula uma nova posição e desenha o star dentro da nova posição. O procedimento inicia o temporizador chamando SetTimer durante o processamento da mensagem 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);
}
Esse aplicativo usa um contexto de dispositivo privado para minimizar o tempo necessário para preparar o contexto do dispositivo para desenho. O procedimento de janela recupera e inicializa o contexto do dispositivo privado ao processar a mensagem WM_CREATE, definindo o modo de operação de varredura binária para permitir que o star seja apagado e desenhado usando a mesma chamada para a função Polyline. O procedimento de janela também define a origem do visor para permitir que o star seja desenhado usando o mesmo conjunto de pontos, independentemente da posição do star na área do cliente.
O aplicativo usa a mensagem WM_PAINT para desenhar o star sempre que a janela deve ser atualizada. O procedimento de janela desenha o star somente se não estiver visível; ou seja, somente se tiver sido apagado pela mensagem WM_ERASEBKGND. O procedimento de janela intercepta a mensagem WM_ERASEBKGND para definir a variável fVisible , mas passa a mensagem para DefWindowProc para que o sistema possa desenhar a tela de fundo da janela.
O aplicativo usa a mensagem WM_SIZE para interromper o temporizador quando a janela é minimizada e reiniciar o temporizador quando a janela minimizada é restaurada. O procedimento de janela também usa a mensagem para atualizar a posição atual do star se o tamanho da janela tiver sido reduzido para que o star não esteja mais na área do cliente. O aplicativo controla a posição atual do star usando a estrutura especificada por rcCurrent, que define o retângulo delimitador para o star. Manter todos os cantos do retângulo na área do cliente mantém o star na área. Inicialmente, o procedimento de janela centraliza o star na área do cliente ao processar a mensagem de WM_CREATE.