Version 8.19
MFC を使わずにアイテムを取得!
「ではさっそく前回の続きを」
『あと関数が3つあったもんね』
「まずはその中の一番簡単なのから」
// OK ボタンが押されました。
BOOL OnOk( HWND p_hDlgWnd )
{
EndDialog( p_hDlgWnd, IDOK );
return TRUE;
}
『 OK ボタンを押したら閉じるってヤツね』
「今回は OK ボタンだけだど、本当はxボタンに対応するために IDCANCEL
にも対応させた方がいいかな」
『 Version 8.09 ( No.151 ) のね』
「では次、ダイアログの初期化」
// ダイアログの初期化。
BOOL OnInitDialog( HWND p_hDlgWnd )
{
TVINSERTSTRUCT stInsertItem;
stInsertItem.hParent = TVI_ROOT;
stInsertItem.hInsertAfter = TVI_LAST;
stInsertItem.item.mask = TVIF_TEXT;
stInsertItem.item.pszText = "1番目のアイテム";
HWND hMainTreeWnd
= GetDlgItem( p_hDlgWnd, IDC_TREE_MAIN );
HTREEITEM h1stItem
= (HTREEITEM)SendMessage
( hMainTreeWnd
, TVM_INSERTITEM
, 0
, (LPARAM)&stInsertItem
);
stInsertItem.item.pszText = "2番目のアイテム";
SendMessage
( hMainTreeWnd
, TVM_INSERTITEM
, 0
, (LPARAM)&stInsertItem
);
stInsertItem.hParent = h1stItem;
stInsertItem.item.pszText = "1−1番目のアイテム";
SendMessage
( hMainTreeWnd
, TVM_INSERTITEM
, 0
, (LPARAM)&stInsertItem
);
return TRUE;
}
『長い……けど、 Version 8.16 ( No.158 ) と同じね』
「あのときと同じことを3回してるってだけ」
『じゃ、最後のねー』
// アイテムの選択が変更された時。
BOOL OnSelchangedTreeMain( NM_TREEVIEW *p_pstNmTreeView )
{
char pchText[256];
TVITEM stTvItem;
stTvItem.mask = TVIF_TEXT;
stTvItem.hItem = p_pstNmTreeView->itemNew.hItem;
stTvItem.pszText = pchText;
stTvItem.cchTextMax = 255;
SendMessage
( p_pstNmTreeView->hdr.hwndFrom
, TVM_GETITEM
, 0
, (LPARAM)&stTvItem
);
OutputDebugString( pchText );
OutputDebugString( "\n" );
return 0;
}
『どっかで見たような、そうじゃないような……』
「これは Version 8.15 ( No.157 ) の〈今選択されているアイテムの情報
を取得する方法〉を MFC を使わずにしているんです」
『そういえばちょっと似てる……けど結構違うかな』
「そうだね、まずこの OnSelchangedTreeMain() って関数から」
『前回のを見ると、選択してるアイテムを変えるとこの関数が呼ばれるよう
になってるんだよね』
「そう、 TVN_SELCHANGED 通知メッセージが送られてきたらディスパッチす
るようにしてるからね」
『その時の LPARAM が NM_TREEVIEW にキャストされて渡されてるのね。こ
の辺は Version 8.15 と同じ?』
「同じ。あのときは LPARAM は出てこなかったけど、実際にはこういうふう
に LPARAM から NM_TREEVIEW のポインタにキャストできるから」
『つまり LPARAM から NMHDR のポインタにもキャストできるわけね』
「そゆこと。次の TVITEM の準備は Version 8.15 のと同じ。そのあとの」
SendMessage
( p_pstNmTreeView->hdr.hwndFrom
, TVM_GETITEM
, 0
, (LPARAM)&stTvItem
);
『これがつまり』
m_cMainTree.GetItem( &stTvItem );
『の代わりなわけね』
「そう、コントロールの操作はさっきの OnInitDialog() で
TVM_INSERTITEM したようにメッセージを送ってします」
『で、アイテムの情報をもらうのが TVM_GETITEM なわけね』
「 TVM_INSERTITEM と使い方はほとんど同じだから大丈夫かな。こうやって
TVM_GETITEM メッセージを送ることで、 stTvItem の中に情報を入れてくれ
ます」
『あ』
( p_pstNmTreeView->hdr.hwndFrom
『がちょっと難しいかも』
「じゃ、ひとつずつ分けて」
p_pstNmTreeView->hdr
「これは NM_TREEVIEW の hdr 変数を指してます」
『ポインタだから -> なんだよね』
「そう。この hdr は NMHDR 構造体で、この中の hwndFrom 変数を指してい
るのが」
hdr.hwndFrom
「の部分」
『 -> が . になるのよね……』
「そう、前も言ったけど、この時点ではもう p_pstNmTreeView のことは忘
れて hdr だけを見て。 hdr はポインタじゃなくて普通の変数だから」
『 -> じゃなくて . なわけね』
「そゆこと。この hwndFrom には〈通知メッセージを送ってきたコントロー
ルのウィンドウハンドル〉が入ってるから」
『このウィンドウハンドル宛にメッセージを送ればいいわけね』
「あ、もちろんこの通知メッセージは TVN_SELCHANGED のことだから」
『質問!』
「はい火美ちゃん」
『さっきの MFC の例ではこの hwndFrom って使わなかったよね。なん
で?』
「ん、そうだね、結論から言えば」
m_cMainTree.GetItem( &stTvItem );
「の方が間違い」
『げ、そうなの?』
「まず、どのツリービューコントロールから送られてきた通知メッセージか
どうかはこの hwndFrom を見ないと分からない、っていうのを憶えて」
『ほい憶えた』
「ってことは、ツリービューコントロールが複数あったら、その複数のツ
リービューコントロールから送られてきた通知メッセージが、この
OnSelchangedTreeMain() に送られてくるってこと」
『げ、つまりいろんなツリービューコントロールのがごちゃ混ぜになって
入って来るんだ』
「だから、実際には hwndFrom を見てどう処理するか決めなきゃいけないわ
け。理想はコントロール毎に別の関数にディスパッチすることだね」
『ダイアログプロシージャのとこで振り分けちゃうわけね』
「で、今回の例ではツリービューコントロールはひとつだけだから、どんな
通知メッセージも、どのツリービューコントロールから送られてきたかは
はっきりと分かってるわけ」
『それが m_cMainTree なわけね』
「そゆこと。だからここでは問題ないってこと。あ、それに、これは MFC
の問題じゃないからね」
『そなの?』
「 m_cMainTree の代わりに、 m_cMainTree の中に入ってるツリービューコ
ントロールのハンドルを操作する、ってことなら今の例でもできるから」
HWND hMainTreeWnd
= GetDlgItem( p_hDlgWnd, IDC_TREE_MAIN );
『 OnInitDialog() の中のだね。あ、そっか、これがそのツリービューコン
トロールのハンドルなんだ』
「そゆこと。だから、今回みたいにツリービューコントロールがひとつだけ
なら、 hwndFrom を使わずにこの hMainTreeWnd を使うって手もあるわけ」
『ひとつだけならそれも許されるわけね』
「あ、そうそう、当たり前って言えば当たり前だけど、 hMainTreeWnd と
hwndFrom は値が同じ、つまり hMainTreeWnd == hwndFrom だから」
『おー、なるほど。同じツリービューコントロールだからハンドルも同じな
んだ。あ! もしかしてそれで通知メッセージがどこから送られてきたか調
べるとか?』
「あ、ううん、 NMHDR 構造体に idFrom ってメンバ変数があって、これが
送信元コントロールの ID になってるから」
『なんだ、便利なのがあるんだ。これと IDC_TREE_MAIN が同じか調べれば
いいわけね』
「そゆこと。というわけでダイアログプロシージャの話はここまで!」
『おお』
「最後になるけど、こういうふうに MFC を使わないでプログラムすること
を〈 SDK だけで作る〉って言います」
『 SDK って Version 5.31 ( No.096 ) のだね』
「そうそう。あ、同じく〈 API だけで作る〉とも言うから。こういう、
MFC を使わない、 SDK だけで作る知識は MFC を使う時でも必要だから、
しっかりマスターしておいてね」
『 MFC も SDK 使ってるから、だよね?』
「そゆこと」
/*
Preview Next Story!
*/
『とゆーわけで次回からは新章!』
「次回からは SDI アプリケーションについて見ていきます」
『って、それならさっきやったじゃん』
「 SDK じゃなくて、 SDI 」
『似たようなもんじゃないの?』
「全然違います」
『というわけで次回』
< Version 9.01 SDI アプリを作ろう! >
「につづく!」
『似てるんならパスしよ、パス』
「だから似てないんだって……」