第26章 ビットマップ画像の表示


今回は、ビットマップ画像の表示についてします。 少し面倒くさいのですが、ワンパターンなので覚えてしまえば どうということもありません。

ビットマップ表示手順 1.リソース・エジタでビットマップリソースを作る 2.BeginPaintとEndPaint関数で挟まれたところに・・ 3.LoadBitmap関数でビットマップリソースをロードする 4.必要があれば、GetObject関数でビットマップの情報を取得する 5.CreateCompatibleDC関数でビットマップイメージをメモリ内に準備する 6.SelectObject関数でビットマップオブジェクトを選択する 7.BitBltまたは、StrechBlt関数でビットマップイメージをデバイス環境に   コピーする 8.メモリデバイスコンテキストや、ビットマップの開放

と、まあこんな具合です。

HBITMAP LoadBitmap( HINSTANCE hInstance, // インスタンスハンドル LPCTSTR lpBitmapName // ビットマップリソースの名前 );

インスタンスハンドルの取得方法は、第19章で解説しています ので参考にしてください。

int GetObject( HGDIOBJ hgdiobj, // オブジェクトのハンドル int cbBuffer, // オブジェクト情報のバッファサイズ LPVOID lpvObject // オブジェクト情報バッファのアドレス );

ここではビットマップの情報を得るために使うので、 hgdiobjには、LoadBitmapで得たビットマップハンドルを使います。 オブジェクト情報は、ビットマップ構造体に格納します。 したがって2番目の引数はsizeof(BITMAP)ということになります。 3番目の引数は、ビットマップ構造体のアドレスを入れます。 ビットマップ構造体は、次のように定義されています。

typedef struct tagBITMAP { // bm LONG bmType; LONG bmWidth; LONG bmHeight; LONG bmWidthBytes; WORD bmPlanes; WORD bmBitsPixel; LPVOID bmBits; } BITMAP;

この章で必要なメンバは、bmWidth(ビットマップの幅)と bmHeight(ビットマップの高さ)くらいでしょう。後は知らなくても良いです。 気になる人はヘルプで調べてみてください。 なお16ビット版では上から4つまでのメンバはint型になっているので 注意してください。

HDC CreateCompatibleDC( HDC hdc // handle to memory device context );

戻り値としてメモリデバイスコンテキストハンドルを取得することができます。

HGDIOBJ SelectObject( HDC hdc, // handle of device context HGDIOBJ hgdiobj // handle of object );

この関数は第23章ですでに出てきました。 ここでは、第2引数はメモリデバイスコンテキストハンドルを使います。

BOOL BitBlt( HDC hdcDest, int nXDest, // 転送先X座標 int nYDest, // 転送先Y座標 int nWidth, // 転送先長方形の幅 int nHeight, // 高さ HDC hdcSrc, // 転送元デバイスコンテキストハンドル int nXSrc, // 転送先X座標 int nYSrc, // 転送先Y座標 DWORD dwRop // ラスターオペレーション );

これは、引数がいっぱいあって面倒そうですね。 でも、使い方は簡単です。例題を見ればわかると思います。 最後のラスターオペレーションについては、簡単に言うと 転写先とどのように合成するかということです。 単純にコピーするならSRCCOPYを使います。

BOOL StretchBlt( HDC hdcDest, // 転送先デバイスコンテキストハンドル int nXOriginDest, // 転送先X座標 int nYOriginDest, // 転送先Y座標 int nWidthDest, // 転送先長方形の幅 int nHeightDest, // 転送先長方形の高さ HDC hdcSrc, // 転送元デバイスコンテキストハンドル int nXOriginSrc, // 転送元X座標 int nYOriginSrc, // 転送元Y座標 int nWidthSrc, // 転送元ビットマップの幅 int nHeightSrc, // 高さ DWORD dwRop // ラスターオペレーション );

転送先長方形の幅、高さをオリジナルより大きくしたり 小さくしたりすることでビットマップの拡大・縮小が できます。

BOOL DeleteDC( HDC hdc );

この関数によりデバイスコンテキストハンドルを開放します。 これに似たものに

int ReleaseDC( HWND hWnd, HDC hDC );

というのがあります。 GetDC関数で取得したデバイスコンテキストハンドルは DeleteDCで削除してはいけません。ReleaseDCで開放します。 GetDC関数については、まだやっていません。 前置きが長くなってしまいました。例題を見てみましょう。

// grph04.cpp #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void ShowMyBMP(HWND, HDC); char szClassNme[] = "grph04"; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow) { HWND hWnd; MSG lpMsg; WNDCLASS myProg; if (!hPreInst) { myProg.style =CS_HREDRAW | CS_VREDRAW; myProg.lpfnWndProc =WndProc; myProg.cbClsExtra =0; myProg.cbWndExtra =0; myProg.hInstance =hInstance; myProg.hIcon =NULL; myProg.hCursor =LoadCursor(NULL, IDC_ARROW); myProg.hbrBackground =GetStockObject(WHITE_BRUSH); myProg.lpszMenuName =NULL; myProg.lpszClassName =szClassNme; if (!RegisterClass(&myProg)) return FALSE; } hWnd = CreateWindow(szClassNme, "猫でもわかるプログラミング", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while (GetMessage(&lpMsg, NULL, 0, 0)) { TranslateMessage(&lpMsg); DispatchMessage(&lpMsg); } return (lpMsg.wParam); } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (msg) { case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); ShowMyBMP(hWnd, hdc); TextOut(hdc, 50, 50, "猫でもわかるプログラミング", 26); SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, RGB(255, 0, 0)); TextOut(hdc, 50, 100, "粂井康孝 制作・著作", 19); EndPaint(hWnd, &ps); break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return (0L); } void ShowMyBMP(HWND hWnd, HDC hdc) { HDC hmdc; HBITMAP hBitmap; BITMAP bmp; HINSTANCE hInst; int BMP_W, BMP_H; hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); hBitmap = LoadBitmap(hInst, "MYBMP"); GetObject(hBitmap, sizeof(BITMAP), &bmp); BMP_W = (int)bmp.bmWidth; BMP_H = (int)bmp.bmHeight; hmdc = CreateCompatibleDC(hdc); SelectObject(hmdc, hBitmap); BitBlt(hdc, 0, 0, BMP_W, BMP_H, hmdc, 0, 0, SRCCOPY); StretchBlt(hdc, 0, BMP_H, BMP_W / 2, BMP_H / 2, hmdc, 0, 0, BMP_W, BMP_H, SRCCOPY); DeleteDC(hmdc); DeleteObject(hBitmap); return; }

リソース・スクリプトはどうなっているかというと

///////////////////////////////////////////////////////////////////////////// // // Bitmap // MYBMP BITMAP DISCARDABLE "my.bmp"

と、こんなに簡単です。 さて、このプログラムではビットマップを表示した後、 この上にテキストを表示するようにしています。 単純にTextOut関数を呼び出してテキストを表示すると テキストの下地がウィンドウの下地で塗りつぶされます。 これを防ぐには、

int SetBkMode( HDC hdc, int iBkMode );

を使います。2番目の引数をTRANSPARENTにします。 2番目の引数がOPAQUEですと、背景が現在の背景色で 塗りつぶされます。この関数を実行しないときは OPAQUEと同じことが起こります。 では、プログラムを実行してみましょう。


同じビットマップを上下に並べて表示しています。 下のビットマップは2分の1に縮小しています。 ビットマップ上にテキストを表示していますが 1列目と、2列目の違いに注意してください。



[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update Apr/30/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。