前回の記事でちらつきを防止するための[ダブル・バッファリングの方法(1)]を紹介しました。
今回の記事では、DIBセクションという方法で[ダブル・バッファリング]を構築します。
こちらの利点は、DIBセクションで作成するため、オフスクリーンをピクセル単位で操作できます。
通常ピクセル単位で描画するには SetPixel、SetPixelV 関数を利用します。
しかし、この関数を多用して図形を描画すると極端に処理速度が遅くなります。
そこで DWORD 型の配列をDIBセクションで用意して、その配列に色情報を独自に書き込むことができます。
この方法なら直接ピクセル情報を書き換えてるので、高速で独自の図形を描画できます。
このDIBセクションを使って[ダブル・バッファリング]を構築すると、きめ細かい処理ができて便利です。
特にピクセル単位での描画をしない場合は、前回の記事で紹介した[ダブル・バッファリングの方法(1)]を利用して下さい。
個人的にはピクセル単位での描画が欲しいので、[ダブル・バッファリング]は今回の方法で構築します。
それでは具体的なプロシージャの記述を紹介します。
サンプル
// break付きのキーワード #define CASE break;case #define DEFAULT break;default // オフスクリーンの画面サイズ #define MAX_WIDTH (640) #define MAX_HEIGHT (480) // ウインドウ・プロシージャの関数 LRESULT CALLBACK mainWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static BITMAPINFO bmpInfo; // ビットマップ情報 static LPDWORD lpPixel; // ピクセル配列 static HBITMAP hBitmap; // ビットマップ static HDC hMemDC; // オフスクリーン static UINT saveX; static UINT saveY; switch ( uMsg ){ CASE WM_CREATE: { HDC hDC; // DIB構造体の初期化 bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth = +MAX_WIDTH; bmpInfo.bmiHeader.biHeight = -MAX_HEIGHT; // マイナス値で上下逆転の座標 bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = 32; bmpInfo.bmiHeader.biCompression = BI_RGB; // DIBセクションの作成 hDC = GetDC( hWnd ); hMemDC = CreateCompatibleDC( hDC ); hBitmap = CreateDIBSection( NULL, &bmpInfo, DIB_RGB_COLORS, (LPVOID*)&lpPixel, NULL, 0 ); SelectObject( hMemDC, hBitmap ); SelectObject( hMemDC, GetStockObject(DC_PEN) ); SelectObject( hMemDC, GetStockObject(DC_BRUSH) ); ReleaseDC( hWnd, hDC ); } CASE WM_CLOSE: // DIBセクションの破棄 DeleteDC( hMemDC ); DeleteObject( hBitmap ); DestroyWindow( hWnd ); CASE WM_DESTROY: PostQuitMessage( 0 ); CASE WM_PAINT: { PAINTSTRUCT ps; HDC hDC; // DIBセクションの描画 hDC = BeginPaint( hWnd, &ps ); BitBlt( hDC, 0, 0, MAX_WIDTH, MAX_HEIGHT, hMemDC, 0, 0, SRCCOPY ); EndPaint( hWnd, &ps ); } CASE WM_ERASEBKGND: // 何も処理しない⇒塗り潰した return 1; CASE WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: { UINT cx = (SHORT)LOWORD(lParam); UINT cy = (SHORT)HIWORD(lParam); if ( GetKeyState(VK_SHIFT) < 0 ){ cx = saveX += 16; cy = saveY += 16; } SetDCPenColor( hMemDC, RGB(0xFF,0xFF,0x00) ); SetDCBrushColor( hMemDC, RGB(0x00,0x00,0xFF) ); Rectangle( hMemDC, cx, cy, (cx + 16*5), (cy + 16*3) ); // ピクセル単位で描画 for ( UINT no = 0 ; no < (16 * 3) ; no++ ){ lpPixel[ MAX_WIDTH * (cy + no) + (cx + no) ] = 0xFFCC33; // 橙色 } InvalidateRect( hWnd, NULL, FALSE ); } CASE WM_RBUTTONUP: saveX = 0; saveY = 0; PatBlt( hMemDC, 0, 0, MAX_WIDTH, MAX_HEIGHT, BLACKNESS ); InvalidateRect( hWnd, NULL, FALSE ); DEFAULT:return DefWindowProc( hWnd, uMsg, wParam, lParam ); } return 0; }
※コメント投稿者のブログIDはブログ作成者のみに通知されます