ビットマップの表示


メモリデバイスコンテキスト

ビットマップを操作する時、通常はビット列をメモリに展開する
この、擬似的にメモリに描かれたビットマップに私たちは絵を描いたりすることができる

ディスプレイなどの物理的なデバイスではなく
メモリの論理的なデバイスを メモリデバイスコンテキスト と呼びます
物理的なデバイスコンテキストと違い、操作しても描画しません

メモリデバイスコンテキストは、それを描画するデバイスと互換である必要があります
そのため、メモリデバイスコンテキストの作成には
物理デバイスのデバイスコンテキストのハンドルが必要となります
メモリデバイスコンテキストを作成するには CreateCompatibleDC() 関数を使用します

HDC CreateCompatibleDC(HDC hdc);

hdc には、互換をとるデバイスコンテキストのハンドルを指定します
これに NULL を指定するとディスプレイと互換性を取ります
成功すればメモリデバイスコンテキストのハンドル、失敗すれば NULL が返ります
このハンドルは DeleteDC() 関数でハンドルを削除する必要があります

これで、メモリデバイスコンテキストのハンドルを取得できました
しかし、初期状態では幅1、高さ1、モノクロの1ビットしか持ち合わせていません
これを使うには ビットマップオブジェクト を設定する必要があります

そのために、まずリソーススクリプトからビットマップファイルをモジュールに埋めこみます
この時、フォーマットは Windows で表示できるビットマップならなんでも構いません
ビットマップを埋めこむには BITMAP 文を使います

nameID BITMAP filename

nameID は、このビットマップの ID
filename は、挿入するビットマップファイルの名前を指定します
この仕様は、ICON 文と同じなのでとくに難しくありませんね

さて、次にプログラムは LoadBitmap() 関数でビットマップのハンドルを取得します
この関数は、常にディスプレイと互換性を持ったハンドルを返してくれます

HBITMAP LoadBitmap(HINSTANCE hInstance , LPCTSTR lpBitmapName);

hInstance はビットマップが入っているモジュールのハンドル
lpBitmapName は、ビットマップの ID を指定します
関数が成功するとビットマップのハンドル、失敗すると NULL が返ります
HBITMAP 型というのがビットマップハンドルの型です

このビットマップハンドルはGDI オブジェクトの一つ です
つまり、ペンやブラシ、フォントといったものの仲間であると考えられます
メモリデバイスコンテキストに対し、このビットマップハンドルを設定すると
メモリデバイスコンテキストの内容はそのビットマップとなります

メモリデバイスコンテキストにビットマップのハンドルを設定するには
他の設定同様に SelectObject() 関数で設定することができます
ただし、ビットマップハンドルが設定できるのはメモリデバイスコンテキストだけです

これで、メモリデバイスコンテキストにビットマップを展開することができました
メモリデバイスコンテキストはメモリの中にだけ存在する画像です
これを実際にデバイスに表示するには、BitBlt() などでビットブロックを転送します
//リソーススクリプト
KITTY BITMAP "test.bmp"
#include <windows.h>

LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc , hBuffer;
	PAINTSTRUCT ps;
	static HBITMAP hBitmap;

	switch (msg) {
	case WM_DESTROY:
		DeleteObject(hBitmap);
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		hBitmap = LoadBitmap(
			((LPCREATESTRUCT)lp)->hInstance ,
			TEXT("KITTY")
		);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd , &ps);
		hBuffer = CreateCompatibleDC(hdc);
		SelectObject(hBuffer , hBitmap);

		BitBlt(hdc , 0 , 0 , 400 , 120 , hBuffer , 70 , 80 , SRCCOPY);

		DeleteDC(hBuffer);
		EndPaint(hwnd , &ps);
		return 0;
	}
	return DefWindowProc(hwnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow ) {
	HWND hwnd;
	MSG msg;
	WNDCLASS winc;

	winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return -1;

	hwnd = CreateWindow(
			TEXT("KITTY") , TEXT("Kitty on your lap") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			NULL , NULL ,
			hInstance , NULL
	);

	if (hwnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}


ビットブロック転送の範囲は、画像に合わせて行ってください
この場合、test.bmp というビットマップリソースを読みこんで表示しています
グラフィックシステムの最大の魅力の一つである画像を表示できましたね!

ビットマップを WM_PAINT 毎に読みこみ、破棄を繰り返すと効率が悪いので
最後までビットマップのハンドルを使う場合、一般的には
このように WM_CREATE で読み込み、WM_DESTROY で解放します


CreateCompatibleDC()

HDC CreateCompatibleDC(HDC hdc);

指定されたデバイスと互換性のあるメモリデバイスコンテキストを作成します

hdc - デバイスコンテキストのハンドル。画面と互換をとる場合は NULL でも構いません

戻り値 - メモリデバイスコンテキストのハンドル。失敗すると NULL

LoadBitmap()

HBITMAP LoadBitmap(HINSTANCE hInstance , LPCTSTR lpBitmapName);

指定したモジュールからビットマップリソースを読みこみます

hInstance - ビットマップリソースが格納されているモジュールのインスタンスを指定します
lpBitmapName - ロードするビットマップリソースの名前を指定します

戻り値 - ビットマップのハンドル。失敗すると NULL

hInstance を NULL にすると、次の定数のいずれかを lpBitmapName に指定できます
これは、Windows がコントロールに用意しているビットマップです
これを使う場合 WINDOWS.H をインクルードする前に OEMRESOURCE 定数を定義してください

定数定数
OBM_BTNCORNERS OBM_OLD_RESTORE
OBM_BTSIZE OBM_OLD_RGARROW
OBM_CHECK OBM_OLD_UPARROW
OBM_CHECKBOXES OBM_OLD_ZOOM
OBM_CLOSE OBM_REDUCE
OBM_COMBO OBM_REDUCED
OBM_DNARROW OBM_RESTORE
OBM_DNARROWD OBM_RESTORED
OBM_DNARROWI OBM_RGARROW
OBM_LFARROW OBM_RGARROWD
OBM_LFARROWD OBM_RGARROWI
OBM_LFARROWI OBM_SIZE
OBM_MNARROW OBM_UPARROW
OBM_OLD_CLOSE OBM_UPARROWD
OBM_OLD_DNARROW OBM_UPARROWI
OBM_OLD_LFARROW OBM_ZOOM
OBM_OLD_REDUCE OBM_ZOOMD



前のページへ戻る次のページへ