CreateCompatibleBitmap

CreateCompatibleBitmapは、指定されたデバイスコンテキストと互換性のあるビットマップを作成するWindowsAPI・・・。

CreateCompatibleBitmap 関数

これまでは、メモリデバイスコンテキストに紐づけられたロードした画像を、直接ウィンドウの物理デバイスコンテキストに転送して表示していた・・・。
しかし、この方法だと画像が動くようなアニメーション描画において、描画タイミングが合わずノイズのようなものでちらついてしまうことがある・・・。

このとき、ダブルバッファリングという方法を使って、ちらつかないようにする・・・。

ダブルバッファリングとは 【 double buffering 】 - 意味/解説/説明/定義 : IT用語辞典

ダブルバッファリングには、画像ロード用のビットマップ&メモリデバイスコンテキスト以外に、物理デバイスコンテキストに転送する前にいったん描画しておくバックバッファ用のビットマップ&メモリデバイスコンテキストが必要・・・。
そのバックバッファ用の物理デバイスコンテキスト互換なビットマップを作成するためにCreateCompatibleBitmapを使う・・・。

今回は、最初にメッセージボックスが出て、「はい」ならダブルバッファリングを使用し、「いいえ」なら使用しない・・・。
画像が表示されて任意のキーが押されたら右下に移動するようなプログラムを作る・・・。

ロード用、バックバッファ用の2つのビットマップハンドル、通常モードかダブルバッファリングモードかを保持する変数、そして矩形描画位置x, yをスタティック変数で用意・・・。

WM_CREATEで、まずはモード選択・・・。

で「はい」ならダブルバッファリングなので、

iMode = 1とし、GetDCで物理デバイスコンテキストhDCを取得し、それを使ってCreateCompatibleBitmapでhBackBitmap作成・・・。hDCはもうここでは用済みなのでReleaseDCで解放・・・。

今度は、

LoadImageでロードし、ハンドルはhLoadBitmapに・・・。
これで2つのビットマップがそろった・・・。
もし、「いいえ」ならhLoadBitmapだけ・・・。

描画はWM_PAINTで行う・・・。

iMode == 1ならhBackMemDCもCreateCompatibleDCで用意する・・・。

iMode == 1ならhBackBitmapもhBackMemDCとSelectObjectで紐づける・・・。

iMode == 1の時、hLoadMemDCの内容はhBackMemDCに転送する・・・。
そのあと、hBackMemDCの座標(x, y)に矩形を描画・・・。
つまり、ビットマップの描画も、矩形の描画も、いったんhBackMemDCに行っている・・・。
そのあと、hBackMemDCの内容をhDCに転送している・・・。
iMode == 0の時は、ビットマップも矩形もhDCに直接描画している・・・。

で、WM_KEYDOWN、つまり任意のキーが押された時、

x, yをそれぞれ1増やしている・・・。
そしてInvalidateRectでは、第3引数の背景の消去、これはFALSEにしておく・・・。
このほうがちらつきは起きにくい・・・。

実行してみる・・・。

f:id:BG1:20150411221237p:plain

まずは「いいえ」を選択・・・。

f:id:BG1:20150411221327p:plain

背景のビットマップ、そして白い矩形が描画されてる・・・。
適当にキーを押すと、

f:id:BG1:20150411221513p:plain

白い矩形が右下に移動し・・・、画面がちらつ・・・かない!!
おかしいな・・・。昔のPCではよく起こったんだけど、最近のスペックのPCでは起こらないのかも・・・。

ちなみに、ダブルバッファリングにして、

f:id:BG1:20150411222653p:plain

矩形を移動しても、

f:id:BG1:20150411222738p:plain

当然ちらつかない・・・。

本来、ダブルバッファリングの時だけちらつかないのを期待していたのだが、ちょっと再現する方法を間違えたかな・・・。
まあ、とにかく、今回は

  1. CreateCompatibleBitmapでhDC互換なビットマップを作れる
  2. ダブルバッファリングという描画方法

この2つがポイント・・・。

Sample/CreateCompatibleBitmap.cpp at master · bg1bgst333/Sample · GitHub