イメージリスト
イメージリストは、複数の画像(ビットマップ、アイコン、カーソル)を保存、管理するための機能です。
ツールバーでは、ボタン画像をツールバー自体に登録しましたが、イメージリストに登録してそこから画像を指定することもできます。
その他に画像のマスクという機能を使用することもできます。
イメージリストはコモンコントロールから使用される機能です。
コモンコントロールの使用についてはツールバー#コモンコントロールを参照してください。
(イメージリスト自体はコモンコントロールの初期化を行わなくても動作します)
イメージリストの使用
イメージリストの作成
イメージリストの作成はImageList_Create
関数を使用します。
- HIMAGELIST ImageList_Create(
int cx,
int cy,
UINT flags,
int cInitial,
int cGrow
); - 横幅cx、縦幅cyのサイズのイメージリストを作成し、イメージリストハンドルを返す。
失敗した場合はNULLを返す。
イメージリストは全て同じサイズの画像を保持します。
そのサイズは引数cx
とcy
で指定します。
flags
は作成するイメージリストの種類を以下の定数の組み合わせで設定します。
ただし名前に「ILC_COLOR」を含む定数同士は同時に指定できません。
定数 | 説明 |
---|---|
ILC_COLOR | デフォルトの設定 通常は ILC_COLOR4 が使用される古いディスプレイでは ILC_COLORDDB が使用される |
ILC_COLOR4 | 4ビットDIB (16色) |
ILC_COLOR8 | 8ビットDIB (256色) |
ILC_COLOR16 | 16ビットDIB (65536色) |
ILC_COLOR24 | 24ビットDIB (フルカラー) |
ILC_COLOR32 | 32ビットDIB (トゥルーカラー) |
ILC_COLORDDB | デバイス依存ビットマップ (DDB) |
ILC_MASK | 画像マスクを使用する マスクを使用する場合、画像は2つのビットマップを登録し、うち一つはもう一方のビットマップを表示する領域を指定するために使用される |
ILC_MIRROR | プロセスがミラーリングされている場合、アイコンをミラーリング(左右反転)する |
ILC_PERITEMMIRROR | ILC_MIRROR フラグでミラーリングするとき、画像全体ではなく項目毎にミラーリングする |
ILC_ORIGINALSIZE | 設定よりも小さなサイズの画像を受け入れ、元のサイズを適用する Windows Vista以降 |
cInitial
はイメージリストが持つ画像の数の初期値です。
cGrow
は、イメージリストが確保している画像の格納可能数が足りなくなったときに、拡張される画像の数を指定します。
0を指定しても必要な数は確保されます。
戻り値はHIMAGELIST型で、これはイメージリストのハンドルです。
失敗した場合はNULL
が返されます。
DIBとはビットマップの形式のひとつで「デバイス独立ビットマップ」というものです。
(Device Independent Bitmap)
デバイス(機器のこと)に依存しないビットマップという意味で、色情報をデータ内に持っていてどのデバイスでも適切な色表現が可能です。
これは通常のビットマップファイル(.bmpファイル)で使用される形式です。
これに対してDDBという形式は「デバイス依存ビットマップ」というものです。
(Device Dependent Bitmap)
これはデータ内に色情報を持っておらず、デバイスが持つ色情報を元に描画を行います。
あるデバイス用に作成されたDDBは、他のデバイスでは表示がおかしくなる可能性があります。
イメージの追加
イメージリストに画像を追加するにはImageList_Add
関数を使用します。
- int ImageList_Add(
HIMAGELIST himl,
HBITMAP hbmImage,
HBITMAP hbmMask
); - イメージリストhimlにビットマップhbmImageを追加する。
マスクを使用する場合はhbmMaskに指定する。
戻り値は追加したイメージの先頭のインデックス。
失敗した場合は-1を返す。
himl
はイメージリストハンドルを指定します。
hbmImage
はビットマップハンドルを指定します。
ビットマップの数はビットマップの幅から計算されます。
例えばイメージリストの幅(cx
)に100を指定して作成した場合、幅が200のビットマップを追加すると画像を2枚追加することになります。
hbmMask
はマスクとして使用するビットマップのハンドルを指定します。
マスクを使用しない場合はNULL
を指定します。
イメージリストへの画像の追加はコピー処理が行われます。
元の画像は破棄しても問題ありません。
アイコンの追加
イメージリストはビットマップのほか、アイコンやカーソルなども追加することができます。
アイコン、カーソルの追加はImageList_AddIcon
マクロを使用します。
- void ImageList_AddIcon(
himl,
hicon
); - イメージリストhimlにアイコン(またはカーソル)hiconを追加する。
イメージリストにマスク(ILC_MASK
フラグ)を設定している場合はマスクも同時にコピーされます。
イメージリストの描画
イメージリストに追加した画像はImageList_Draw
で描画することができます。
- BOOL ImageList_Draw(
HIMAGELIST himl,
int i,
HDC hdcDst,
int x,
int y,
UINT fStyle
); - イメージリストhimlの画像インデックスiを、デバイスコンテキストhdcDstの座標x,yに、描画フラグfStyleを適用して描画する。
成功した場合は0以外を、失敗した場合は0を返す。
himl
はイメージリストハンドルです。
i
はイメージリストが保存する画像のインデックスです。
(先頭は0)
hdcDst
は描画先となるデバイスコンテキストハンドルです。
x
、y
は画像を描画する座標です。
fStyle
は描画スタイルを以下の定数で指定します。
定数 | 説明 |
---|---|
ILD_BLEND ILD_SELECTED |
ILD_BLEND50 と同じ。 |
ILD_FOCUS | ILD_BLEND25 と同じ。 |
ILD_BLEND25 | システムハイライトカラーと25%ブレンドして描画する。 画像マスクを使用しない場合は効果がない。 |
ILD_BLEND50 | システムハイライトカラーと50%ブレンドして描画する。 画像マスクを使用しない場合は効果がない。 |
ILD_IMAGE | オーバーレイの描画にマスクを必要としない場合、このフラグを設定する。ImageList_DrawEx 関数はマスクを無視して画像を描画する。 |
ILD_MASK | マスクを描画する。 |
ILD_NORMAL | イメージリストの背景色を使用して画像を描画する。 背景色が CLR_NONE の場合はマスクを使用して透過して描画する。 |
ILD_TRANSPARENT | 背景色に関係なくマスクを使用して画像を透過して描画する。 イメージリストにマスクが含まれない場合は効果がない。 |
ImageList_DrawEx関数
画像の描画はImageList_DrawEx
関数を使用することもできます。
- BOOL ImageList_DrawEx(
HIMAGELIST himl,
int i,
HDC hdcDst,
int x,
int y,
int dx,
int dy,
COLORREF rgbBk,
COLORREF rgbFg,
UINT fStyle
); - イメージリストhimlの画像インデックスiを、デバイスコンテキストhdcDstに、座標x,y、サイズdx,dy、背景色rgbBk、前景色rgbBk、描画フラグfStyleを適用して描画する。
成功した場合は0以外を、失敗した場合は0を返す。
座標の指定までの引数、およびfStyle
はImageList_Draw
関数と同じです。
dx
は画像の横幅、dy
は縦幅の指定です。
拡大/縮小されるわけではなく、画像上の描画する範囲の指定です。
0を指定すると画像の横幅、縦幅がそのまま使用されます。
rgbBk
は画像の背景色の指定です。
マスクを使用する時、透過される領域を指定の色で塗りつぶします。
(マスクを使用しない場合は効果はありません)
RGB
マクロで生成したCOLORREF型の値を指定できるほか、以下の定数も指定できます。
定数 | 説明 |
---|---|
CLR_NONE | 背景色を使用しない (透明) |
CLR_DEFAULT | イメージリストに設定されている背景色を使用する |
rgbFg
は画像の前景色です。
ブレンド(ILD_BLEND25
、ILD_BLEND50
)を使用する時の色を指定します。
RGB
マクロで生成したCOLORREF型の値を指定できるほか、以下の定数も指定できます。
定数 | 説明 |
---|---|
CLR_NONE | デバイスコンテキストの背景色とブレンドする |
CLR_DEFAULT | システムのハイライト色とブレンドする |
イメージリストの破棄
イメージリストは不要になったらImageList_Destroy
関数で破棄します。
- BOOL ImageList_Destroy(
HIMAGELIST himl
); - イメージリストhimlを破棄する。
成功した場合は0以外を、失敗した場合は0を返す。
この関数は難しいことはないでしょう。
サンプルコード
ここまでのサンプルコードです。
画像は以下のビットマップを「IDB_BITMAP1」というIDでリソースに追加しています。
(8bitカラー、300 × 100)
#pragma comment(lib, "Comctl32.lib")
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
//ウィンドウの生成等は省略
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HIMAGELIST hImageList;
HBITMAP hBmp;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
//イメージリストの作成
hImageList = ImageList_Create(
100, 100, //サイズ
ILC_COLOR8, //8ビットカラー
3, //画像3枚分の保存領域の確保
0);
//画像の追加
hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
ImageList_Add(
hImageList,
hBmp,
NULL);
//ロードした画像の破棄
DeleteObject(hBmp);
break;
case WM_PAINT: //描画
hdc = BeginPaint(hWnd, &ps);
//イメージリストから描画
ImageList_Draw(hImageList, 0, hdc, 0, 0, ILD_NORMAL);
ImageList_Draw(hImageList, 1, hdc, 100, 50, ILD_NORMAL);
ImageList_Draw(hImageList, 2, hdc, 200, 100, ILD_NORMAL);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY: //ウィンドウの破棄
//イメージリストの破棄
ImageList_Destroy(hImageList);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
実行結果です。
クライアント領域の背景色はグレー(COLOR_APPWORKSPACE
)にしています。
追加した画像は一枚だけですが、イメージリスト作成時に指定した画像一枚当たりの横幅は「100」で、追加した画像の横幅は「300」です。
そのため、リスト上では三枚の画像が存在することになります。
サンプルコードではそれぞれ別の画像として描画できることを示すために描画位置を適当にズラしています。
マスクの使用
マスクを使用すると、画像の不要な部分を透過することができます。
マスクを使用するにはイメージリストの作成時に、引数flags
にILC_MASK
フラグを追加します。
HIMAGELIST hImageList = ImageList_Create(
100, 100,
ILC_COLOR24 | ILC_MASK, //マスクフラグの追加
3,
0);
マスクを使用する場合、描画するビットマップとは別に、描画したい領域を黒色で塗りつぶしたビットマップをもう一枚用意します。
ここでは先ほどの画像に加えて以下の画像を「IDB_BITMAP2」というリソースIDで読み込みます。
このビットマップハンドルをImageList_Add
関数の第三引数に指定します。
#pragma comment(lib, "Comctl32.lib")
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
//ウィンドウの生成等は省略
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HIMAGELIST hImageList;
HBITMAP hBmp1, hBmp2;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
//イメージリストの作成
hImageList = ImageList_Create(
100, 100,
ILC_COLOR8 | ILC_MASK,
3,
0);
//画像の追加
hBmp1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
hBmp2 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP2));
ImageList_Add(
hImageList,
hBmp1,
hBmp2);
//ロードした画像の破棄
DeleteObject(hBmp1);
DeleteObject(hBmp2);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//イメージリストから描画
ImageList_Draw(hImageList, 0, hdc, 0, 0, ILD_NORMAL);
ImageList_Draw(hImageList, 1, hdc, 100, 50, ILD_NORMAL);
ImageList_Draw(hImageList, 2, hdc, 200, 100, ILD_NORMAL);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY: //ウィンドウの破棄
//イメージリストの破棄
ImageList_Destroy(hImageList);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
実行結果です。
マスク画像中の塗りつぶされた領域が描画され、それ以外の領域は透過されます。
ImageList_AddMasked関数
マスク用の画像を用意する方法は複雑な色を含む画像でも形状通りに切り抜くことが出来ます。
しかし今回のように単純な塗りの画像の場合はImageList_AddMasked
関数を使用すると便利です。
- int ImageList_AddMasked(
HIMAGELIST himl,
HBITMAP hbmImage,
COLORREF crMask
); - イメージリストhimlにビットマップhbmImageを追加する。
マスクとして使用する色はカラー情報crMaskで指定する。
これはImageList_Add
関数と同じくイメージリストに画像を追加しますが、第三引数がビットマップハンドルではなくCOLORREF型になっています。
(→文字色と背景色を参照)
ここに指定した色が透過されます。
hImageList = ImageList_Create(
100, 100,
ILC_COLOR8 | ILC_MASK,
3,
0);
//画像の追加
hBmp1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));
//hBmp2 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP2));
//ImageList_Add(
// hImageList,
// hBmp1,
// hBmp2);
ImageList_AddMasked(
hImageList,
hBmp1,
RGB(255, 255, 255));
//ロードした画像の破棄
DeleteObject(hBmp1);
//DeleteObject(hBmp2);
ただしこの関数は8bitカラー以下のビットマップに有効で、16bitカラー以上のビットマップには対応していません。
(と、Microsoftは説明しています)