6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ウィンドウリサイズ時のちらつきを抑える

Last updated at Posted at 2012-11-24

#問題

case WM_CREATE:
 pImage = new Image(TEXT("大きめの画像ファイル.jpg"));
 break;

case WM_PAINT:
 PAINTSTRUCT ps;
 HDC hdc = BeginPaint(hwnd, &ps)

 Gdiplus::Graphics g(hdc);
 g->DrawImage(pImage, 0, 0);

 EndPaint(hdc);
 break;

として満足していたけれど、この処理だとウィンドウをリサイズして大きくしたときに
ものすごい勢いでちらついた。

これを直したい。

#対応

WM_ERASEBKGND の抑制

case WM_ERASEBKGND:
  return 1;

BeginPaint から WM_ERASEBKGND がSendMessage されて背景を消去しているらしいのでこれを抑制する。
非ゼロを返すと、抑制される。

case WM_PAINT:
 PAINTSTRUCT ps;
 HDC hdc = BeginPaint(hwnd, &ps)

 //------------------------------------------------------- ここから追加
 RECT rect;
 GetClientRect(hwnd, &rect);
  HBRUSH hbr = (HBRUSH)GetStockObject(GRAY_BRUSH);
 FillRect(hdc, hbr, 0, 0, width, height);
 //------------------------------------------------------- ここまで

 Gdiplus::Graphics g(hdc);
 g->DrawImage(pImage, 0, 0);

 EndPaint(hdc);
 break;

WM_ERASEBKGND で背景描かないようにしてしまったので、自分で実装する必要がある。

これは画像を扱うプログラムではもうおまじないレベルの必須だそうで、実装しておく。
が、これだけでは全然意味なかった。

##描画に、GDI+を使わないように変更

ためしに、同じ画像を GDI+ を使わないで表示するようにしてみたところ、全くちらつかない。
・・・わるいのは GDI+ だ

というわけで、GDI+は画像の読み込みだけにとどめ、画像の描画は GDI の BitBlt を利用するように変更する。

まず、読み込んだ画像を保存するHBITMAPを宣言。

 HDC hBackDC;
 HBITMAP hBackBmp;

つぎに、画像読み込み部分を修正。

case WM_CREATE:
 pImage = new Image(TEXT("大きめの画像ファイル.jpg"));
 {
 //------------------------------------------------------- ここから追加
  HDC hDC = GetDC(hwnd); // hWndはウインドウプロシージャのもの
  hBackDC = CreateCompatibleDC(hDC);
  hBackBmp = CreateCompatibleBitmap(hDC, pImage->GetWidth(), pImage->GetHeight());
  SelectObject(hBackDC, hBackBmp);
  Graphics g(hBackDC);
  g.DrawImage(pImage, 0, 0);
  ReleaseDC(hwnd, hDC);
 //------------------------------------------------------- ここまで
 }
 break;

最後に画像を描画する。

case WM_PAINT:
 PAINTSTRUCT ps;
 HDC hdc = BeginPaint(hwnd, &ps)

 RECT rect;
 GetClientRect(hwnd, &rect);
  HBRUSH hbr = (HBRUSH)GetStockObject(GRAY_BRUSH);
 FillRect(hdc, hbr, 0, 0, width, height);

 //------------------------------------------------------- ここを修正
 BitBlt(hDC, 0, 0, width, height, hBackDC, 0, 0, SRCCOPY);
 //------------------------------------------------------- ここまで

 EndPaint(hdc);
 break;

以上

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?