CTreeCtrlの非選択状態

[戻る]
DIO 2007/06/04(月) 20:55:48
VS2005 MFC_SDI WinXP

いつもお世話になります。

チェックボックスとアイコンつきの
CTreeCtrl(正確にはCTreeView)があります。
質問は2点


1.TreeCtrlのアイテムを、操作できなくしたい。

つまり特定のアイテムをチェックボックスを含めて、
CEdit ed;
ed.EnableWindow(false)
のようなことがしたいです。

具体的には、任意のフォルダとその中にあるファイルが
ツリーに読み込まれていて、
親のフォルダのチェックをはずすと、そのサブアイテム全部を
非選択状態?(操作できない)ようにしたいのです。



2.チェックを含めた保存

チェックの状態を含めて、ファイルにツリーを保存し、
読み込んで復元したいのですが、いい方法が浮かびません。
皆さんならどういう方法で実装しますか?

以上、よろしくお願いします。

#http://oshiete1.goo.ne.jp/qa3043530.html
#教えてgooではレスが付かず、こっちに来ました。
#無効は閉じますのでよろしくお願いします。

Blue 2007/06/05(火) 10:08:28
前者だけ。

1. CTreeViewクラスのNM_CLICKイベントをハンドリングし、
   以下のコードを記述。

void CXXXXX::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{
    // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
    NMTREEVIEW *pNMTree = (NMTREEVIEW*)pNMHDR;
    CTreeCtrl& tree = this->GetTreeCtrl();
    TVHITTESTINFO ht = {0};
    DWORD pos = ::GetMessagePos();

    ht.pt.x = LOWORD(pos);
    ht.pt.y = HIWORD(pos);
    ::MapWindowPoints(HWND_DESKTOP, pNMHDR->hwndFrom, &ht.pt, 1);
    tree.HitTest(&ht);

    if (ht.hItem)
    {
        HTREEITEM hParent = tree.GetParentItem(ht.hItem);
        if (hParent && !tree.GetCheck(hParent))
        {
            *pResult = TRUE; // TRUE(!=0)にすると選択状態にならない
            return;
        }
    }
    
    // チェックボックスクリックイベント
    if (TVHT_ONITEMSTATEICON & ht.flags)
        tree.Invalidate();
    
    *pResult = 0;
}

2. (選択できないぽく見せるため、ノードのテキストをグレイにするため)
   CTreeViewクラスの NM_CUSTOMDRAWイベントをハンドリングし、
   以下のコードを記述。
   ※カスタムドローではチェックボックスの表示まで変更できない。
   
void CXXXXX::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMTVCUSTOMDRAW lpCustomDraw = (LPNMTVCUSTOMDRAW)pNMHDR;
    CTreeCtrl& tree = this->GetTreeCtrl();
    HTREEITEM hParent;

    switch (lpCustomDraw->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT:
        *pResult = CDRF_NOTIFYITEMDRAW;
        return;
    case CDDS_ITEMPREPAINT:
    case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
        hParent = tree.GetParentItem((HTREEITEM)lpCustomDraw->nmcd.dwItemSpec);
        // 親にチェックが入っていないか
        if (hParent && !tree.GetCheck(hParent))
            lpCustomDraw->clrText = ::GetSysColor(COLOR_GRAYTEXT);
        return;
    }
    *pResult = 0;
}

親のチェックボックスのチェックをはずしたとき、このチェックをはずす場合は
http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200610/06100043.txt
を参考にOnClickを変更してください。(条件は逆になる)

Blue 2007/06/05(火) 10:43:42
後者は
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200607/06070041.txt
を参考にしてみてください。

ただ、PreCreateWindowでスタイル変更しOnInitialUpdateで表示させようとすると
初回だけ、SetCheckが成功しないようです。(原因はわからないです)

DIO 2007/06/05(火) 21:05:16
Blueさん

返信ありがとうございます。

なるほど〜
マウスのヒットテストでアイテムを持ってきて
制御するのですね。

ひとつわからないのですが
    case CDDS_PREPAINT:
        *pResult = CDRF_NOTIFYITEMDRAW;
        return;

はどうして必要なのでしょうか?
コメントアウトすると動かなくなるので、
必要だということぐらいしか・・・

多分、
   *pResult

が何をしているかわかってないからだと思いますが。
      
それに関連して、
 *pResult = TRUE; // TRUE(!=0)にすると選択状態にならない

といった情報はどういう方法で手に入れるのでしょうか?

質問ばかりですが、
よろしくおねがいします。

Blue 2007/06/05(火) 23:31:54
NM_CUSTOMDRAW Message
http://msdn2.microsoft.com/en-us/library/ms672574.aspx
をよんでみてください。

> *pResult = TRUE; // TRUE(!=0)にすると選択状態にならない
は、ちょっと試してみたら※できただけで、確証はなかったです。
(らしいをつけておいたほうが良かったですね。)

※リストビューのときに選択させないという処理は、LVN_CHANGINGで*pResultに
TRUEを入れるから、TRUEを入れればできるかなと。
関連スレ)CListCtrlで選択行だけを選択不可にするには? 
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200607/06070085.txt

DIO 2007/06/06(水) 20:42:34
[[解決]]
>Blueさん

返信ありがとうございます。

えーっと、
CDDS_PREPAINTはTreeViewの書き換えの前に送られてきて、
もし、0をかえすと、サブアイテムに描写前にメッセージが飛んでこない。

今回はサブアイテムの描画を変更したいので、
CDRF_NOTIFYITEMDRAW をかえして、

メッセージを飛ばしてもらってる。
であってますか?

おかげさまで、少し理解がすすみました。
ありがとうございました。

古いスレッドには追加発言できません。