Version 5.31
コンボボックスとエディットボックス
「前回はファイルダイアログを使ってみました」
『 CFileDialog ってクラスで簡単にできたよねー。で、その開いたファイ
ルを読み込むんだよね』
「そう。 CFileTestDlg::OnBtnShow() の中で……」
void CFileTestDlg::OnBtnShow()
{
m_cDataLstBox.ResetContent();
std::ifstream cIFStrm;
cIFStrm.open( "Data.txt" ); // ここ!
// 以下略
「この "Data.txt" をその開いたファイルのフルパス文字列に置き換えれば
うまくいきます」
『でもどーやって渡すの? メンバ関数違うじゃん』
「そこで〈コンボボックス〉を使います」
『こんぼぼっくす?』
「 IDC_CMB_FILE って ID を付けたコントロール。 Ver 5.01 ( No.066 )
を見といてね」
『あ、[ファイル]の右隣のだね。コンボって、チキンとフライドポテトとか
が一緒のセットをコンボとかゆーよね』
「それと同じ。コンボボックスは、エディットボックスとリストボックスが
組み合わさってるんです。 Spy++ 起動してからテスト実行してみて」
『はんこみたいなボタン!』
「普通に Spy++ の照準を重ねると ComboBox って出るでしょ」
『うんそーゆーウィンドウクラスだね』
「その内側に照準を持ってくると……」
『 Edit になった!!』
「つまりこの普通に見えるところはエディットボックス」
『おー』
「で、その横の [▼] を押すと出てくるのを〈ドロップダウンリスト〉って
言うんだけど、これがリストボックスで作られてます」
『リストボックス……むむむ、 Spy++ じゃ調べらんないね』
「そうだね」
『……じゃーなんでリストボックスだってわかるの?』
「あー、書いてあるんだよそう。 MSDN の Combo Boxes Overview ってペー
ジを見てみて」
『英語ページね。へー、クラス名は COMBOBOX だとか、 list box と edit
control の組み合わせだとか書いてあるんだね』
「【次へ】を押してくと、どんどん見られるよ」
『色々細かい解説書いてあるんだね……あ、メッセージっぽいのが出てきた。
コンボボックスのメッセージは CB_ なんだね』
「左上の【同期】ってボタン押してみて」
『目次見るボタンだね。結構深いところにあるページだね』
「上の方に Platform SDK ってあるでしょ」
『うんある』
「ここ以下に書いてあるのが、ウィンドウズそのものの仕様」
『仕様……って、これ文章かなり多くない?』
「多いよー。コンボボックスだけでも50ページ以上あるみたいだし」
『50ページ以上!? あ、そーか、メッセージとか API の分も入れてね。
でも解説もかなり分量あるね。はっ、もしかして』
「そう、他のコントロールも同じくらいあるから」
『すごい量……』
「この Platform SDK には重要なことが書いてあること多いから、まめに見
るようにね」
『それって最初に言うべきことじゃない?』
「いや、ある程度勉強しとかないと見ても理解できないから」
『う~。質問! ぷらっとふぉーむえすでぃーけーってどーゆーいみ?』
「プラットフォームっていうのは OS のこと」
『つまりウィンドウズ?』
「そゆこと。 SDK は Software Development Kit の略。つまりソフトを作
るためのもののこと」
『ソフトを作るためのもの?』
「つまり API のこと」
『ああ!』
「 API はウィンドウズアプリを作るためのキットってことだね。ま、基本
的には SDK と API は同じに考えていいかな」
『違うことってある?』
「 API ってゆーと関数のこと指すことが多いかな。だから、前回使った
MAX_PATH みたいな整数値は API とは呼ばないことが多いみたいだけど」
『これは SDK のものってことなのね。ってことは SDK の中に API が入っ
てるってことなのかな』
「そういう考え方もできるかな。と、話がそれちゃったね」
『コンボボックスだよね。よーするにエディットボックスとリストボックス
がくっついてコンボボックスになってるんだね』
「そゆこと。ま、その辺が混乱の元なんだけどね」
『どゆこと?』
「それは……そうだね、メンバ変数作ってみれば分かるかな。リストボック
スの時みたいに、 IDC_CMB_FILE を操作するメンバ変数を作りましょう」
『リストボックスの m_cDataLstBox みたいなのってことね』
「まず ClassWizard ダイアログを表示させて【クラス名】が CFileTestDlg
になってるのを確認してから【コントロール ID 】の IDC_CMB_FILE をダブ
ルクリック」
『【メンバ変数の追加】ダイアログが出たよ。【変数のタイプ】が CString
なんだね』
「コンボボックスはエディットボックスとしても機能するから、その部分を
CString とくっつける方法も採れるんだけど、今回はパス。【カテゴリ】を
〈コントロール〉にして」
『【変数のタイプ】が CComboBox になった!』
「こっちなら CComboBox クラスを使ってコンボボックスを操作できるから」
『 CString の方だとそういう操作ができない?』
「そゆこと。計算機作ったときにやったでしょ、 UpdateData( FALSE ) を
呼ぶと、メンバ変数の値がコントロールに書き込まれるってやつ」
『やった! そっか、エディットの部分を CString 型のメンバ変数と結び
付けて、書き込み読み込みができるようにすることができるんだね』
「詳しくは Ver 3.11 ( No.036 ) 参照。でも、コンボボックスはリストボッ
クスとしての操作も必要でしょ」
『そっちは CComboBox 型のメンバ変数でってことになるんだ。ってことは
ふたつメンバ変数を作るってこと?』
「それもできるんだけどね」
『「ね」って? あんましない方がいいってこと?』
「まーね。コンボボックスを操作するメンバ変数がふたつもあったら混乱の
元だからね」
『……なんか煮え切らない言い方ね』
「でもふたつ作っちゃった方が楽って場合もあるからね。今回は CComboBox
だけにするけど」
『ま、確かに混乱の元ってのは分からなくもないけどね。えーっと、メンバ
変数の名前は m_cFileCmbBox でいい?』
「うんOK」
『んじゃ【カテゴリ】をコントロール、【変数のタイプ】を CComboBox に
して OK っと。ほいメンバ変数できたよ』
「さて、じゃあこのコンボボックスに文字列を表示しましょう。 CComboBox
のリファレンス見て」
『メンバ関数一覧~。…………ねー、エディットボックスのとこにどーたら
って感じのメンバ関数がみつかんないんだけど』
「そう、ないんです」
『えええっ!!』
「なんでねぇ、さっきの CString 使うっててもあるってことだね」
『うー、じゃー面倒な方法必要なんだ』
「あ、別にそういうわけじゃないんだけどね。えーっと、さっき見た MSDN
の Combo Boxes Overview のページ開いて」
『ほい』
「【次へ】ボタンを何度も押して Edit Control Selection Fields って
ページを表示させて読んでみて」
『ほい出た。えーっとなになに……あ、 WM_SETTEXT ってある! これって
ウィンドウのタイトルとか、ボタンの文字列変えるときに使うのだよね』
「そうそう。これを見れば分かるとおり、コンボボックスにこのメッセージ
を直接送れば、エディットボックスに送られて、エディットボックスの文字
列を書き換えることができるんです」
『思い出した! WM_SETTEXT って SetWindowText() と同じなんだよね。
ってことはこの API 使えばいいんだ!』
「 API じゃなくても大丈夫でしょ」
『え? えーっと、 SetWindowText() は…… CWnd のメンバ関数にもなっ
てるね。そっか、コントロールのクラスは CWnd から継承してるから!』
「そういうこと! CComboBox は CWnd のメンバ関数も使えるんです。と
いうわけで、前回の CFileTestDlg::OnBtnBrowse() の中身をこう書き換え
てみましょう」
void CFileTestDlg::OnBtnBrowse()
{
CFileDialog cFileDlg( TRUE );
char chPath[MAX_PATH];
GetModuleFileName
( AfxGetInstanceHandle(), chPath, MAX_PATH - 1 );
cFileDlg.m_ofn.lpstrInitialDir = chPath;
int iRes
= cFileDlg.DoModal();
if( iRes == IDCANCEL )
{
return;
}
// この下の行だけ書き換え。
m_cFileCmbBox.SetWindowText( cFileDlg.GetPathName() );
}
『なるほど、 m_cFileCmbBox からそのまま SetWindowText() 呼んじゃえば
いいんだ』
「で、前回使った CFileDialog::GetPathName() と組み合わせれば」
『ビルドして実行! ファイルダイアログでファイル選んで【開く】っと。
おおっ選んだファイルのフルパスがコンボボックスに!!』
「じゃ、ついでに CFileTestDlg::OnBtnShow() の方も書き換えちゃいましょ
う。 SetWindowText() の逆に文字列を取得するのは」
『 GetWindowText() !! MSDN のリファレンス~っと、2番目のよく分
かんないから1番目のでいーや。 LPTSTR だから文字配列用意して、サイズ
は……』
「前回やったでしょ、フルパスは最大」
『 MAX_PATH まで! だから、こんな感じかな?』
void CFileTestDlg::OnBtnShow()
{
m_cDataLstBox.ResetContent();
char chPath[MAX_PATH];
m_cFileCmbBox.GetWindowText( chPath, MAX_PATH - 1 );
std::ifstream cIFStrm;
cIFStrm.open( chPath );
// 以下そのまま。
『ビルドして実行、【参照】ボタンでファイルダイアログで Data.txt を選
んで開いて、んで【表示】ボタン押して……おおおっ、前みたくリストボッ
クスに表示された!!』
「ここまでできると、なんかちゃんとしたアプリっぽいよね」
『アプリっぽい!! なんかすご~い!!』
「ま、ようするにコンボボックスも SetWindowText() とかでエディットの
操作ができるってことだね」
『なんだ、やっぱし CString は要らないんだね』
「でももし1人でやってとしたら、こーゆーことわかったと思う?」
『思わない。 CComboBox のメンバ変数から SetWindowText() を呼ぶって発
想出てこないし、そこまでたどり着かせるのも大変だし』
「だから CString の方法があるってことかも。 MFC は元々簡単にこういう
ことができるようにしてくれてるからね」
『確かにねー』
/*
Preview Next Story!
*/
『コンボボックスひとつでも奥が深いのねぇ』
「作ってみる側から考えればそれも当然だよ」
『げ! 作る!?』
「そりゃコンボボックスだってプログラムとして作れるわけだから」
『そりゃそうだけど』
「操作ひとつひとつが、どういう仕様にするべきか熟考されてるんだから」
『というわけで次回』
< Version 5.32 コンボボックスのリストに追加! >
「につづく!」
『……ホントに熟考されてると思う?』
「う”」