CTreeCtrlでアイコンが変化しない

このQ&Aのポイント
  • MSVC++6.0&MFCの環境で、CTreeCtrlを使用してツリーコントロールのアイコンをエクスプローラのフォルダのように開閉する際に、アイコンが変化しない問題が発生しています。
  • OnItemexpanded関数を使用して、ツリービューアイテムが展開または収束したときにアイコンを変更しようとしています。
  • しかし、アイコンは変わらず、表示される文字列は正しく表示されます。解決策をご存知の方は教えてください。
回答を見る
  • ベストアンサー

CTreeCtrlでアイコンが変化しない

環境は、MSVC++6.0&MFCです。 やりたいことは、ツリーコントロールのアイコンをエクスプローラのフォルダのように、 開いたときと閉じたときとで、アイコンを変化させたいのです。 以下は、ソースです。 CTreeCtrlからMyTreeCtrlを派生しています。 テスト用に開いたときは、文字列を"開いた"、閉じたときは、"閉じた"のように変化させるようにしています。 void MyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; if(pNMTreeView->action == TVE_EXPAND){ SetItemState(pNMTreeView->itemNew.hItem , INDEXTOSTATEIMAGEMASK(0) , TVIS_STATEIMAGEMASK); SetItemText(pNMTreeView->itemNew.hItem , "開いた"); }else{ SetItemState(pNMTreeView->itemNew.hItem , INDEXTOSTATEIMAGEMASK(1) , TVIS_STATEIMAGEMASK); SetItemText(pNMTreeView->itemNew.hItem , "閉じた"); } *pResult = 0; } 実行すると、文字は、開いたときは、"開いた"、閉じたときは、"閉じた"とちゃんと表示されますが、 アイコンが変化しません。 お分かりの方、いらっしゃいましたら、教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • mcWalker
  • ベストアンサー率69% (27/39)
回答No.1

レスがないようなので、ご参考になれば。 MFC でやったことはありませんが、 >>アイコンが変化しません。 とあることは、非選択状態ではアイコンは表示されているのですか。 API プログラムではアイコンを変化させるには、hItem の mask に アイコンを2種類登録する指定(TVIF_IMAGE | TVIF_SELECTEDIMAGE)をして、 アイコンデータを ImageList に登録し、その番号を hItem の iImage, iSelectedImage にセットしています。 で、notify が来たとき決める場合は iImage も iSelectedImage も -1 にしてnotify を送るようにしておき、 notify 処理で、image 番号を指定しています。 CTreeCtrl にそれぞれのメソッドがあるでしょう。

miswaki777
質問者

お礼

回答どうもありがとうございます。 実は、別の方法で解決していました。 一定時間たたないと、質問を削除できないようなので...。 次のようにすると、うまくいきました。 void MyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください if(pNMTreeView->action == TVE_EXPAND){ pNMTreeView->itemNew.iImage = 1; pNMTreeView->itemNew.iSelectedImage = 1; SetItem(&pNMTreeView->itemNew); }else{ pNMTreeView->itemNew.iImage = 0; pNMTreeView->itemNew.iSelectedImage = 0; SetItem(&pNMTreeView->itemNew); } *pResult = 0; }

関連するQ&A

  • MSGFILTER lParmで得られるキーコード?

    いつもお世話になっております。 以下のような関数で押されたキーを判定しています。 lParmで得られるキーコードはVK_??のコードと違うようなのですが、 (キーボードの並び方順になってる?) これをVK_??に変換するような方法はあるのでしょうか? (本当はSHIFTデータもプラスして文字コードに変換したいのですが・・・) 何か良い方法があればアドバイスお願いいたします。 void CCtypeView::OnMsgfilterEdit1(NMHDR* pNMHDR, LRESULT* pResult) { MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR); if( pMsgFilter->msg == WM_KEYDOWN ) { SHORT sho = GetAsyncKeyState(VK_SHIFT); TRACE( "%d : \nWM_LBUTTON x=%x,y=%d sho=%x", pMsgFilter->msg, HIWORD( pMsgFilter->lParam), LOWORD( pMsgFilter->lParam), sho ); } *pResult = 0; }

  • CTreeCtrlのHitTestメソッドについて

    環境:WinXP VS2005 MFC使用 CTreeCtrlに階層のあるアイテムを複数個設定しています。 ノード開閉時にカーソル位置にあるアイテムをGetCorsorPos()+HitTest()関数を使用し、取得していました。これは正しいアイテムのハンドルが返ってきています。 ところが、ある程度ノードを開いていき、表示しきれなくなるとスクロールが表示されますが、一番下までスクロールしている状態だとアイテムがうまく取得できていないようです。 おそらく、GetCursorPosが画面上の相対座標を取得するのに対し、HitTestで設定するのはツリーコントロール自体の相対座標なので、スクロールしている分だけずれてしまっているのではないかと思っているのですが、スクロールしているサイズを取得する方法がわかりませんでした。ご存じの方いましたらご教授をお願いします。 ※ソース抜粋 void CTestTreeCtrl::OnTvnItemexpanded(NMHDR *pNMHDR, LRESULT *pResult) { CPoint point; GetCursorPos(&point); ScreenToClient(&point); // マウスカーソルの位置からアイテムのハンドルを取得する HTREEITEM hItem = HitTest(point);           ・           ・           ・

  • VC++6.0 CDateTimeCtrl の暴走について

    開発環境 VC++6.0 WindowsXP Home CDateTimeCtrl(日時指定プロパティ)を使用していますが、 日付を変更した場合はメッセージを表示して、ある処理を行おうと思っています。 ドロップダウンで月のカレンダーを表示させ、 前月または次月などを行います。(何度か同じ処理を繰り返す) 日付が変更されるため、メッセージが表示されます。 「OKボタン」クリック後に自動的に次月→次月→次月・・・・と繰り返されます。 これはバグでしょうか? また、回避策はありますでしょうか? 下記はサンプルプログラムです void クラス::OnDatetimechangeXX(NMHDR* pNMHDR, LRESULT* pResult) { AfxMessageBox( "メッセージ", MB_ICONEXCLAMATION ); } 以上、ご教授よろしくお願いします

  • 右クリックメニューの非活性化

    MFCのCListViewを使用してリストビューのプログラムを作成しています。 で、現在その右クリックメニューを作成しようと思いい、ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)でハンドルし、その中で右クリックメニューの活性、非活性(グレーアウト)の制御を追加したいのですが、その制御がうまくいきません。(例えばある条件下の場合はあるメニューを非活性にする等) 詳しい方がいましたら教えていただけないでしょうか? ちなみに右クリックメニューは以下のようにして出力しています。 void CDebugTool::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) { CMenu cme; cme.LoadMenu(IDR_RCLICKMENU); cme.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTBUTTON|TPM_RIGHTBUTTON, pt.x, pt.y, this); }

  • VC++のLV_KEYDOWNについて

    キーボードのショートカット処理の関数を作成しているのですが、Ctrl + sでデフォルトの保存処理ではなく 別の処理を作成したいと考えております。 ですが下記のように実装してもCtrl + sを検出できません。(Ctrl + a)は検出するのですが。 何か原因があるのでしょうか? ご存知の方がいましたらご教授いただけないでしょうか? void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) { LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR; SHORT nCtrl = 0; switch(pLVKeyDow->wVKey) { case 's': case 'S': nCtrl = GetKeyState(VK_CONTROL); if(nCtrl >= 0) { // Ctrlキーが押下されていない場合 break; } // Ctrl + sの処理 break; case 'a': case 'A': nCtrl = GetKeyState(VK_CONTROL); if(nCtrl >= 0) { // Ctrlキーが押下されていない場合 break; } // Ctrl + aの処理 break; } *pResult = 0; }

  • インライン処理

    VS2008 MFC を使用して、CListCtrlの派生クラスを全てインラインで書きたいと思い、 ・追加->クラス->C++クラス->基本クラス"CListCtrl" + インラインオプションにチェック で作成したのですが、メッセージ処理を追加するとcppファイルが出来てしまいます。 利便性からヘッダファイル単体で使用したいのですが、cppの内容をヘッダに全て書き写し、cppファイルを削除することは出来ないのでしょうか? Ex. <クラス生成直後=ヘッダファイルのみ> #pragma once #include "afxcmn.h" class CTest01 : public CListCtrl { public: CTest01(void) { } virtual ~CTest01(void) { } }; <メッセージ追加後=ヘッダ> #pragma once #include "afxcmn.h" class CTest01 : public CListCtrl { public: CTest01(void) { } virtual ~CTest01(void) { } DECLARE_MESSAGE_MAP() afx_msg void OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult); }; <メッセージ追加後=cpp> #include "StdAfx.h" #include "Test01.h" BEGIN_MESSAGE_MAP(CTest01, CListCtrl) ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CTest01::OnLvnColumnclick) END_MESSAGE_MAP() void CTest01::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // TODO: ここにコントロール通知ハンドラ コードを追加します。 *pResult = 0; } 上記の例でOnLvnColumnclickをヘッダファイルに記述することは可能でしたが、BEGIN_MESSAGE_MAPの辺りと、インクルードをヘッダに移動するとリンク時にエラーが出てしまいます。 メッセージ処理をする場合cppファイルは必須なのでしょうか? ・追加->クラス->MFCクラス->基本クラス"CListCtrl" で作成した場合、上記プラスIMPLEMENT_DYNAMICもインクルードファイル内に記述出来ずに困っています。 MFC初心者のため、いまいちBEGIN_MESSAGE_MAPやIMPLEMENT_DYNAMICの意味がわからず行き詰まっています。 なにかヒント等有りましたら、教えていただけないでしょうか? よろしくお願いいたします。

  • リストコントロールのデータの変更を検知したい

    リストコントロールのデータの変更時に呼び出されるイベントが分かりません、 OnLvnItemchangedList()であっているのでしょうか?もっと簡単に実現できるのなら、 教えてください。 VC++2010 MFC です。 削除のときは、条件なしに、OnLvnDeleteitemList()内でいいのですが、 追加も pNMLV->uChanged == 4 にすれば問題ないです。でもその他は、厳しくしすぎると クリックしただけで、データが変更されたと判断されたり、・・・でうまく行きません。 【リスト上のデータが変更されるケース】 データが変更される場合は、非選択状態から「すべてを置換」するケースや 一個一個 検索(選択)しながら、「置換」するケースがあります。 後は、リストコントロールにエディットボックスを張り付かせて、「編集」(エンターで確定) して、データを変更するケースがあります。 ただし、「すべてを置換」する場合でも、既に選択状態のデータを処理する場合もあり、困っています。 自分で作ったプログラムなのですから、各機能終了時に変更されたか?されてないか?は 分かっているのですが、勉強のため、質問をしました。 PreTranslateMessage()で出来るのでしょうか? (参考サイト: http://isobe.exblog.jp/996027/ ) 【目的】 起動時 から(前回保存時から)リストデータに変化がない場合、何もせずに終了したい 【やりたいこと】 リストの文字が変わったら、キャプションを FileListCreator(*) にすると ともに、ListDataNoChange_FLG = FALSE; にする。 保存ややリカバリ(復帰)を行ったら (*) を取って、 ListDataNoChange_FLG = TRUE; にする。 if ( ListDataNoChange_FLG == TRUE ) //保存処理をスキップする。 【できれば】 あとは、pNMLV->uChanged などの 4とか8とか、定数で記述したいです。 lParamが何を意味しているか?分からないです。教えて下さい。 void CFileListCreatorDlg::OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult) {   LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);   // TODO: ここにコントロール通知ハンドラー コードを追加します。   if (( pNMLV->uChanged == 4 && pNMLV->uNewState == 0 && pNMLV->uOldState == 0 ) //リストコントロールにアイテムが追加した時     || ( pNMLV->uChanged == 8 && pNMLV->uNewState == 3 && pNMLV->uOldState == 0)){ //「すべてを置換」「置換」ボタンを押した時 //「検索」ボタンで検索しただけでも選択状態になる     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 1 )     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 2 )     //|| ( pNMLV->uChanged == 8 && pNMLV->uNewState == 0 && pNMLV->uOldState == 3 )){     ListDataNoChange_FLG = FALSE;//追加 2012.05.13          CFileListCreatorDlg* m_Dlg = (CFileListCreatorDlg*)AfxGetMainWnd();     if( (m_Dlg==NULL)||(m_Dlg->GetSafeHwnd()==NULL) ){       return;     }     m_Dlg->SetWindowText(_T("FileListCreator (*)"));   }   //CString tempStr;   //tempStr.Format(_T("OnLvnItemchangedList iItem: %d, lParam: %d, uChanged: %d, uNewState: %d, uOldState: %d\n"), pNMLV->iItem, pNMLV->lParam, pNMLV->uChanged, pNMLV->uNewState, pNMLV->uOldState);   //MessageBox(tempStr);   *pResult = 0; } void CFileListCreatorDlg::OnLvnDeleteitemList(NMHDR *pNMHDR, LRESULT *pResult) {   LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);   // TODO: ここにコントロール通知ハンドラー コードを追加します。   ListDataNoChange_FLG = FALSE;//追加 2012.05.13   CFileListCreatorDlg* m_Dlg = (CFileListCreatorDlg*)AfxGetMainWnd();   if( (m_Dlg==NULL)||(m_Dlg->GetSafeHwnd()==NULL) ){     return;   }   m_Dlg->SetWindowText(_T("FileListCreator(*)"));   *pResult = 0; } ご教授下さい。

  • アドレス

    利用環境はMFCのVC++6.0です。 void CTestDlg::OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult) { CString str; int num=m_list.GetSelectionMark(); str=m_list.GetItemText(num,0); if(Tstr!=NULL){ *Tstr=str; } CTest2 dlg2; dlg2.DoModal(); ・ ・ ・ } ヘッダ:CString *Tstr; とすると*Tstr=str;がおかしいらしく、アドレスがきちんと渡っていないようです。Tstr!=NULLの所ではアドレスは0xcccccc"???"となっていて if文は意味をなしません。 値を受け取るダイアログでは CTest Tdlg; CString aa; Tdlg.Tstr=&aa; MessageBox(aa); としています。 TestDlgのリストビューの内容をうけとりそれを新しくダイアログを作って そちらに移すプログラムです。

  • 時刻の日時指定コントロールで実行エラー

    時刻の日時指定コントロールで実行エラー MFCでwindowsアプリケーションを勉強しているものです。 OS : Vista Premium VS : 2008 Pro 日時指定コントロールで、日付や時刻を選択する参考書サンプルを動かそうとしています。 結果は、 時刻のDate Time Pickerのスピンコントロールを動かすとエラーが表示されます。 添付画像にあるエラー表示内の 'File: f:\dd\vctools\crt_bld\self_x86\crt\src\output.c ' というファイルは、 C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\ にあるoutput.cのことでしょうか? そうだとしても、今の私のスキルでは解読することができません。 この時刻のコントロールのプロパティは、以下のように設定しました。 ID : IDC_DATETIMEPICKER4 Format : 時刻 Use Spin Control : True ( 淡色表示になっている ) その他は、デフォルト値です。 このコントロールのイベントハンドラコード部分 void CDateTimeCtrlDialog::OnDtnDatetimechangeDatetimepicker4(NMHDR *pNMHDR, LRESULT *pResult) {     LPNMDATETIMECHANGE pDTChange = reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR);     // TODO: ここにコントロール通知ハンドラ コードを追加します。     CTime ct;     m_MonthCal4.GetTime( ct );     m_strDate4.Format( L"%02d:%02d:%02" , ct.GetHour() , ct.GetMinute() , ct.GetSecond() );     UpdateData( false );     *pResult = 0; } どなたか教えてください。 お願いします。

  • CListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップするには

    CListCtrlに表示している複数ファイルを他アプリへドラッグ&ドロップするソースに手間取っていますのでご教授をお願いします。 (VC++ 6.0のサンプルコードがあまりなくて) なんとか、1つのファイルはできるようになったのですが複数にするやり方がわかりません。 どのようにすればよいでしょうか? また、おかしい箇所などありましたら合わせてお願いします。 ※単純の繋げるだけじゃないんですよね?※ CString fname = "C:\\aaa.txt"; fname += "C:\\bbb.txt"; -環境- ・VC++ 6.0 ・MFC ・ダイアログベース -ソース- void aaaDlg::OnBegindragListView(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください if(pNMListView->iItem != -1) { CString fname = "C:\\aaa.txt"; // 動作確認のため固定 HDROP hptr = DragCreateFiles(fname); if (hptr == NULL) { *pResult = 0; return; } m_DropData.CacheGlobalData(CF_HDROP, hptr); CRect rect(0,0,0,0); DROPEFFECT effect = m_DropData.DoDragDrop(DROPEFFECT_COPY, rect); } *pResult = 0; } static HDROP DragCreateFiles (LPCSTR fname) { HDROP hDrop; LPDROPFILES lpDropFileStruct; // Allocate dynamic memory for the DROPFILESTRUCT data // structure and for the extra zero-character identifying // that there are no pathnames in the block yet. int flen = lstrlen(fname); hDrop = (HDROP)GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(DROPFILES) + flen + 2); // If unsuccessful, return NULL if (hDrop == NULL) return(hDrop); // Lock block and initialize the data members lpDropFileStruct = (LPDROPFILES) GlobalLock(hDrop); memset(lpDropFileStruct,0,sizeof(DROPFILES) + flen + 2); lpDropFileStruct->pFiles = sizeof(DROPFILES); lpDropFileStruct->pt.x = 0; lpDropFileStruct->pt.y = 0; lpDropFileStruct->fNC = FALSE; lpDropFileStruct->fWide = FALSE; char* szPathA = (char*) (&lpDropFileStruct[1]); lstrcpy(szPathA,fname); // Unlock the block and return its handle. GlobalUnlock(hDrop); return(hDrop); }

専門家に質問してみよう