0

前書き:

ビットマップをウィンドウの背景として描画することに関して、純粋なWIN32で小さなプログラムをテストするために、C++でMS Visual Studio 2008でテストプロジェクトを作成することにしました。

問題:

ウィンドウには、灰色のブラシとビットマップ画像がクライアント領域に引き伸ばされている必要があります。

の私のコードでWM_PAINT、ビットマップなしでウィンドウの灰色のブラシをペイントしようとすると、すべてがうまくいくようです。

ビットマップを背景として配置しようとした場合も同様です。

しかし、これら 2 つを組み合わせると、ビットマップ画像が引き伸ばされ、ビットマップの背景が灰色になるため、次のようになります。

ビットマップ画像は「静止」しているように見えますが、灰色のブラシがウィンドウ全体に 1 秒間表示された後、完全に消えるため、引き伸ばされたビットマップのみが表示され、その後再び表示されます。

まるで上から下に向かって描かれているかのようで、まるでアプリケーションがそれを繰り返しているかのようです。

これは、プログラムを開始したときに表示される方法です。

関連情報:

このプログラムは、オプション File->New を選択し、オプションから Win32 プロジェクトを選択して作成されました。

Windowクラスは自動で設定され、以下のメンバーは以下のように設定されました。

   wcex.style = CS_HREDRAW | CS_VREDRAW;

   wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

ビットマップ ハンドルを格納する静的グローバル変数を追加しました。

   static HBITMAP bmp;

ウィザードによって作成されたウィンドウ プロシージャで、次のコードで初期化しました。

   case WM_CREATE:

        bmp = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1) );

        return 0;

        break;

ウィザードによって作成されたウィンドウ プロシージャに、WM_PAINT次のコードを使用してハンドラーを追加しました。

    case WM_PAINT:
     {

        hdc = BeginPaint(hWnd, &ps);

        RECT r;

        GetClientRect( hWnd, &r );

        // TODO: Add any drawing code here...

            // fill client area with gray brush, just to test

            FillRect( hdc, &r, (HBRUSH)GetStockObject( GRAY_BRUSH ) );

            // memory DC for double buffering

        HDC MemDC = CreateCompatibleDC( hdc );

            // select our bitmap into memory DC

        HBITMAP old = (HBITMAP)SelectObject( MemDC, bmp );

            // get bitmap's width and height so we can stretch it  

        BITMAP b;

        GetObject( bmp, sizeof(BITMAP), &b );

            // stretch our bitmap

        StretchBlt( hdc, 0, 0, r.right - r.left, r.bottom - r.top, 
             MemDC, 0, 0, b.bmWidth, b.bmHeight, SRCCOPY );

            // perform proper cleanup

        SelectObject( MemDC, old );

        DeleteDC(MemDC);


        EndPaint(hWnd, &ps);

     }
     return 0L;
     break;

次のように、ウィンドウのサイズが変更されたとき、または背景の消去が発生したときに、クライアント領域も無効にしました。

   case WM_ERASEBKGND:

        InvalidateRect( hWnd, NULL, TRUE );

        return 1L;
        break;

   case WM_SIZE:

        InvalidateRect( hWnd, NULL, TRUE );

        return 0L;

ビットマップは次のように破棄されます。

   case WM_DESTROY:

        DeleteObject( bmp );

        PostQuitMessage(0);
        break;

重要な注意点:

WM_SIZEとのハンドラーをコメントアウトしてもWM_ERASEBKGND、効果は引き続き発生します。

ダブルバッファリングの経験はあまりありませんが、これは簡単なことです。

間違いを見落としているだけなので、経験豊富で熟練した同僚に助けてもらいます。

追加のソース コードが必要な場合は、それを要求して投稿しますが、それまでは質問を簡潔にするために省略します。

4

1 に答える 1

3

電話InvalidateRectをかけないでくださいWM_ERASEBKGND。それは無限の一連のペイントサイクルを強制するだけです.

の仕事はWM_ERASEBKGND背景を描くことであり、それはあなたがすべきことのすべてです。WM_PAINTウィンドウ全体をペイントする場合は、背景をペイントする必要はありません。その場合、これはあなたのシナリオだと思いますが、 では何もしないでくださいWM_ERASEBKGND

于 2013-09-22T13:36:15.050 に答える