VS2005 MFC_SDI WinXP
いつもお世話になります。
チェックボックスとアイコンつきの
CTreeCtrl(正確にはCTreeView)があります。
質問は2点
1.TreeCtrlのアイテムを、操作できなくしたい。
つまり特定のアイテムをチェックボックスを含めて、
CEdit ed;
ed.EnableWindow(false)
のようなことがしたいです。
具体的には、任意のフォルダとその中にあるファイルが
ツリーに読み込まれていて、
親のフォルダのチェックをはずすと、そのサブアイテム全部を
非選択状態?(操作できない)ようにしたいのです。
2.チェックを含めた保存
チェックの状態を含めて、ファイルにツリーを保存し、
読み込んで復元したいのですが、いい方法が浮かびません。
皆さんならどういう方法で実装しますか?
以上、よろしくお願いします。
# http://oshiete1.goo.ne.jp/qa3043530.html
#教えてgooではレスが付かず、こっちに来ました。
#無効は閉じますのでよろしくお願いします。
前者だけ。
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を変更してください。(条件は逆になる)
後者は
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200607/06070041.txt
を参考にしてみてください。
ただ、PreCreateWindowでスタイル変更しOnInitialUpdateで表示させようとすると
初回だけ、SetCheckが成功しないようです。(原因はわからないです)
Blueさん
返信ありがとうございます。
なるほど~
マウスのヒットテストでアイテムを持ってきて
制御するのですね。
ひとつわからないのですが
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW;
return;
はどうして必要なのでしょうか?
コメントアウトすると動かなくなるので、
必要だということぐらいしか・・・
多分、
*pResult
が何をしているかわかってないからだと思いますが。
それに関連して、
*pResult = TRUE; // TRUE(!=0)にすると選択状態にならない
といった情報はどういう方法で手に入れるのでしょうか?
質問ばかりですが、
よろしくおねがいします。
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
>Blueさん
返信ありがとうございます。
えーっと、
CDDS_PREPAINTはTreeViewの書き換えの前に送られてきて、
もし、0をかえすと、サブアイテムに描写前にメッセージが飛んでこない。
今回はサブアイテムの描画を変更したいので、
CDRF_NOTIFYITEMDRAW をかえして、
メッセージを飛ばしてもらってる。
であってますか?
おかげさまで、少し理解がすすみました。
ありがとうございました。