none
コモンコントロールのツリービューにおいて、子ノード無し状態で展開ボタンを有効にする方法 RRS feed

  • 質問

  • タイトルのとおりの質問なんですが、このようなことは可能でしょうか。

    実現したいことは、特定のノード配下の子ノードたちを親ノードがはじめて展開されたタイミングでロードすることです。
    (ツリービューのスタイルにはTVIS_HAS_BUTTONS付きを前提としています。)

    ---------------------------------------------- イメージ
    ・展開前
    ● PARENT

    ・展開後 (PARENTノードを開いたタイミングで、子ノードをロードして表示)
    ● PARENT
    |
    + CHILD1
    + CHILD2
    ----------------------------------------------

    要するに、展開ボタンの押下を検知するために、子ノードが1件もない状態で展開ボタンを有効にできないかと考えました。
    「ノードのステータスをいじることで、コントロールを騙し、展開ボタンを有効にすることが可能」といったテクニックは無いものでしょうか?

    その他、「未ロードの親ノードにダミーノードを1件だけ追加して展開ボタンを有効にする」といった案を考えてはいますが
    もし、前述したようなテクニックがあるのならば、直感的ではありますが前者の方が簡単そうに思えたので、今回質問させて頂いた次第です。

    以上、ご回答よろしくお願いいたします。
    • 編集済み さんど 2010年1月27日 12:37 文章修正
    2010年1月27日 12:36

回答

  • (ツリービューのスタイルにはTVIS_HAS_BUTTONS付きを前提としています。)
    TVS_HASBUTTONS ですね?

    TreeView_SetItem()で子要素がなくても展開ボタンを[+]にするように設定できます。
    TVIF_CHILDREN. TVITEM.cChildren あたりのキーワードで調べてみてください。
    • 回答としてマーク さんど 2010年1月28日 13:34
    2010年1月27日 15:01
  • それだとノードを閉じて開くたびに、子ノードが追加されてしまいますよ。

    NMTREEVIEW.itemNew.stateのTVIS_EXPANDEDONCEをCheckするか、
    TVITEMEX.lParamにその情報を入れておくとか、何かしら対策が必要になりますね。
    • 回答としてマーク さんど 2010年1月30日 0:30
    2010年1月28日 14:16

すべての返信

  • (ツリービューのスタイルにはTVIS_HAS_BUTTONS付きを前提としています。)
    TVS_HASBUTTONS ですね?

    TreeView_SetItem()で子要素がなくても展開ボタンを[+]にするように設定できます。
    TVIF_CHILDREN. TVITEM.cChildren あたりのキーワードで調べてみてください。
    • 回答としてマーク さんど 2010年1月28日 13:34
    2010年1月27日 15:01
  • ご回答有難うございます。

    記載頂いたキーワードから、『ノード展開時に子ノードをロードする処理』を実現することができました。
    参考までに、ソースの一部を紹介いたします。

    --------------------------------------------------------------------------------
    ●ツリーアイテムの挿入
    
        TV_INSERTSTRUCT tvis;
        tvis.hParent = TVI_ROOT;
        tvis.hInsertAfter = TVI_LAST;
        tvis.item.mask = TVIF_TEXT
                       | TVIF_CHILDREN;
        tvis.item.pszText = (LPTSTR)_T("hogehoge");
    
        // ☆展開ボタンを有効にする
        tvis.item.cChildren = 1;
    
    
    ●TVN_ITEMEXPANDING を受信できるように、メッセージハンドラを追加。※ATLを使用
    
        BEGIN_MSG_MAP( CHogehoge )
            ・・・略
    
            REFLECTED_NOTIFY_CODE_HANDLER(TVN_ITEMEXPANDING , OnNotifyItemExpanding)
            DEFAULT_REFLECTION_HANDLER()
        END_MSG_MAP()
    
        LRESULT OnNotifyItemExpanding(int wParam, LPNMHDR lParam, BOOL bHandled);
    
    ●展開時に子ノードを読み込む
    
    LRESULT CHogehoge::OnNotifyItemExpanding(int wParam, LPNMHDR lParam, BOOL bHandled)
    {
    
        LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
    
        // 対象アイテム
        HTREEITEM hTargetItem = pnmtv->itemNew.hItem;
    
        // ツリービューの対象アイテムが展開されようとしている場合
        if (pnmtv->action == TVE_EXPAND) {
    
            // ここで子ノードを追加する
        }
    
        // 0を返すことで子ノードを展開する
        return 0;
    }
    ----------------------------------------------------------------------
    
    

    ポイントは、TVN_ITEMEXPANDINGを使うということです。(EXPANDEDでは駄目です)
    非常にざっくりなソースで、イメージが伝わりにくいかもしれませんが、以上のような形で処理を実現することができました。

    Atsushi777さん有難うございました。
    • 編集済み さんど 2010年1月28日 13:34 修正
    2010年1月28日 13:33
  • それだとノードを閉じて開くたびに、子ノードが追加されてしまいますよ。

    NMTREEVIEW.itemNew.stateのTVIS_EXPANDEDONCEをCheckするか、
    TVITEMEX.lParamにその情報を入れておくとか、何かしら対策が必要になりますね。
    • 回答としてマーク さんど 2010年1月30日 0:30
    2010年1月28日 14:16
  • kozzさん

    フォロー有難うございます。

    実際には、lParamに読み込み済みフラグのようなものを入れて、再読み込みされないよう対処しています。
    ※上のソースに、それが分かるように書き込んでおくべきでした。

    TVIS_EXPANDEDONCEを使うというのも有りですね。勉強になります。
    2010年1月30日 0:29