Version 8.11
ツリービューコントロールを作ろう!
「前回の最後に」
WM_ : 普通のメッセージ。ウィンドウプロシージャで受ける
*M_ : コントロールに送って操作する。 EM_ とか
*N_ : 通知メッセージ。コントロールから WM_COMMAND と一緒に来る
「って説明しました」
『で、なんか最後のが違うって言ってたよね』
「言いました。これは、通知メッセージは WM_COMMAND と一緒に送られてく
るものだけじゃなくて、 WM_NOTIFY ってメッセージと一緒に送られてくる
ものもあるから」
『 WM_NOTIFY の notify って〈通知〉って意味だよね。こっちの方がむし
ろ通知メッセージっぽいね』
「この WM_COMMAND が送られてくるか WM_NOTIFY が送られてくるかってい
うのは、コントロールの種類によって決まります」
『エディットボックスは WM_COMMAND だったね』
「そう、ほとんどのコントロールは WM_COMMAND で送られてきます。
WM_NOTIFY が送られてくるのはツリービューコントロールやリストビューコ
ントロールとかの、比較的新しいコントロールだけ」
『新しい?』
「まー、ウィンドウズ95からって意味での新しいってこと」
『ウィンドウズ3.1の頃はなかった?』
「たぶん……で!」
『で?』
「その WM_NOTIFY を使うためにはツリービューコントロールとかを使わな
きゃいけない」
『つまりこれからツリービューコントロールを作るわけね』
「そうなるんだけど……普通にそれをやると大変だから、まず MFC で使っ
てみることにします」
『 MFC ? 今のプロジェクトで MFC 使えるの?』
「使えないから、新しくプロジェクト作ります」
『げ』
「というわけで、今の SimpleDialog を閉じて、新しく MFC プロジェクト
を作って」
『ほいほい。【MFC AppWizard (exe)】で普通にダイアログのを作ればいい
んだよね』
「そうそう。プロジェクト名は MfcDialog にでもしといて」
『ほいほい』
「作ったら、そこにツリービューコントロールを貼り付けて」
『ツリービューコントロールって、横向きの手の指みたいなのだよね』
「手の指……そうそれ」
『貼り付けたよ』
「次にそのツリービューコントロールの ID を IDC_TREE_MAIN に」
『ほい』
「さらに、プロパティの【スタイル】ページで【ボタンあり】と
【線を表示】と【最上位にも線を表示】をオンにして」
『これがないと、エクスプローラーとかみたくなんないんだね』
「そうなんだよね、最初からそういうスタイルになってないから、これをし
ないとツリービューコントロールっぽくならないから忘れずに。じゃ、とり
あえずビルドして実行してみて」
『ほい。んー、でもツリービューコントロールに何も表示されないね』
「そう、そこは自分で追加しなきゃいけないんです。プログラム書いてね」
『あらま、それは面倒』
「うん、結構面倒かも」
『げ……』
「まず、クラスウィザードを表示して」
『あ、操作するのにメンバ変数作るんだね』
「その通り。 Version 5.31 ( No.096 ) とかでやったね」
『同じようにすればいいんだよね』
「そう。【メンバ変数】ページで IDC_TREE_MAIN を選択して
【変数の追加】を押して」
『ほい。あれ、【カテゴリ】が最初から〈コントロール〉になってる』
「ツリービューコントロールとかは複雑だから、普通の変数に置き換えられ
ないんです」
『だから変数版のメンバ変数は作れないわけね。メンバ変数は m_cMainTree
でいい?』
「うんそれで。このメンバ変数を使って、ツリービューコントロールに項目
を追加してみます。追加するのはおなじみの OnInitDialog() に」
BOOL CMfcDialogDlg::OnInitDialog()
{
// 略。
// TODO: 特別な初期化を行う時はこの場所に追加してください。
m_cMainTree.InsertItem( "1番目のアイテム" );// この1行を追加。
return TRUE;
}
『ん、追加するのって1行だけでいいの?』
「とりあえず」
『じゃーとりあえずビルドして実行。おお、ツリービューコントロールに
〈1番目のアイテム〉が追加された!』
「この CTreeCtrl::InsertItem() で項目……アイテムっていうのもあれだ
から【アイテム】って呼ぶね」
『ほいアイテム。ゲームなんかのアイテムと同じ?』
「そう同じ。このアイテムの追加を CTreeCtrl::InsertItem() でします」
『んーと、これを』
m_cMainTree.InsertItem( "1番目のアイテム" );
m_cMainTree.InsertItem( "2番目のアイテム" );
『ってやると……あー、どんどん増えてくけど、ツリーになんないね。1番
目のアイテムの……子アイテムってどうやって入れるの?』
「それには CTreeCtrl::InsertItem() の隠された引数を使います」
『隠された引数?』
「 CTreeCtrl::InsertItem() のリファレンスを見てみて」
『ほい。あれれ? メンバ関数がいっぱいある』
「関数は引数が違うものをいっぱい作れるから。これを【オーバーロード】
って言います」
『オーバーロードって前にやったね』
「 Version 7.09 ( No.129 ) でやった【演算子のオーバーロード】と同
じ。あれは演算子だったけど、こっちは普通の関数」
『???』
「んー、演算子のオーバーロードの方は難しいかも……うん、〈同じ〉発言
は撤回」
『なんですと?』
「とりあえずは、普通のオーバーロードと、演算子のオーバーロードは別に
憶えた方がいいかも」
『別に?』
普通のオーバーロード:同じ名前の関数を、引数の変えて色々作ること
演算子のオーバーロード:クラスに演算子を使えるように関数を作ること
「って憶えた方が今は楽かもね」
『うん、この方が分かりやすい……けど、ホントは同じなの?』
「そう、 C++ では演算子も関数の一種、って見方が強いからね」
『演算子も関数の一種、ねぇ……』
「というわけで話を戻して」
『 CTreeCtrl::InsertItem() にはオーバーロードしてて、関数が4つある
ね。あれ? でもさ、今呼んでる、引数ひとつのってないよ?』
「そこでもうひとつ使うのが、引数の省略。 Version 5.13 ( No.078 ) で
教えたように」
『そっか、引数に = で値入れとくと、それは省略できるんだ。それだと、
省略して引数ひとつだけにできるのは』
HTREEITEM InsertItem
( LPCTSTR lpszItem
, HTREEITEM hParent = TVI_ROOT
, HTREEITEM hInsertAfter = TVI_LAST
);
『だけだからこれだね』
「そう、このメンバ関数が呼ばれてます」
『質問! これってどうやって選ぶの? 似たような引数のがあったら?』
「これ、自分で〈どのメンバ関数を選ぶ〉っていうのは決められません。関
数に渡した引数の型と数を見て自動的に決められます」
『決められなかったら? 引数が似てたりして、たとえば』
void Test( int p_i );
void Test( int p_i, int p_i2 = 0 );
『で、引数ひとつしか渡さないとか』
「そしたらコンパイルエラーになります。逆に言うと、オーバーロードした
り引数の省略をしたりするときは、似たような引数にならないように作らな
きゃいけないってこと」
『あー、ってことはあたしの例だと、 Test() って関数を作るときに注意し
なきゃいけないのね』
「そゆこと。作っても呼べないからどっちか削ることになるし、この例な
ら」
void Test( int p_i );
「はいらないでしょ」
『そっか、引数省略したらこれと同じになるから』
「もしくは引数の省略をやめるか」
『それって』
void Test( int p_i );
void Test( int p_i, int p_i2 );
『ってことね。でもさっきの方が、関数ひとつだけでいいからいいんじゃな
い?』
「その辺は議論の的だったり……場合によって使い分けが必要だから」
『場合?』
「たとえば、引数を省略したときとしないときとで、呼ばれる関数を変えた
いときとか」
『そっか、引数省略の方だと、関数ひとつだから困るってこともあるんだ』
「その辺は、火美ちゃんがオーバーロード関数を作る時になったらの話だ
ね」
『おお』
「さて話を戻して、さっきの CTreeCtrl::InsertItem() 、省略してた第2
引数に〈これから追加するアイテムの親〉を渡すと、その親の子アイテムと
して追加することができます」
BOOL CMfcDialogDlg::OnInitDialog()
{
// 略。
// TODO: 特別な初期化を行う時はこの場所に追加してください。
HTREEITEM hParentItem
= m_cMainTree.InsertItem( "1番目のアイテム" );
m_cMainTree.InsertItem( "2番目のアイテム", hParentItem );
return TRUE;
}
『 HTREEITEM ってので、さっきのメンバ関数の戻り値受け取ってるね』
「これは頭に H が付いてるとおり」
『ハンドル!』
「なんです。ツリービューコントロールのアイテムを操作するためのハンド
ルで」
『これを第2引数に渡すと、これが親になるから〈2番目のアイテム〉が
〈1番目のアイテム〉の子アイテムになるわけねー』
「ちなみに第2引数を省略すると TVI_ROOT っていうのが渡されます」
『これを渡すと追加したアイテムが親になるわけね』
「ちなみに【ルート】は【根っこ】って意味」
『木の根っこだから親ってわけねー』
/*
Preview Next Story!
*/
『アイテムの追加とか、簡単だね』
「 MFC だからねー」
『またかい! だったら MFC だけでいーじゃん』
「それだとできることが限られちゃうからね」
『できることねー』
「火美ちゃんはどんなアプリ作りたいの?」
『へ? あたし、そーゆーのないよ』
「ないって……」
『というわけで次回』
< Version 8.12 ツリーアイテム >
「につづく!」
『だって水希ちゃんが教えてくれるから勉強してるだけでー』
「それでいいの?」
『いーの』