いつもお世話になっています。
TreeViewにアイテムを選択すると、このアイテム名を知りたい。
例
void MyTreeView::OnTvnItemexpanded(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
CTreeCtrl& ctrl = GetTreeCtrl();
CString str_ = ctrl.GetItemText(pNMTreeView->itemNew.hItem);
AfxMessageBox(str_) ;
}
正常にアイテム名が取得できました。
同じく
void MyTreeView::OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
CTreeCtrl& ctrl = GetTreeCtrl();
CString str_ = ctrl.GetItemText(pNMTreeView->itemNew.hItem);
AfxMessageBox(str_) ;
}
取得できません str=””
void MyTreeView::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO : ここにコントロール通知ハンドラ コードを追加します。
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
CTreeCtrl& ctrl = GetTreeCtrl();
CString str_ = ctrl.GetItemText(pNMTreeView->itemNew.hItem);
AfxMessageBox(str_) ;
*pResult = 0;
}
も取得できません str=””
目的:左側TreeViewのフォルダをクリッリすると
右側にファイルを表示することです。
よろしくお願いします。
環境:XP 。Net MFC
NM_CLICK、NM_DBLCLK のリファレンスを見てください。
http://msdn.microsoft.com/en-us/library/bb773466.aspx
http://msdn.microsoft.com/en-us/library/bb773475.aspx
pNMHDR を LPNMTREEVIEW にキャストしていいなんてどこにも書いてありません。
アイテムを選択したときに取得したいのであれば、TVN_SELCHANGED ハンドラを作りまし
ょう。
あくまでクリックないしはダブルクリックでやりたい場合は、CTreeCtrl::HitTest でマ
ウス座標からアイテムを求めなければなりません。
aetosさん
ご回答ありがとう。
void MyTreeView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{。。。
}
で、取得できました。
>あくまでクリックないしはダブルクリックでやりたい場合は、CTreeCtrl::HitTest でマ
>ウス座標からアイテムを求めなければなりません。
使い方がわかっていません。
OnTvnSelchanged()を使うと最初起動する時に呼んでいますが、
それがほしくないです。只、マウスを選択するだけに呼んでほしい。
これが回避の方法があるのでしょうか。
よろしくお願いします。
単純に考えるなら呼ばれるのはしかたがないから
必要なときだけ処理するようにすれば良いとか。
この辺は柔軟に考えて良いと思います。
実際の話、起動時にも呼ばれるようなパターンは
他のイベントでも結構あります。
PATIOさん
ご回答ありがとう。
static BOOL m_Post_flag = FALSE;
if(!m_Post_flag)
m_Post_flag=TRUE;
else
pFrameWnd->PostMessage( WM_CHNG_VIEW, 0, 1);
で解決しましたが、最適なことかどうかわかりません。
追加質問:
パース名を取得できるのでしょうか。
(F:\\フォルダ1\\フォルダ2\\...\\adf.txt)
よろしくお願いします。
訂正
>パース名
パス名
> 使い方がわかっていません。
void MyTreeView::OnNMDblclk(NMHDR */*pNMHDR*/, LRESULT *pResult)
{
DWORD dwPos(::GetMessagePos());
CPoint pos(GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos));
CTreeCtrl& ctrl = GetTreeCtrl();
ctrl.ScreenToClient(&pos);
UINT uFlag(0);
HTREEITEM hItem = ctrl.HitTest(pos, &uFlag);
CString strSelect = ctrl.GetItemText(hItem);
AfxMessageBox(strSelect);
*pResult = 0;
}
考え方次第と言う気もしますけれど。
そのイベントで呼ばれる最初の一回だけを対象外にしたいと
考えるか、ツリービュウへの最初のデータセットが終わった以降
のイベントを処理対象と考えるかで制御の仕方は変わってきます。
結果的に両者が同じになるケースもあると思いますから
常に同じ結果になるのであれば、簡単な方で代替と言うのもあり
でしょう。意味付けを重視するなら方法論も自ずと決まるでしょう。
パス名の質問に関しては質問の意図がわかりません。
何処から取得するつもりなのでしょう?
アイテムに設定されていない情報は取得できませんとしか言いようがありませんが。
各アイテムにフォルダとかファイル単位で設定しているのなら
自分で全部取得して繋げるしかないのではと思います。
maruさん、PATIOさん
ご回答ありがとう。
>void MyTreeView::OnNMDblclk(NMHDR */*pNMHDR*/, LRESULT *pResult)
>{
>}
本当にありがとう。
正直に言って、いくらに質問にしてもコードが書かないです。
ヒントこない。
これが一番に困っていること。
>パス名の質問に関しては質問の意図がわかりません。
目的としては、左側のフォルダをクリックと
右側にファイルなどを表示したい。
やることが2通りです。
1.左側にフォルダなど検索する時に、その情報を保管する。
例
1.フォルダ1
2.ファイル1~ファイル10
3.フォルダ1¥フォルダ2
4.フォルダ1¥フォルダ2¥ファイル1~ファイル10
など
問題:保管した情報を確実に右側に表示すること。
保管内容:
typedef struct _MU_COMMON
{
int id; //0,1,2....
CString type; //file or dir
CString PathName; //fileName Or DirName
CString IndexsName; //filePath
} MU_COMMON;
今考えたことは
左側のあるフォルダをクリックして、そのフォルダ名を取得し、
保管関数に保存してあるフォルダ名を比較して、一致した場合、
そのフォルダ階層のファイルを右側に表示すること。
やってみたら、フォルダ名だけだめです。
フォルダ名が同じの場合多いです。(例:Debug)
階層の深さを確認することで、ファイルパスが必要になりました。
例:
p_size = pGGs->GetCommonDataMuSize( index); //保管関数のSize取得
CString pathName=pGGs->m_DirName; //左側のフォルダ名
for(int i=0; i<p_size; i++){
p =pGGs->GetCommonDataMu( i);
fpath =p->IndexsName;
if ( ( n = fpath.ReverseFind( '\\')) >= 0){
fname = fpath.Left( n + 1); //パス名洗い出す
}
else{
fname = fpath;
}
if(fname == pathName){
//成功、ファイルを表示
・・・・
}
}
問題は、pathName=フォルダ名ですが、階層の情報が持っていない。
どうしたら困っています。
よろしくお願いします。
追記
2、左のフォルダ名を取得して、ふただびにファイルを検索すること。
検束されたファイルを右側に表示する。
2方法ですが、皆さんがどうやっているのでしょうか
正しい考え方なのでしょうか。
もっと簡単な方法があるのでしょうか。
よろしくお願いします。
前のコードは */*pNMHDR*/ でコンパイルエラーになるってことかな?
void MyTreeView::OnNMDblclk(NMHDR * /*pNMHDR*/, LRESULT *pResult)
{
DWORD dwPos(::GetMessagePos());
CPoint pos(GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos));
CTreeCtrl& ctrl = GetTreeCtrl();
ctrl.ScreenToClient(&pos);
UINT uFlag(0);
HTREEITEM hItem = ctrl.HitTest(pos, &uFlag);
bool bIsDir = (ctrl.GetChildItem(hItem) != NULL) ? TRUE:FALSE;
// ITEMにはフォルダ名またはファイル名が入っている
CString strPath = ctrl.GetItemText(hItem);
while ((hItem = m_tree_ctrl.GetParentItem(hItem)) != 0)
{
strPath = m_tree_ctrl.GetItemText(hItem) + _T(\\) + strPath ;
}
if (bIsDir )
{ // 作成されたstrPathをフォルダ名として使用する。
} else
{ // 作成されたstrPathをファイル名として使用する。
}
*pResult = 0;
}
具体的なサンプルコードがほしいと言う話であれば、私は降ります。
サンプルコードを提示すれば、細かい説明は無くても
動かすことは可能でしょうけれど、
C++言語の文法の知識とMSDNで各クラスと関数の利用方法を
調べれば、全くわからないと言う事は無いと思っています。
こういう方法でできると思うのだけれど、どうでしょうと
言う話ならわかりますけれど。
今までの中身を見る限りでは少なくともC++言語の文法はわかっていて
MSDNを読む事はできると思っています。
自分でやるべき部分があるように思えます。
書き込まれている内容を見ていると
仕組み作りの部分をすっ飛ばしているような気がします。
単純にコントロールの組合せだけで何とかしようとしていませんか?
ちゃんと制御する為にはどういう仕組みが必要なのか考えているでしょうか?
もし、ツリーコントロールに設定している内容だけで
フルパスを得ようとしているのであればそれだけでは駄目でしょう
と既に書いています。
選択されているアイテムを元にルートレベルのアイテムまで遡って名称を収集し、
それを繋ぎ合わせるくらいはしないと無理なのではと思います。
何か関数を一つ呼べば済むと言う話では無いと思いますよ。
ちゃんと管理するのであれば、
ツリーコントロールにデータの管理を任せるのではなく、
データを管理する部分とツリーコントロールに表示をする部分は
分けて考えて、データを管理する部分の中身とツリー上のアイテムを
関連付ける方法を考える事です。
で、こういう部分はプログラムを作成する上で御本人が考えるべき
部分です。こういう部分は設計作業に当たりますよね。
この部分を他の人に効くと言う事はこの部分の作業を人に
お願いしているような状態になってしまいます。
まずは自分でどう管理するのかと言う案を提示して
その上でこの部分にこういう問題があると思うけれど、
解決方法はないでしょうかと言うような質問の仕方が必要ではないかと思います。
maruさん、PATIO さん
返事が遅かったすみませんでした。
まず、サンプルありがとう。
感想:TreeViewの最大ポイントは
hItemをどう掴むということ。
ctrl.GetChildItem(hItem)
と
while ((hItem = m_tree_ctrl.GetParentItem(hItem)) != 0)
修正:m_tree_ctrl.GetParentItem(hItem)=>ctrl.GetParentItem(hItem)
でOK
大変勉強になりました。
(説明がなくても、わかっています。)
>まずは自分でどう管理するのかと言う案を提示して
>その上でこの部分にこういう問題があると思うけれど、
>解決方法はないでしょうかと言うような質問の仕方が必要ではないかと思います。
わかりました。
ほんとにありがとうございました。