第70章 イメージリスト


突然ですが今回はイメージリストに付いてやります。 イメージリストとは、VC++のヘルプによると

「イメージリストとは、同じサイズのイメージの集合であり、 それぞれは、そのインデックスで参照することができる」

(筆者の訳なので間違いがあるかもしれないのであまり鵜呑みにしない ように。)
同じサイズのイメージを取り扱うときは便利そうな機能であることは 何となくわかりますね。実はタブコントロールのタブの部分に 画像を表示するときはイメージリストを使います。

また、イメージリストにはマスクと、非マスクというのがあります。 マスクとは何かというと背景を透明化したりするときに使います。 では、さっそくイメージリストの作り方の手順を示します。

1.コモンコントロール使用のための準備 2.ImageList_Create関数でイメージリストを作る 3.実際のビットマップをLoadBitmap関数でロードする 4.ImageList_Add関数でイメージを追加する 5.ImageList_Draw関数でイメージを描画します。 6.不要になったらImageList_Destroy関数で破棄する

と、まあこんなところです。マスクを使うときは 上の3番の作業で普通のイメージとマスクイメージの2つを ロードします。しかし、この方法だと自分でマスクイメージを 作らねばならず面倒くさいです。自動的にマスクイメージを 作ってもらうには、ImageList_AddMasked関数を使うのが便利です。

mybmp1.bmpmybmp2.bmp
まずは、32*32のビットマップを2つ用意します。 (というか、リソースエジタで作ります。) これらを"MYBMP1", "MYBMP2"という名前のビットマップリソースにします。

これをイメージリストに加えて、イメージリストから クライアント領域に表示しようとするものです。

イメージの白色部分を透過させて表示したのが左の2つです。
右側のイメージは従来の方法で表示したものです。 背景が白色だと違いがわからないのでウィンドウの背景は わざとに暗くしています。

それでは、さっそくここで使用する関数やら、マクロについて開設します。

HIMAGELIST ImageList_Create( int cx, int cy, UINT flags, int cInitial, int cGrow );

cxはイメージの幅、cyは高さを指定します。

flagsは、イメージリストの タイプを表します。ILC_COLORがデフォルトです。さらに、マスクを使用するときは ILC_MASKを加えます。

cInitialは、リスト中のイメージ数の初期値です。

cGrowは、新しいイメージのための領域を作るためにシステムがリストを リサイズするためのイメージの数。

戻り値はイメージリストハンドル(HIMAGELIST)です。

int ImageList_Add( HIMAGELIST himl, // イメージリストハンドル HBITMAP hbmImage, // handle to the bitmap containing the image HBITMAP hbmMask // handle to the bitmap containing the mask );

himlは、イメージリストハンドル

hbmImageは、ビットマップイメージハンドル。

hbmMaskは、マスクイメージのビットマップハンドル。

成功したときは、最初の新しいイメージのインデックス、 失敗したときは−1を返します。

int ImageList_AddMasked( HIMAGELIST himl, // イメージリストハンドル HBITMAP hbmImage, // ビットマップハンドル COLORREF crMask // マスクを作るときに使われる色 );

これは、ビットマップイメージを用意するだけで マスクを自動的に作ってくれる関数です。

BOOL ImageList_Draw( HIMAGELIST himl, // イメージリストハンドル int i, // イメージのインデックス HDC hdcDst, // デバイスコンテキストハンドル int x, // X座標 int y, // Y座標 UINT fStyle // 描画スタイル );

描画スタイルはIDL_NORMALが標準のスタイル。IDL_MASKがマスクを 描画します。

BOOL ImageList_Destroy( HIMAGELIST himl );

不要になったイメージリストを破棄します。 成功したときは0以外の値、失敗したときは0を返します。

では、さっそくサンプルを見てみましょう。

// ilist01.rcの一部 // 自分で作る人はwindows.hと自前のヘッダーファイルを // インクルードしてください ///////////////////////////////////////////////////////////////////////////// // // Bitmap // MYBMP1 BITMAP DISCARDABLE "mybmp1.bmp" MYBMP2 BITMAP DISCARDABLE "mybmp2.bmp"

これは、別にどうということもありません。

// ilist01.cpp #define STRICT #include <windows.h> #include <commctrl.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "ilist01"; //ウィンドウクラス HINSTANCE hInst; HIMAGELIST hImg; int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!hPrevInst) { if (!InitApp(hCurInst)) return FALSE; } if (!InitInstance(hCurInst, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }

これは、いつもとたいして変わりません。

//ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; //インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); wc.lpszMenuName = NULL; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; return (RegisterClass(&wc)); }

hbrBackgroundメンバがいつもと違うことに注意してください。 最初にも書いたように背景が白では違いがわかりにくいためにGRAY_BRUSH にしてあります。

//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; hWnd = CreateWindow(szClassName, "猫でもわかるイメージリスト", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInstance, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

親ウィンドウはいつもと同じです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; HBITMAP hBmp; PAINTSTRUCT ps; HDC hdc, hdc_mem; switch (msg) { case WM_CREATE: InitCommonControls(); hImg = ImageList_Create(32, 32, ILC_COLOR | ILC_MASK, 2, 0); hBmp = LoadBitmap(hInst, "MYBMP1"); ImageList_AddMasked(hImg, hBmp, RGB(255,255,255)); DeleteObject(hBmp); hBmp = LoadBitmap(hInst, "MYBMP2"); ImageList_AddMasked(hImg, hBmp, RGB(255, 255, 255)); DeleteObject(hBmp); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); ImageList_Draw(hImg, 0, hdc, 0, 0, ILD_NORMAL); ImageList_Draw(hImg, 1, hdc, 40, 0, ILD_NORMAL); hBmp = LoadBitmap(hInst, "MYBMP2"); hdc_mem = CreateCompatibleDC(hdc); SelectObject(hdc_mem, hBmp); BitBlt(hdc, 80, 0, 32, 32, hdc_mem, 0, 0, SRCCOPY); DeleteDC(hdc_mem); DeleteObject(hBmp); EndPaint(hWnd, &ps); break; case WM_CLOSE: id = MessageBox(hWnd, (LPCSTR)"終了してもよいですか", (LPCSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: if(ImageList_Destroy(hImg) == TRUE) MessageBox(NULL, "イメージリスト破棄成功", "成功", MB_OK); PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; }

ImageList_AddMaskedの最後の引数を見てください。RGB(255, 255, 255) (白)に設定してあります。白色の部分が透明化されるというわけです。 イメージリストを作ってしまえば、イメージの描画は簡単です。 最後にImageList_Destroyを忘れないでください。 このプログラムでは明示的にイメージリストの破棄に成功したときは その旨メッセージボックスを出すようにしてみました。 次章では、イメージリストを利用してタブコントロールに イメージを付けてみます。


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

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