秘密基地、どこに作った?

こんばんわ。visual studio express 2013でC++を勉強している者です。

ダブルバッファリングをしたいのですが、チラつきが改善しません。
どう書けばダブルバッファリングを実現できるのか、ご教授ください。

以下は私が書いたコードの一部です。よろしくお願いします。

(要は、hdc_mem1のビットマップを、hdc_mem0(白紙のビットマップ)に読み込み、hdc_mem0のみを画面に表示しようとしています。
いずれは用意したすべての種類のビットマップをhdc_mem0に読み込み、hdc_mem0のみ画面に表示させることによってチラつきを抑えようと考えています)

case WM_CREATE:

 hdc = GetDC(hWnd);

 hBmp0 = LoadBitmap(hInst, TEXT("MYBMP0"));
 GetObject(hBmp0, (int)sizeof(BITMAP), &bmp_info0);
 hdc_mem0 = CreateCompatibleDC(hdc);
 SelectObject(hdc_mem0, hBmp0);

 hBmp1 = LoadBitmap(hInst, TEXT("MYBMP1"));
 GetObject(hBmp1, (int)sizeof(BITMAP), &bmp_info1);
 hdc_mem1 = CreateCompatibleDC(hdc);
 SelectObject(hdc_mem1, hBmp1);

 DeleteObject(hBmp0);
 DeleteObject(hBmp1);

 ReleaseDC(hWnd, hdc);

 break;

case WM_PAINT:

 hdc = BeginPaint(hWnd, &ps);

 BitBlt(hdc_mem0, 0, 0, bmp_info1.bmWidth, bmp_info1.bmHeight, hdc_mem1, 0, 0, SRCCOPY);
 BitBlt(hdc, 0, 0, bmp_info0.bmWidth, bmp_info0.bmHeight, hdc_mem0, 0, 0, SRCCOPY);

 EndPaint(hWnd, &ps);

 break;

case WM_DESTROY:
 DeleteDC(hdc_mem0);
 DeleteDC(hdc_mem1);
 PostQuitMessage(0);
 break;

A 回答 (2件)

ちらつきが発生する原因は、おそらくですが背景の消去を行っているためではないかと思います。


InvalidateRect() の bErase パラメータに TRUE を指定していませんか?


蛇足かもしれませんが、ちらつきがなぜ発生するかというと、画面に表示するためのスクリーンのDBに対して、異なる内容の描画が複数回行われるためです。
たとえばなにかグラフのような物を描画するとした場合、「背景消去」→「枠描画」→「グリッド線描画」→「グラフ線描画」などの複数ステップで描画内容を構築すると思いますが、この処理の途中が画面上で目に見えるのがちらつきになります。
毎回、1回のBitBltだけを行って全面を上書き描画だけしていればちらつきは防げます。
ですので、描画画像とサイズが固定だとすれば、背景消去無しでこの例でいうhdc_mem1を直接Bltするだけでも事足ります。


ダブルバッファを利用する目的は、No.1にてmyuki1232 さんがすでに回答されている通りですが、WM_PAINの処理で1度だけBitBltを行うためです。
通常、たとえばユーザ操作などによって描画の内容が変化する場合にメモリDCへの描画を行ってInvalidateRect()を行い、
WM_PAINTでは描画済みのメモリDC内容をスクリーンDC(BeginPaintのDC)への転送のみを行います。
これにより、
・描画処理は必要な場合にメモリDCへ行うだけとなり、必要最低限の回数で済む。
・メモリDCからスクリーンDCへ転送するだけで済むので、WM_PAINTが高速になる。
・複数ステップの描画を画面上に現れないメモリDC上で済ませておくので(スクリーンへは上書き転送だけなので)ちらつきが抑止できる。
ということになるわけです。


さらに蛇足で、この質問の件とはあまり関係しないとは思いますが、ゲームや動画表示と言ったような高速で描画内容が変化する必要のあるアプリの場合には、このままの手法ではうまくいきませんし「ティアリング」といった別の問題も生じてきます。
それらについては、また必要となったときに調べてみてください。
    • good
    • 0

気になった点としては、


> hdc = BeginPaint(hWnd, &ps);
>
> BitBlt(hdc_mem0, 0, 0, bmp_info1.bmWidth, bmp_info1.bmHeight, hdc_mem1, 0, 0, SRC
> COPY);
> BitBlt(hdc, 0, 0, bmp_info0.bmWidth, bmp_info0.bmHeight, hdc_mem0, 0, 0, SRCCOPY)
> ;
>
> EndPaint(hWnd, &ps);
BeginPaint と EndPaint の間には、1回の BitBlt 以外の処理を入れてはいけません。
BeginPaint と EndPaint の間の時間(できれば、WM_PAINT の応答時間全体)を短くするのがこの手法の目的だからです。

上のコードで言えば、1つ目の BitBlt(hdc_mem0, ...) は BeginPaint の後でやる必要がないので、前に移動すれば多少良くなるかもしれません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報