#pragma twice

KAB-studio > プログラミング > #pragma twice > 158 Version 8.16 API だけでツリーコントロール操作

#pragma twice 158 Version 8.16 API だけでツリーコントロール操作

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

 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 ウィンドウズの歴史 >
「につづく!」
『理由なんて分かんなくてもいいんじゃない?』
「ま、それはそれで」
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。