Version 8.13
構造体の使い方
「まずは前回の復習から!」
BOOL CMfcDialogDlg::OnInitDialog()
{
// 略。
// TODO: 特別な初期化を行う時はこの場所に追加してください。
HTREEITEM hParentItem
= m_cMainTree.InsertItem( "アイテム" );
// TVITEM 構造体の初期化。
char pchText[256];
TVITEM stTvItem;
stTvItem.mask = TVIF_TEXT; // 文字列だけ取得。
stTvItem.hItem = hParentItem; // 取得したいアイテム。
stTvItem.pszText = pchText; // 文字列を受け取る配列。
stTvItem.cchTextMax = 255; // そのサイズ。
// 実際に受け取ります。
m_cMainTree.GetItem( &stTvItem );
TRACE( "%s\n", pchText );
// アイテム
return TRUE;
}
『これでアイテムの文字列を取るんだよね。でも結構面倒……』
「 in と out 、つまりこっちから渡すデータとウィンドウズから渡される
データが同じ構造体に入ってるからねー。っていうか」
『ってゆーか?』
「この辺は TVITEM のリファレンス見てもよく分からないかも」
『英語だから?』
「それを差し引いても。こういうのはサンプルとか見るしかないかもね」
『水希ちゃんのコードもサンプルコード?』
「一番基本的なことだけだけどね。さて、前回ちょっとギリギリだったか
ら、またゆっくり見てみます」
『ほいほい』
char pchText[256];
TVITEM stTvItem;
『文字配列と TVITEM 構造体の変数作ってるね』
「では次」
stTvItem.mask = TVIF_TEXT; // 文字列だけ取得。
『これは〈どのデータをもらうか〉を指定するビットフラグなんだよね』
「今回はアイテム名が欲しいから TVIF_TEXT 。リファレンス見ると分かる
とおり、いろんなメンバ変数が TVITEM にはあるから、その中のどれを渡し
てもらうかを TVITEM::mask で指定します」
『 TVIF_IMAGE とか、イメージリストとか書いてあるけどこれってなに?』
「ツリービューコントロールって普通はアイコンが付いてるでしょ」
『うん付いてる。あー、そのアイコンのこと?』
「そうそう。今回は面倒だからこのイメージリストの使い方はパス」
『結構面倒?』
「まーね。次」
stTvItem.hItem = hParentItem; // 取得したいアイテム。
『データを取りたいアイテムのハンドルをこれで指定するんだよね』
「そうそう。リファレンス見ると何気なくこのメンバ変数があるからなんか
受け取りそうだけど」
『これで指定するわけねー』
「次」
stTvItem.pszText = pchText; // 文字列を受け取る配列。
『これってちょっとややこしいかも』
「まず、文字列を受け取るためには文字配列を用意してそのポインタを渡し
ます、ってのは分かるよね」
『もちろん』
「構造体のメンバ変数で文字列を受け取る場合、その構造体の中に文字配列
を用意することもできるんだけど、それだとサイズが固定でしょ」
『アイテムの文字列が長いと受け取れない!』
「そゆこと。だから、文字配列は構造体の外に置くわけ。」
『で、そのポインタを構造体に入れると』
「ウィンドウズはそのポインタの指す先に文字配列があるって見なして、そ
こに文字列を書き込みます」
『ポインタはこーゆーのに便利ねー』
「そのためのものだしね。で、〈文字配列とみなす〉としても、ポインタが
指す先はただのメモリ、そのメモリのどの範囲が文字配列なのかどうか不安
だから」
stTvItem.cchTextMax = 255; // そのサイズ。
『でどこまでが文字配列かっていうのを教えるわけね』
「ここまでが構造体の準備。で、」
m_cMainTree.GetItem( &stTvItem );
「でデータをウィンドウズから渡してもらいます」
『簡単って言えば簡単だけど……他のメンバ変数のことが気になるなー』
「それはパス。というわけで、今度は追加の方をしてみましょう」
『ってゆーかそれが目的なんだもんね』
「追加には TVINSERTSTRUCT って構造体を使います」
『うお、また新しい構造体が!』
「って言っても、メンバ変数が3つ入ってるだけ。ひとつは TVITEM 。この
中に追加するアイテムのデータを渡します」
『 "アイテム" とか?』
「そうそう。ふたつめのメンバ変数は TVINSERTSTRUCT::hParent 。これは
この前使った CTreeCtrl::InsertItem() の第2引数」
『追加するアイテムの親アイテム!』
「そゆこと。ってことは、みっつめのメンバ変数は」
『 CTreeCtrl::InsertItem() の第3引数、ってことは縦のどこにアイテム
を追加するか!』
「ってこと。これが TVINSERTSTRUCT::hInsertAfter ってメンバ変数になり
ます。というわけで実際のコードを見てもらいましょう」
BOOL CMfcDialogDlg::OnInitDialog()
{
// 略。
// TODO: 特別な初期化を行う時はこの場所に追加してください。
TVINSERTSTRUCT stInsertItem;
stInsertItem.hParent = TVI_ROOT;
stInsertItem.hInsertAfter = TVI_LAST;
stInsertItem.item.mask = TVIF_TEXT;
stInsertItem.item.pszText = "アイテム";
HTREEITEM hParentItem
= m_cMainTree.InsertItem( &stInsertItem );
return TRUE;
}
『 TVI_ROOT と TVI_LAST は、前回言ってた省略したときに渡したのだね』
「これを渡すこともできるし、もちろん」
『 CTreeCtrl::InsertItem() で返ってきたアイテムのハンドルを渡すこと
もできるわけね』
「追加するアイテムの情報は TVINSERTSTRUCT::item が TVITEM 型になって
るから、この中に入れます」
『受け取ったときより少ない…… TVITEM::hItem と TVITEM::cchTextMax
がないんだ』
「 TVITEM::hItem は、これから追加するアイテムなんだから」
『ハンドルがあるわけないのね』
「 TVITEM::cchTextMax は、今回は文字列を渡すだけで受け取るわけじゃな
いから」
『サイズ指定する必要がない、と。そういえば TVITEM::pszText にも文字
列そのまま渡してるものね』
「だから渡す時はこれだけでOK。アイコンを付けないし、その他の属性も
要らないから他のメンバ変数も放っておいていいからね」
『んで追加は CTreeCtrl::InsertItem() で……って、さっきと同じメンバ
関数じゃない』
「これはオーバーロードされた関数」
『あ、いつもの文字列とか渡してたのと違うメンバ関数なんだね』
「このメンバ関数は TVINSERTSTRUCT へのポインタを受け取るメンバ関数。
MFC 使わないでアイテムを追加するときには TVINSERTSTRUCT を使うから、
その互換性のためにって感じかな」
『ってことは、また MFC 使わないのに戻ったら TVINSERTSTRUCT 使ってや
るわけね。いつもの便利な方の CTreeCtrl::InsertItem() は使えないで』
「そゆこと。その辺は不便だけどね」
『不便ってゆーか……今は水希ちゃんに教えてもらえたからできたけど、他
のコントロール使ったりするときにはどうすればいいのか分かんないんだけ
ど』
「サンプルコード探してきて調べて試す、それだけ」
『何それ』
「って言うか、僕もツリービューコントロールとかってあまり使わないから
今回も調べながらだから」
『そーゆーもんなの?』
「そーゆーもん。実際、リファレンスとか分かりにくいし」
『ってゆーか、 TVINSERTSTRUCT のリファレンス、全然分からないんだけ
ど』
typedef struct tagTVINSERTSTRUCT {
HTREEITEM hParent;
HTREEITEM hInsertAfter;
#if (_WIN32_IE >= 0x0400)
union
{
TVITEMEX itemex;
TVITEM item;
} DUMMYUNIONNAME;
#else
TVITEM item;
#endif
} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
「これは難しいかもね……これは次回見てみようか」
『わかる?』
「ひとつひとつ教えればたぶん大丈夫だと思うよ。実際、こういうのを読め
るようになる方が大事かもしれないし」
『大事?』
「ここで問題。一番身近なサンプルコードはなんでしょう」
『水希ちゃん!』
「いや、それは置いといて」
『それ以外……』
「答は MFC 」
『 MFC って難しくない?』
「比較的難しくはないと思う……っていうか、他に難しいコードはいくらで
もあるから、 MFC くらいは読めるようにならないとね」
『げげ』
「でも、 MFC が読めれば……たとえば今回の例。 TVINSERTSTRUCT は MFC
使わないときに使う、ってことは、 MFC は TVINSERTSTRUCT を使ってるっ
てこと」
『え? でもあたしが TVINSERTSTRUCT を用意したら……あ! オーバー
ロードのもひとつの方!』
「そゆこと。文字列とかだけ渡したのは、 TVINSERTSTRUCT を用意してその
中に文字列とかを渡してアイテムを追加してます」
『それが読めるようになれば MFC がサンプルコードになる!』
「当面はそれくらいが身近な目標かもね」
/*
Preview Next Story!
*/
『次回は結構難敵っぽいねー』
「そうでもないと思うけど」
『そうなの?』
「プログラミングって、複合的に絡み合うこと少ないから」
『どゆこと?』
「AがBに、CがDにってことはあるけど、A+BがE、は少ないから」
『つまりひとつひとつ憶えておけばいいわけねー』
「というわけで次回」
< Version 8.14 構造体を読み解く >
『につづく!』
「ま、そのひとつひとつ憶えるってのが大変なんだけどね。でも」
『あたしは大丈夫!』
「その辺はちょっとうらやましいかも……」