時間指定間隔での描画
SetTimer関数を使用してタイマーを作成することで、時間単位で描画できます。 タイマーを使用して WM_TIMER メッセージを一定の間隔でウィンドウ プロシージャに送信することで、アプリケーションはクライアント領域で単純なアニメーションを実行しながら、他のアプリケーションの実行を継続できます。
次の例では、アプリケーションはクライアント領域で星を左右にバウンスします。 ウィンドウ プロシージャが WM_TIMER メッセージを受け取るたびに、プロシージャは現在の位置の星を消去し、新しい位置を計算して、新しい位置内に星を描画します。 このプロシージャは、WM_CREATE メッセージの処理中 SetTimer を呼び出してタイマーを開始します。
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);
}
このアプリケーションでは、プライベート デバイス コンテキストを使用して、描画用のデバイス コンテキストを準備するために必要な時間を最小限に抑えます。 ウィンドウ プロシージャは、WM_CREATE メッセージを処理するときにプライベート デバイス コンテキストを取得して初期化し、ポリライン 関数の同じ呼び出しを使用してスターを消去して描画できるようにバイナリ ラスター操作モードを設定します。 また、ウィンドウ プロシージャでは、クライアント領域内での星の位置に関係なく、同じポイント セットを使用して星を描画できるようにビューポートの原点も設定します。
アプリケーションでは、ウィンドウを更新する必要があるときに常に、WM_PAINT メッセージを使用して星を描画します。 ウィンドウ プロシージャは、星が表示されない場合にのみ、星を描画します。つまり、WM_ERASEBKGND メッセージによって消去された場合に限ります。 ウィンドウ プロシージャは、WM_ERASEBKGND メッセージをインターセプトして fVisible 変数を設定しますが、システムがウィンドウの背景を描画できるように、DefWindowProcにメッセージを渡します。
アプリケーションは、WM_SIZE メッセージを使用して、ウィンドウが最小化されているときにタイマーを停止し、最小化されたウィンドウが復元されたときにタイマーを再起動します。 また、ウィンドウ プロシージャは、メッセージを使用して、ウィンドウのサイズが縮小され、星がクライアント領域に存在しなくなった場合に、星の現在位置を更新します。 アプリケーションは、rcCurrent で指定された構造体を使用して星の現在位置を追跡します。この構造体は、星を包む四角形を定義します。 四角形のすべての角をクライアント領域に保持すると、その領域に星が保持されます。 ウィンドウ プロシージャは、最初に、WM_CREATE メッセージを処理するときに、クライアント領域のスターを中央に移動します。