#pragma twice

KAB-studio > プログラミング > #pragma twice > 161 Version 8.19 MFC を使わずにアイテムを取得!

#pragma twice 161 Version 8.19 MFC を使わずにアイテムを取得!

前のページへ 表紙・目次へ 次のページへ

 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 アプリを作ろう! >
「につづく!」
『似てるんならパスしよ、パス』
「だから似てないんだって……」
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。