WinAPIでキレイに描画する -その2 バックバッファリング-
前回からの続き。
描画タイミングを合わせたとしても、描画途中が表示されては意味がない
という話。
ではどうすればいいかというと、
描画が完了するまで表示しなければいい。
正確には、描画が完了するまでは内部のバッファに描画し、
描き終ったら実際に表示するバッファに先程のバッファを丸々コピーすればいい。
という話。
この色が今回の追加分。
...
#define WINDOW_WIDTH (/*Windowの幅*/)
#define WINDOW_HEIGHT (/*Windowの高さ*/)
...
/*
* Windowプロシージャ
*/
LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg,
WPARAM wp, LPARAM lp )
{
...
static HDC back_hdc;
static HBITMAP back_buf;
...switch( msg )
{
...
case WM_CREATE:
...
HDC hdc = GetDC( hWnd );// バックバッファ生成
back_buf = CreateCompatibleBitmap(
hdc,
WINDOW_WIDTH, WINDOW_HEIGHT
);
// バックバッファ描画用ハンドル取得
back_hdc = CreateCompatibleDC( hdc );// ハンドルにバッファを設定しておく
SelectObject( back_hdc, back_buf );
// 念のためペン初期化
SelectObject( back_hdc, GetStockObject( NULL_PEN ) );ReleaseDC( hWnd, hdc );
...
break;
...
case WM_DESTROY:
...
// 忘れずにバックバッファ解放
DeleteDC( back_hdc );
DeleteObject( back_buf );
...
break;
...
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint( hWnd, &ps );// 描画用の処理をまとめた関数
// 引数にデバイスコンテキスタあたりを渡しておくと便利?
// →引数に描画先のデバイスコンテキスタを渡す
Draw( back_hdc );// 表示用バッファにバックバッファをそのままコピー
BitBlt( hdc,
0, 0,
WINDOW_WIDTH, WINDOW_HEIGHT,
back_hdc,
0, 0,
SRCCOPY );EndPaint( hWnd, &ps );
break;
...
}
...
}
...
とりあえず、ここまでで描画の際にチラつくことはほとんどなくなるはず。
…ただ、現状だとWM_PAINTが呼ばれないと描画されない(=表示が更新されない)。
ずっとアクティブな状態であるとを仮定すると、最初の生成時に描画した内容がそれっきり更新されないことになってしまう。
以降、次回。