#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のトップページをご覧ください。