<Previous>   <Next>   <SDK Top>   <Top>


章.3節.コンボボックスにビットマップを取り入れてみよう

     

コンボボックスにグラフィック(ビットマップ)を取り入れて表示してみましょう.
まず,ビットマップを書いてやる必要がありますね.
別章.3節.ビットマップ(Bitmap)を描いてみよう」に習って,次のようなビットマップを描いてみましょう.



黒,茶,緑,オリーブ・・・と順番に横15,縦16ピクセルの絵を書いてみました.
今回はそれをIDB_BITMAP1というIDにしてみました.

コンボボックスのIDは前回と同じですね.
(IDの作り方を知らない方は,「別章.2節.ストリングテーブルを編集してみよう」を先に読んでください.)

ID キャプション
IDC_COMBO コンボボックス

今回のポイントは,
@コンボボックスにビットマップをどうやって取り入れる?
というところです.

では,プログラムを見ましょう.


#include "stdafx.h"
#include <commctrl.h>
#include "resource.h"

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

#define MAX_LOADSTRING 100

#define TOOL_HEIGHT (30)

// グローバル変数:
HINSTANCE hInst;					// 現在のインスタンス
TCHAR szTitle[MAX_LOADSTRING];		// タイトル バー テキスト
TCHAR szWindowClass[MAX_LOADSTRING];	// タイトル バー テキスト

// このコード モジュールに含まれる関数の前宣言:
ATOM				MyRegisterClass( HINSTANCE hInstance );
BOOL				InitInstance( HINSTANCE, int );
LRESULT CALLBACK	WndProc( HWND, UINT, WPARAM, LPARAM );

HWND		ToolBarCreate(HWND hWnd);
HWND		ComboBoxCreateEx(int id, HWND hParent, int nX, int nY, int nWidth, int nHeight);
void		ComboBoxSetTopString(char *pszBuf);
void		ComboBoxEnumFontColor(HWND hWnd);

HWND		hToolBar;
HWND		hCombo;

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
	MSG msg;
	HACCEL hAccelTable;

	// グローバル ストリングを初期化します
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_SAMPLE, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass( hInstance );

	// アプリケーションの初期化を行います:
	if( !InitInstance( hInstance, nCmdShow ) ) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SAMPLE);

	// メイン メッセージ ループ:
	while( GetMessage(&msg, NULL, 0, 0) ) 
	{
		if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) 
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
	}

	return msg.wParam;
}

ATOM MyRegisterClass( HINSTANCE hInstance )
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_SAMPLE);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_SAMPLE;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx( &wcex );
}

BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
{
   HWND hWnd;

   hInst = hInstance; // グローバル変数にインスタンス ハンドルを保存します

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if( !hWnd ) 
   {
      return FALSE;
   }

   ShowWindow( hWnd, nCmdShow );
   UpdateWindow( hWnd );

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int				wmId, wmEvent;
	static char		szBuf[256]="";
			
	switch( message ) 
	{
		case WM_CREATE:
			// ツールバーを作る
			hToolBar = ToolBarCreate( hWnd );
			// コンボボックスを作る
			hCombo = ComboBoxCreateEx(IDC_COMBO, hToolBar, 0, 0, 200, 200);
			// コンボボックスに色のビットマップ及び名前を挿入する
			ComboBoxEnumFontColor(hWnd);
			// コンボボックスの初期表示文字列を決める
			ComboBoxSetTopString("黒");

			break;
		case WM_SIZE:
			MoveWindow(hToolBar, 0, 0, LOWORD(lParam), TOOL_HEIGHT, TRUE);
			break;
		case WM_DESTROY:
			PostQuitMessage( 0 );
			break;
		default:
			return DefWindowProc( hWnd, message, wParam, lParam );
   }
   return 0;
}

HWND	ToolBarCreate(HWND hWnd)
{
	HWND hTool;

	InitCommonControls();

	hTool = CreateWindowEx(
					WS_EX_TOOLWINDOW, 
					TOOLBARCLASSNAME,
                    NULL,
                    WS_CHILD | WS_VISIBLE |
					CCS_ADJUSTABLE | CCS_NORESIZE,
					0,0,0,0,
                    hWnd,
                    NULL,
                    hInst,
                    NULL);

	SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);

	return hTool;
}

HWND	ComboBoxCreateEx(int id, HWND hParent, int nX, int nY, int nWidth, int nHeight)
{
	INITCOMMONCONTROLSEX ic;
	
	//フォントカラーのコンボボックスの作成
	ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
	ic.dwICC = ICC_USEREX_CLASSES;
	InitCommonControlsEx(&ic);

	hCombo = CreateWindowEx(0, WC_COMBOBOXEX, "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_AUTOHSCROLL| WS_CLIPSIBLINGS | WS_VSCROLL, 
				nX, nY, nWidth, nHeight, hToolBar, (HMENU)id, hInst, NULL);

    return hCombo;
}

void	ComboBoxSetTopString(char *pszBuf)
{
	WPARAM	index;

	index = SendMessage(hCombo, CB_FINDSTRINGEXACT, -1, (LPARAM)pszBuf);
	SendMessage(hCombo, CB_SETCURSEL, index, 0);
}

void ComboBoxEnumFontColor(HWND hWnd)
{
	COMBOBOXEXITEM citem;
	HIMAGELIST hImg;

	SendMessage(hCombo, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0));

	//イメージを取り込む
    hImg = ImageList_LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1), 15, 16, RGB(255,255,255));
    if (hImg == NULL)
        MessageBox(hWnd, "イメージを取り入れられませんでした", "OK", MB_OK);

    SendMessage(hCombo, CBEM_SETIMAGELIST, 0, (LPARAM)hImg);
    citem.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
    citem.pszText = "黒";
    citem.iItem = 0;
    citem.iIndent = 0;
    citem.iImage = 0;
    citem.iSelectedImage = 0;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "茶";
    citem.iItem = 1;
    citem.iIndent = 0;
    citem.iImage = 1;
    citem.iSelectedImage = 1;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

    citem.pszText = "緑";
    citem.iItem = 2;
    citem.iIndent = 0;
    citem.iImage = 2;
    citem.iSelectedImage = 2;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

    citem.pszText = "オリーブ";
    citem.iItem = 3;
    citem.iIndent = 0;
    citem.iImage = 3;
    citem.iSelectedImage = 3;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

    citem.pszText = "紺";
    citem.iItem = 4;
    citem.iIndent = 0;
    citem.iImage = 4;
    citem.iSelectedImage = 4;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "紫";
    citem.iItem = 5;
    citem.iIndent = 0;
    citem.iImage = 5;
    citem.iSelectedImage = 5;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "青緑";
    citem.iItem = 6;
    citem.iIndent = 0;
    citem.iImage = 6;
    citem.iSelectedImage = 6;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "灰色";
    citem.iItem = 7;
    citem.iIndent = 0;
    citem.iImage = 7;
    citem.iSelectedImage = 7;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "銀色";
    citem.iItem = 8;
    citem.iIndent = 0;
    citem.iImage = 8;
    citem.iSelectedImage = 8;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "赤";
    citem.iItem = 9;
    citem.iIndent = 0;
    citem.iImage = 9;
    citem.iSelectedImage = 9;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "黄緑";
    citem.iItem = 10;
    citem.iIndent = 0;
    citem.iImage = 10;
    citem.iSelectedImage = 10;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "黄";
    citem.iItem = 11;
    citem.iIndent = 0;
    citem.iImage = 11;
    citem.iSelectedImage = 11;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "青";
    citem.iItem = 12;
    citem.iIndent = 0;
    citem.iImage = 12;
    citem.iSelectedImage = 12;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "赤紫";
    citem.iItem = 13;
    citem.iIndent = 0;
    citem.iImage = 13;
    citem.iSelectedImage = 13;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

}

☆プログラムの解説☆

@コンボボックスにビットマップをどうやって取り入れる?

// コンボボックスを作る
hCombo = ComboBoxCreateEx(IDC_COMBO, hToolBar, 0, 0, 200, 200);

ビットマップを取り入れたコンボボックスを作るには,コンボボックスを拡張しないといけないみたいですね.
まず,拡張コンボボックスを生成する関数を見てみましょう.

HWND	ComboBoxCreateEx(int id, HWND hParent, int nX, int nY, int nWidth, int nHeight)
{
	INITCOMMONCONTROLSEX ic;
	
	//フォントカラーのコンボボックスの作成
	ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
	ic.dwICC = ICC_USEREX_CLASSES;
	InitCommonControlsEx(&ic);

	hCombo = CreateWindowEx(0, WC_COMBOBOXEX, "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_AUTOHSCROLL| WS_CLIPSIBLINGS | WS_VSCROLL, 
				nX, nY, nWidth, nHeight, hToolBar, (HMENU)id, hInst, NULL);

    return hCombo;
}

前回のコンボボックスの作り方と少し違いますね.
IDD_USEREX_CLASSESは,拡張コンボボックスのクラスIDです.
それをInitCommonControlsEx(API)を使ってロードされます.
さらに,CreateWindowEx(API)を用いて,拡張コンボボックスを作成します.

// コンボボックスに色のビットマップ及び名前を挿入する
ComboBoxEnumFontColor(hWnd);

この関数は,コンボボックスに先ほど作った色のビットマップとその色名を挿入する関数です.
中身を見ましょう

void ComboBoxEnumFontColor(HWND hWnd)
{
	COMBOBOXEXITEM citem;
	HIMAGELIST hImg;

	// コンボボックスの名前をコンパクトに見せる
	SendMessage(hCombo, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0));

	//イメージを取り込む
    hImg = ImageList_LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1), 15, 16, RGB(255,255,255));
    if (hImg == NULL)
        MessageBox(hWnd, "イメージを取り入れられませんでした", "OK", MB_OK);

    SendMessage(hCombo, CBEM_SETIMAGELIST, 0, (LPARAM)hImg);
    citem.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
    citem.pszText = "黒";
    citem.iItem = 0;
    citem.iIndent = 0;
    citem.iImage = 0;
    citem.iSelectedImage = 0;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	citem.pszText = "茶";
    citem.iItem = 1;
    citem.iIndent = 0;
    citem.iImage = 1;
    citem.iSelectedImage = 1;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

    citem.pszText = "緑";
    citem.iItem = 2;
    citem.iIndent = 0;
    citem.iImage = 2;
    citem.iSelectedImage = 2;
    SendMessage(hCombo, CBEM_INSERTITEM, 0, (LPARAM)&citem);

	・・・

という感じですね.
始めに,前回と同様コンボボックスの文字をコンパクトにするSendMessage(API)があります.
ImageList_LoadBitmapというマクロを使って先ほど作ったビットマップをイメージリストとして取り込んでいるんですね.
イメージリストっていうのは,ある大きさ(この場合は(15,16)と指定してますね)のイメージが並んでいるものです.
「黒,茶,緑,・・・」の一つのイメージを作りましたが,イメージリストは,
イメージは(今回は色)は各々が独立したもので,それらがくっついたもの(リスト)
と考えられます.
また,イメージリストの各々のイメージは,添え字によって参照することが可能です.
黒,茶,緑でそれに対応するcitemのメンバ変数の値が0,1,2・・・と変わってますね.
黒の場合,0なので,イメージの1番左端( (0,0)から(15,16)まで)のイメージ,
茶の場合,1なので,イメージの左から2番目( (16,0)から(31,16)まで)のイメージ,
緑の場合,2なので,イメージの左から3番目と言った感じで参照できます.

そして,順番に各々のイメージを順番にSendMessageを使ってコンボボックスに追加しています!


              

 

------------------------------------------------------------------------------------------------

当ページの一部または全部を転載、複写、複製することを禁じます。
また,当サイトを利用した結果に関するトラブル等は、一切関与いたしませんのでご容赦下さい。
Update 04/03/15 By 松本義弘

------------------------------------------------------------------------------------------------

デル4_120x60富士通ショッピングサイト WEB MART   NEC得選街   sotecロゴ88x31b   バナー 10000035