Version 8.16
API だけでツリーコントロール操作
「さて、今回からまた Version 8.10 ( No.152 )まで使ってた
SimpleDialog に戻ります」
『これから MFC 使わないでやってくわけね』
「でも大丈夫、やり方はほとんど教えてあるから」
『確かに面倒な方法色々教わったからねー』
「その辺を思い出してもらいつつ、 SimpleDialog を開いて、 IDD_MAIN に
ツリービューコントロールを貼り付けて」
『ほい。 ID は IDC_TREE_MAIN でいい?』
「そうだね、その方が分かりやすいかな。あと、プロパティの【スタイル】
ページで【ボタンあり】と【線を表示】と【最上位にも線を表示】」
『 Version 8.11 ( No.153 ) と同じね。そのあとは…… MFC の時は
InitDialog() でアイテムを追加したけど』
「それと同じことをします。 InitDialog() は WM_INITDIALOG ってメッ
セージが送られてきた時に呼ばれるメンバ関数」
『ってことは、ダイアログプロシージャの中で WM_INITDIALOG が来るのを
待ってればいいんだ』
「そゆこと。えーっと、久しぶりだから Main.cpp 全行見ておこうか」
#include <Windows.h>
#include <Commctrl.h> // この行を追加。
#include <stdio.h>
#include "resource.h"
// ダイアログプロシージャ。
BOOL CALLBACK DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
if( p_uiMessage == WM_INITDIALOG )
{
// ダイアログの初期化。
TVINSERTSTRUCT stInsertItem;
stInsertItem.hParent = TVI_ROOT;
stInsertItem.hInsertAfter = TVI_LAST;
stInsertItem.item.mask = TVIF_TEXT;
stInsertItem.item.pszText = "アイテム";
HWND hMainTreeWnd
= GetDlgItem( p_hDlgWnd, IDC_TREE_MAIN );
SendMessage
( hMainTreeWnd
, TVM_INSERTITEM
, 0
, (LPARAM)&stInsertItem
);
return TRUE;
}
else if( p_uiMessage == WM_COMMAND )
{
if( LOWORD( p_wParam ) == IDOK )
{
// OK ボタンが押されました。
EndDialog( p_hDlgWnd, IDOK );
return TRUE;
}
}
return FALSE;
}
// WinMain() 。
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
DialogBox
( p_hInstance
, MAKEINTRESOURCE( IDD_MAIN )
, NULL
, DialogProc
);
return 0;
}
『こうやって見てみると長いねー』
「っていうより、1行で書いてもいいところを複数行に分けてるから長い、
っていう方が正しいかも」
『水希ちゃんはいつもこういうふうに書いてるの?』
「そうだよ。特に関数の引数の所はこういうふうに改行して、いつもはそこ
にコメント加えてるんだけどね」
『相変わらずまめねー』
「そうかな……」
『んっと、前と変わってるとこってどこ?』
「まず」
#include <Windows.h>
#include <Commctrl.h> // この行を追加。
#include <stdio.h>
『インクルードファイルが増えてるね』
「ツリービューコントロールを使う時には Commctrl.h ってファイルをイン
クルードしなきゃいけないから」
『 MFC は勝手にインクルードしてくれてる?』
「そう。ちなみに Commctrl.h は〈コモンコントロール〉を使う時にインク
ルードするヘッダーファイルです」
『……あ、なんかデジャブ……』
「 Version 3.10 ( No035 ) で教えてたね……」
『次の違いは?』
「ダイアログプロシージャの中の WM_INITDIALOG のところ」
if( p_uiMessage == WM_INITDIALOG )
{
// ダイアログの初期化。
TVINSERTSTRUCT stInsertItem;
stInsertItem.hParent = TVI_ROOT;
stInsertItem.hInsertAfter = TVI_LAST;
stInsertItem.item.mask = TVIF_TEXT;
stInsertItem.item.pszText = "アイテム";
HWND hMainTreeWnd
= GetDlgItem( p_hDlgWnd, IDC_TREE_MAIN );
SendMessage
( hMainTreeWnd
, TVM_INSERTITEM
, 0
, (LPARAM)&stInsertItem
);
return TRUE;
}
「これだけ長いと、別の関数にした方がいいかも」
『えっと、中身は Version 8.13 ( No.155 ) のに似てるね』
「 TVINSERTSTRUCT のメンバ変数に色々入れてる部分は同じ」
『 GetDlgItem() はどっかで見覚えが……あ、ダイアログコントロールのハ
ンドルを取るのだ!』
「 Version 5.26 ( No.091 ) で教えたけど、あれは CWnd::GetDlgItem()
つまり MFC のだから」
『そだね、あのときはポインタだったけど、今度の API のはウィンドウハ
ンドルが返ってきてる。それに引数も違う』
「第1引数が加わってて、この第1引数に、コントロールを持ってるダイア
ログのハンドルを渡します」
『 CWnd::GetDlgItem() の時は渡さなくていいの?』
「 CWnd の中にメンバ変数として持ってるからね」
『あ、そっか』
「 API では、ダイアログプロシージャの引数として渡された、ダイアログ
のウィンドウハンドルと、ウィンドウハンドルが欲しいコントロールの ID
を渡せば」
『そのコントロールのウィンドウハンドルがもらえるわけね』
「で、そのウィンドウに SendMessage() でツリービューコントロールを操
作するメッセージを送ります」
『そっか、メッセージを受け取るのがダイアログプロシージャ、メッセージ
を送るのは SendMessage() 、って分担するんだ』
「そゆこと。 Version 8.12 ( No.154 ) でちょっと触れたけど、 TVM_ が
ツリービューコントロールを操作するためのメッセージ」
『 TVM_INSERTITEM がアイテムをインサートするメッセージね。
CTreeCtrl::InsertItem() と同じ機能、ってゆーかこのメンバ関数も
TVM_INSERTITEM を SendMessage() してるってこと?』
「そゆこと。 CTreeCtrl::InsertItem で検索すると見つかるから」
『んじゃ見とこう。おー、ホントに同じ感じに SendMessage() してる』
「この SendMessage() の LPARAM に TVINSERTSTRUCT 構造体へのポインタ
を渡せば、その構造体どおりのアイテムが追加されます」
『なんか無理矢理。 WPARAM と LPARAM 使う時ってこれって仕方ないの?』
「残念ながら、ね」
『しょうがないならいーや。これで追加できた、と。他の変更点は?』
「ないよ。 else if の所は OK ボタンを押した時にダイアログを閉じるの
だし」
『 Version 8.09 ( No.151 ) のと同じね』
「 WinMain() は変化なし。今回の中で大事な部分は WM_INITDIALOG の所だ
から」
『これだけ見ると、ホントにこれまでのの応用だけだね』
「そうだよ。 TVINSERTSTRUCT は MFC の方で使ってもらったし、メッセー
ジですべてやりとりするってことが分かってれば」
『混乱はしないかな。でもめんどいね』
「それは仕方ないね。この辺が MFC の便利な部分だから」
『あ! 最後に質問!』
「はい火美ちゃん」
『まだ教えてもらってなかった、 WPARAM と LPARAM の W と L ってなんな
の?』
「あ、そういえば。これは僕も確かなことは知らないんだけど、昔、つまり
ウィンドウズ95より前の頃の名残みたい」
『お、また昔話ね』
「ウィンドウズ3.1から95って大きく変わったからね。あ、これは次の
回にちゃんと説明しよう!」
『え?』
/*
Preview Next Story!
*/
「というわけで次回は歴史の時間です」
『そんなの必要なの?』
「僕は必要かな」
『どして?』
「理由が分かるから」
『理由?』
「そう、なんでそういう名前なのか、とかの理由が」
『というわけで次回』
< Version 8.17 ウィンドウズの歴史 >
「につづく!」
『理由なんて分かんなくてもいいんじゃない?』
「ま、それはそれで」