コンボボックス、ドロップダウンリスト

前書き(その0)

C++というタグとWindowsというタグをまとめて、VC++というタグに置き換えることにしました。

前書き(その1)

WTLでコンボボックス(ComboBox)を使ってみました。
そこでわかったことや、参考にさせて
もらったサイトをまとめます。

コンボボックスとは

Windowsユーザーじゃなくても、こういうのを使ったことはあると思います。(以下の写真)
複数の選択肢から1つだけを選択させるやつですね。

コンボボックスの種類

コンボボックスにはいくつかの種類があります。

  • 写真の一番上の"山手線"の部分を編集できるタイプ/編集できないタイプ
  • スクロールバーを表示するタイプ/スクロール機能がないタイプ
  • 自動でスクロールしてくれるタイプ/してくれないタイプ
  • 拡張コンボボックス(フォント,アイコンなどの拡張。*1

ドロップダウンリストとは

どうやら、コンボボックスのことをドロップダウンリストと呼ぶことがあるらしいです。
そのように呼んだ場合は、編集不可能なタイプのことを指すらしいです。
ただしソースはウィキペディア。略してTSW。

通知メッセージ

コンボボックスに入力があった場合、親ウィンドウにWM_COMMANDが送られます。
WPARAM,LPARAMの情報をもとに、親ウィンドウが処理します。
どのような入力が発生したかは、WPARAMの上位ワードを見ます。
通知メッセージの一覧は、こちらのページにありました。
標準 Windows API - コンボボックス
CBN_SELENDOK、CBN_SELENDCANCELはわかりにくいかもしれません。
うまく説明できないので、実際に試してみてください。

コンボボックスを使ってみる(WinAPIでゴリゴリ)

標準 Windows API - コンボボックスや、VC++の使い方 - コンボボックスコントロールが参考になりそうです。
どちらのサイトも結構お世話になってます。

コンボボックスを使ってみる(WTL)

こちらも、人様のページのリンクで済ませさせていただきます。
ATL-WTL コンボボックス
こちらはダイアログ内にコンボボックスを表示していますが、ダイアログリソースを使わないで作るときは

// あるウィンドウのOnCreate(WM_CREATEメッセージハンドラ)の最後にでも書いておく

// ▼ボタンを押したときの、最大の大きさ
// この大きさにおさまらない場合は、スクロールバーがつく
RECT rcCmbBox = { 100, 100, 300, 300, };

DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | CBS_DROPDOWNLIST
		| WS_VSCROLL | CBS_NOINTEGRALHEIGHT;
m_combo.Create( m_hWnd, &rcCmbBox, NULL, dwStyle);
m_combo.AddString( _T("山手線"));
//
// 中略
//
// 0番を選択する。これがないと…コメントアウトして試してみるといい。
m_combo.SetCurSel( 0);

とします。

コンボボックスの大きさ(フォント)を変更する

コンボボックスに限らず、コントロールのフォントを変更するには、WM_SETFONTメッセージを使います。
WTLならCComboBox::SetFont()みたいなのがある。多分MFCでも。)
もっと凝った演出(*2)をしたいときは、オーナードローやカスタムドローを行わなきゃいけないらしいです。

WinAPI式
// hCtrlは、コンボボックスやその他コントロールのウィンドウハンドルとします。

// フォントの設定。面倒くさかったら、これをコピペしてもいいよ。
// 後ろから2番目の引数は、フォントの幅(第2引数との関連は不明)
// DEFAULT_PITCH(既定)/FIXED_PITCH(固定幅)/VARIABLE_PITCH(可変幅) の中から1つ。
//
// 注意: hFontは、コントロールが破棄されるまでDeleteObjectしないでください。
HFONT hFont = CreateFont(
	12,		// 高さ(というか大きさ)
	0,		// 平均文字幅
	0,		// 角度
	0,		// 角度
	FW_REGULAR,	// 太さ
	0,		// 斜体(1で有効)
	0,		// 下線(1で有効)
	0,		// 打ち消し線(1で有効)
	SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
	PROOF_QUALITY,
	VARIABLE_PITCH | FF_DONTCARE,	// 幅
	NULL	// フォント名
);
if(hFont == NULL) {
	// CreateFont()失敗
}

// コントロールのフォントを設定する
SendMessage( hCtrl, WM_SETFONT, (WPARAM)hFont, 1);
WTL

WinAPI式とほとんど同じです。
SendMessageしないで、wndCmbBox.SetFont( hFont);ってすればOK。
WTL::CFontというHFONTをクラス化したものがありますが、むやみに使うと、
CFontのデストラクタが、いつの間にかにDeleteObjectしてしまうので注意。
コンボボックスを破棄してから、DeleteObjectしてください。

参考

CreateFontの詳細はMSDNのこちらのページを。

あとがき

WTLによる例を主体にするつもりだったのに、先達がやってました。
この記事の存在意義が
それと、最近やっとダイアログリソースや、コントロールIDの話がわかりました。
実際に使ってみないと理解できませんね。

*1:ComboBoxExという名前で、ComboBoxとは別物

*2:項目ごとに色やフォントや背景色を変えたいなど