概要

イメージリストは同じサイズの画像を複数扱うコモンコントロールである。 リストビュー・タブコントロール・ツリービューでアイコンを表示するときに組み合わせるときにも用いられる。 このサンプルは、国旗をイメージリストで作成し表示します。左からアイルランド、アメリカ、日本の順です。 アイルランドとアメリカはリソースに組み込んだBMPファイル、日本はプログラム上でメモリ上に円を描いてイメージリストに登録しています。

テスト環境

コンパイラ

Visual C++ 2008 Standard 32/64bit
Visual C++ 2013 Express 32/64bit

実行環境

Windows 8.1 Enterprise 64bit
Windows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit

プログラムソースの概要

_tWinMain関数

Windowsから最初に_tWinMain関数が呼び出されます。 ウィンドウを作成する場合は、RegisterClass APIによりウィンドウクラスを定義してからCreateWindow APIを呼び出しウィンドウを作成します。 Windowsは入力等のイベントが発生するとアプリケーションにメッセージを送付します。 メッセージはキューに保管されます。アプリケーションはメッセージを取り出し、該当ウィンドウにメッセージを配信します。 メッセージの取り出しから配信までループで処理を行いウィンドウから終了メッセージが届くと、ループを抜けるように記述します。 これらの一連の処理は、通常にCreateWindow APIの後に記述しこれをメッセージループと呼んでいます。 詳細は以下を参照してください。
メッセージループ

WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)ウィンドウプロシージャー

RegisterClass APIにより登録することによりWindowsから呼び出されます。
第2引数にメッセージの種類が格納されていますので、switchステートメントによりメッセージごとの処理を振り分けます。
自分で処理しないメッセージはDefWindowProc APIに渡せばWindowsが標準的な処理を行ってくれます。

case WM_CREATE:

ウィンドウの初期化時に呼び出されます。
ImageList_Create APIによりイメージリストを作成します。
GetDCによりウィンドウのデバイスコンテキストを取得します。
リソースからイメージリストに登録
アイルランド、アメリカの国旗はリソースに埋め込まれています。
LoadBitmap APIによりリソースからイメージを取得しビットマップに格納します。。 ImageList_AddMasked APIによりビットマップをイメージリストに登録します。
GDIで描画して作成
ビットマップをCreateDIBSection APIにより作成します。
CreateCompatibleDC APIにより指定されたデバイスコンテキストと互換性のあるメモリデバイスコンテキストを作成します。
SelectObject APIによりビットマップにデバイスコンテキストを関連付けます。
CreatePen APIとCreateSolidBrush APIによりペンとブラシを作成します。
ペン・ブラシの作成方法の詳細は以下を参照してください。
GDIのペンの作成方法
GDIのブラシの作成方法
PatBlt APIで塗りつぶすとマスク処理が正常にできなかったのでRectangle APIにより国旗を白く塗りつぶします。
Ellipse APIにより赤丸を描画します。 SelectObject APIにより作成したペンを選択します。
ImageList_AddMasked APIにより白を透明色に設定してイメージリストにビットマップを設定します。 DeleteObjectによりビットマップを削除します。

case WM_PAINT:

ウィンドウを再描画する必要があるときに呼び出されます。 他のウィンドウに隠れ再びフォアグラウンドになった場合などウィンドウの再描画はWindowsが面倒を見ないのでプログラマの仕事となっています。 BeginPaint APIを呼び出して、描画に必要なデバイスコンテキストのハンドルを取得します。 BeginPaint APIの第2引数のポインタにはPAINTSTRUCT構造体のポインタを渡します。 BeginPaint API終了後、PAINTSTRUCT構造体には再描画が必要な領域の座標等の値が格納されています。
ImageList_Draw APIを呼び出してイメージリストを描画します。

case WM_DESTROY:

ウィンドウが閉じるときに呼び出されます。
PostQuitMessage APIにより終了コードを指定して、ウィンドウプロシージャーを終了させます。

プログラムソース

imagelist1.cpp


#include <windows.h>
#include <commctrl.h>
#include <tchar.h>
#include "resource.h"

#pragma comment(lib,"comctl32.lib")

#define IMAGE_WIDTH 120 //      1個の画像の横幅
#define IMAGE_HIGHT  80 //      1個の画像の高さ


TCHAR* szClassName=TEXT("イメージリスト");
HINSTANCE hInst;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInst,
        TCHAR* lpszCmdLine, int nCmdShow){
        HWND hWnd;
        MSG lpMsg;
        WNDCLASS myProg;
        hInst=hInstance;

        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 = (HBRUSH__ *)GetStockObject(/*GRAY_BRUSH*/ WHITE_BRUSH);
                myProg.lpszMenuName        =NULL;
                myProg.lpszClassName    =szClassName;
                if (!RegisterClass(&myProg))
                        return FALSE;
        }
        hWnd = CreateWindow(szClassName,
                TEXT("イメージリスト"),
                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 int(lpMsg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
        static HIMAGELIST hImg;
        static HBITMAP hbitmap;
        static HDC img_hdc;
        HDC hdc;
    PAINTSTRUCT ps;

        HBRUSH hBrush, hOldBrush;
        BITMAPINFO bmp;

        switch(msg){
        case WM_CREATE:
//      イメージリスト作成
                hImg = ImageList_Create(IMAGE_WIDTH , IMAGE_HIGHT , ILC_COLOR32 | ILC_MASK, 3 , 0);

                hdc=GetDC(hWnd);
//      リソースから画像を読み込みイメージリストに登録
                hbitmap=LoadBitmap(hInst,MAKEINTRESOURCE(IRELAND_BMP));
                ImageList_AddMasked(hImg ,hbitmap,RGB(255,255,255));
                DeleteObject(hbitmap);
//      リソースから画像を読み込みイメージリストに登録
                hbitmap=LoadBitmap(hInst,MAKEINTRESOURCE(USA_BMP));
                ImageList_AddMasked(hImg ,hbitmap,RGB(255,255,255));
                DeleteObject(hbitmap);

//      日の丸を作成
//      メモリ上にデバイス独立ビットマップを(DIB)作成する。
                ZeroMemory(&bmp,sizeof(bmp));
                bmp.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
                bmp.bmiHeader.biBitCount=32;
                bmp.bmiHeader.biPlanes=1;
                bmp.bmiHeader.biWidth=IMAGE_WIDTH;
                bmp.bmiHeader.biHeight=-IMAGE_HIGHT;
                hbitmap=CreateDIBSection(NULL,&bmp,DIB_RGB_COLORS,NULL , NULL,0);
//      画面と互換性のあるデバイスコンテキストを作成
                img_hdc=CreateCompatibleDC(hdc);
                SelectObject(img_hdc , hbitmap);
                ReleaseDC(hWnd,hdc);

                HPEN hPen,hOldPen;
                hPen=CreatePen(PS_SOLID, 2, RGB(255,255,255) );
                hOldPen=(HPEN__ *)SelectObject(img_hdc, hPen);

                hBrush =CreateSolidBrush(RGB(255,255,255));
                hOldBrush = (HBRUSH__ *)SelectObject(img_hdc, hBrush);

                Rectangle(img_hdc , 0,0,IMAGE_WIDTH-1,IMAGE_HIGHT-1);

                hPen=CreatePen(PS_SOLID, 2, RGB(255,0,0) );
                SelectObject(img_hdc, hPen);

                hBrush =CreateSolidBrush(RGB(255,0,0));
                SelectObject(img_hdc, hBrush);

                Ellipse(img_hdc,IMAGE_WIDTH/2-16,IMAGE_HIGHT/2-16,IMAGE_WIDTH/2+16,IMAGE_HIGHT/2+16);
                SelectObject(img_hdc, hOldBrush);
                DeleteObject(hBrush);
                SelectObject(img_hdc, hOldPen);
                DeleteObject(hPen);
// イメージリストに登録する前にデバイスコンテキストを削除しなければならない
//      削除しないと真っ黒な画像が表示されるだけである。
                DeleteDC(img_hdc);
                ImageList_AddMasked(hImg ,hbitmap,RGB(255,255,255));
                DeleteObject(hbitmap);
                break;
        case WM_PAINT:  //      再描画時に呼び出される
                hdc=BeginPaint(hWnd,&ps);
                ImageList_Draw(hImg , 0 , hdc ,0,0, ILD_NORMAL);
                ImageList_Draw(hImg , 1 , hdc , IMAGE_WIDTH , 0 , ILD_NORMAL);
                ImageList_Draw(hImg , 2 , hdc , IMAGE_WIDTH*2 , 0 , ILD_NORMAL);
                EndPaint(hWnd,&ps);
                break;
    case WM_DESTROY:    //      終了時に呼び出される
                ImageList_Destroy(hImg);
        PostQuitMessage(0);
        break;
    default:
                return(DefWindowProc(hWnd, msg, wParam, lParam));
        }
        return (0L);
}

resource.h


#define IRELAND_BMP 100
#define USA_BMP  110

resource.rc


#include "resource.h"

IRELAND_BMP     BITMAP DISCARDABLE      "Ireland.bmp"
USA_BMP  BITMAP DISCARDABLE     "usa.bmp"

ソースファイルと実行ファイルのダウンロード

ダウンロード imagelist1.zip(51.9kByte)

ZIPファイルに含まれるファイル

imagelist1.cpp
imagelist1.exe
Ireland.bmp
resource.h
resource.rc
usa.bmp