VC++の使い方

VC++の使い方 > リファレンス > GUIリファレンス > コンボボックス コントロール
このページの内容
コンボ ボックスとは
作成方法
コンボボックスのインデックスについて
使い方
ありがたいスポンサー様
All About ソフトウエアエンジニア
ネットで8%割引!自動車保険はアメリカンホーム・ダイレクト
人生の「チャンス」と「ピンチ」にモビット!
保険料が一生上がらない、保険料最大50%割引の一生涯の医療保険!

コンボ ボックスとは

コンボ ボックスは、次のような用途に使います。


具体例として下の図を見てください。これは一般的なフォントの選択ダイアログです。このダイアログは、コンボボックスのオンパレードです。フォントの種類や、スタイル、サイズ、書体の種類にいたるまで、すべてがコンボボックスです。書体の種類が フォントのうちのどれを選ぶかによってリストの内容が変わります。これが上で選択肢は可変だといった理由です。他の場所で選択した内容によって、選択肢が変わるのは、ラジオボタンでは不可能です。

コンボボックスの使用例
コンボボックスの使用例

また、インターネットエクスプローラーのアドレスバーでも、コンボボックスが使われています。

作成方法

CreateWindow で作成する方法

CreateWindow( 
    "COMBOBOX",
    "text is here.",            // 表示する文字列
    ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER, 
                                // ウインドウスタイル
    x, y,                       // 左上の座標
    iWidth, iHeight,            // 幅と高さ
    hParent,                    // 親ウインドウのウインドウハンドル
    NULL,                       // メニューハンドル。NULLでよい。
    hInstance,                  // アプリケーションのインスタンスハンドル。
    NULL                        // ウインドウ作成データ。NULLでよい
) ;

ダイアログで作成する方法

ダイアログエディタで作成する場合には、丸をつけている 『エディットボックス』 で作成できます。

コントロールバーが表示されていない場合は、VC++ のメニューの上で右クリックして、『コントロール』 をチェックすれば出てきます。

ウインドウハンドルを取得するには、hwnd = GetDlgItem( hDlg, IDC_COMBO);といった感じでコントロールIDをしていすればOKです。

コンボボックスのインデックスについて

インデックスは、ドロップダウンリストを表示させたときに、何番目に表示されるかを表します。コンボボックスのスタイルでソートが有効になっている場合、ソート後に何番目になっているかがインデックスの表す数字です。

動的にアイテムが増減するコンボボックスにおいては、インデックスをいつまでも保持しないように注意しましょう。なぜなら、アイテムが追加されると、インデックスが変化してしまうからです。そのため、間違ったアイテムを削除してしまうことになるかもしれません。

使い方

コンボボックスのイベントを受け取りたい

WM_COMMAND を捕まえればよい。代表的なものを次に上げておきます。

CBN_DROPDOWN ドロップダウンリストが開いたとき
CBN_CLOSEUP ドロップダウンリストが閉じられたとき
CBN_SELCHANGE 選択項目が変更されたとき
CBN_EDITUPDATE 直接入力で内容が変更されたとき。変更内容が表示される前に呼ばれる。
CBN_EDITCHANGE 直接入力で内容が変更されたとき。変更内容が表示された後に呼ばれる。
case WM_COMMAND:
	if(LOWORD(wParam) == IDC_COMBOBOX)
	{
		if(HIWORD(wParam) == CBN_DROPDOWN)
		{
			// ドロップダウンされたときの処理。
			// このときはじめて、コンボボックスに追加していくのもあり。
		}
		else if(HIWORD(wParam) == CBN_CLOSEUP)
		{
		}
	}

アイテムを追加する

CB_ADDSTRING を使うと CBS_SORT が設定されている場合は末尾に、いない場合はソートされて追加します。ソートが有効の場合は、追加するまで何番目に追加されたかが分かりません。この場合、SendMessage の戻り値で、追加されたインデックスを取得することが出来ます。

CB_INSERTSTRING では、追加するインデックスを指定して追加することができます。

// インデックスを考えずに追加する。
// ソートが設定されていなければ、末尾に追加される。
SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)"ほげ");

// インデックスを指定して追加する。
// CBS_SORT が設定されていようがなかろうが、index に追加する。
SendMessage(hwndCombo, CB_INSERTSTRING, index, (LPARAM)"ほげ");

アイテムを削除する

// インデックスによって指定する
SendMessage(hwndCombo, CB_DELETESTRING, index, 0);

すべてのアイテムを削除する

専用のメッセージは用意されていません。自力で消していくしかないです。

while(SendMessage(hwndCombo, CB_GETCOUNT, 0, 0) != 0)
{
	SendMessage(hwndCombo, CB_DELETESTRING, 0, 0);
}

アイテムの数を取得する

SendMessage(hwndCombo, CB_GETCOUNT, 0, 0,);

選択されているアイテムのインデックスを取得

SendMessage(hwndCombo, CB_GETCURSEL, 0, 0,);
// 選択されていない場合は、CB_ERR(-1) が帰ってっくる

アイテムを選択する

SendMessage(hwndCombo, CB_SETCURSEL, index, 0,);

indexがアイテム数よりも多かった場合や -1 であったときは、選択はキャンセルされる。

何も選択していない状態にする

SendMessage(hwndCombo, CB_SETCURSEL, -1, 0,);

文字列を取得する

// 選択中 or 編集中のアイテムの場合


// 特定のインデックスの場合
// intIndex 番目の文字列を取得する
int intTxtLen = SendMessage(hwndCombo, CB_GETLBTEXTLEN, intIndex, 0);
if(intTxtLen != CB_ERR)
{
	char* pszBuf = new char[intTxtLen + 1];
	if(SendMessage(hwndCombo, CB_GETLBTEXT, intIndex, (LPARAM)pszBuf) != CB_ERR)
	{
		// ここで参照
		MessageBox(hDlg, pszBuf, NULL, MB_OK);
	}
	delete[] pszBuf;
}

特定の文字列を含む要素を取得する

// hoge から始まるアイテムのインデックスを indexStart 番目から検索する。
// 大文字小文字は区別しない。
int intIndex = SendMessage(hwndCombo, CB_FINDSTRING, indexStart, "hoge");

// hoge という要素であるアイテムのインデックスを indexStart 番目から検索する。
// 大文字小文字は区別しない。
int intIndex = SendMessage(hwndCombo, CB_FINDSTRINGEXACT, indexStart, "hoge");

もっと複雑な検索を行いたい場合は、ひとつずつ文字列を取得して比較していくしかないでしょう。

ドロップダウンリストを表示する

SendMessage(hwndCombo, CB_SHOWDROPDOWN, 0, 0);

文字列の選択を取得・変更する

ドロップダウン の場合(編集できるほう)、文字列のなかでどの文字を選択しているかを CB_GETEDITSEL, CB_SETEDITSEL で取得できます。

実はドロップダウンの場合、編集している部分を表示しているのは、実は エディットボックス ウインドウなのです。そこで、そんなことをしなくても、エディットボックスのウインドウハンドルを取得すれば、もっといろいろ調べることが出来ます。

// ドロップダウンでなければならない
HWND hwndEdit = GetWindow(hwndCombo, GW_CHILD);