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

このQ&Aのポイント
  • リストコントロールのデータの変更を検知する方法について教えてください。また、OnLvnItemchangedList()が正しいイベントかどうかも知りたいです。
  • 削除の場合はOnLvnDeleteitemList()を使用すれば良いですが、追加の場合にはどのように対応すれば良いでしょうか。pNMLV->uChanged == 4 でも問題ないですか?
  • リスト上のデータが変更されるケースについても教えてください。また、PreTranslateMessage()でリストデータの変化を検知することは可能でしょうか?
回答を見る
  • ベストアンサー

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

リストコントロールのデータの変更時に呼び出されるイベントが分かりません、 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; } ご教授下さい。

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

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.5

>BOOL CFileListCreatorDlg::PreTranslateMessage(MSG* pMsg) >のMSG* pMsgとあったので・・・参考サイトを元にに「pMsg->」を追加したのですが、うんともすんともいわないです。 そのダイアログはどのように表示しています? モードレスダイアログでしたらPreTranslateMessage()は有効ですが、 モーダルダイアログの婆とは動作しないっぽいですが。 http://support.microsoft.com/kb/126874/ja # 機械翻訳らしく読みにくいですけどね。 >OnLvnItemchangingListでもOnLvnItemchangedListでもpNMLV->iSubItem==0なので、 >正しく書いたとしても、意味がない気もしますが、もしお時間があればお教え下さい。 前回指摘されたように…カラムクリック時用のメンバかと思われます。 ので、今回の目的ではiSubItemは使えない…ということになるかと。

psychang
質問者

お礼

丁寧にお調べ頂き有難うございました。 機械翻訳のページは、読みました。ちょっと難しいですυ 今、各機能に変更があった場合に、FLGを立てました。これからテストします。 (たいしたことはやっていないですが・・・w) ついでに、カラムを押した時にソートする機能もつけようかと思っています。 さっきの ド・モルガンの法則が、当てはまるなら、 !(LVIS_FOCUSED | LVIS_SELECTED) (!LVIS_FOCUSED & !LVIS_SELECTED) (!LVIS_FOCUSED && !LVIS_SELECTED)かも知れませんね。 冗長ですが、フラグ立てわすれないようにif文をつけてます。  m_Dlg->ListDataNoChange_FLG = FALSE;  CFileListCreatorDlg* m_Dlg = (CFileListCreatorDlg*)AfxGetMainWnd();  if( (m_Dlg==NULL)||(m_Dlg->GetSafeHwnd()==NULL) ){   return;  }  if (ListDataNoChange_FLG == FALSE){   m_Dlg->SetWindowText(_T("FileListCreator (*)"));  } こっちの方がスマートですが・・・  m_Dlg->ListDataNoChange_FLG = FALSE;  AfxGetMainWnd()->SetWindowText(_T("FileListCreator (*)")); 月曜日頃に締め切りたいと思います。長時間付き合ってくれてありがとうございました。

psychang
質問者

補足

補足の欄に失礼します。 >アイテムを追加したときはLVN_INSERTITEMで、削除したときはLVN_DELETEITEMで取れますが… >サブアイテムとかのテキストの変更は通知がなさそうですね。 結論はMFCに、各columnごとのデータ変更を検知する機能はないので、 OnLvnDeleteitemList()やOnLvnInsertitemList()を使用し、後は 自作するという事ですね。 ちょぴり残念ですが、目的の機能は実装できました。 参考URL→ http://wisdom.sakura.ne.jp/system/winapi/windata1.html 以下レスです。 質問に答えてないですねυ 確かにMessageBoxを記述すると、画面が更新されない、画面の一部が欠けるなど、不具合ありますが、用は足ります(!?) 単にTRACE に変えれば良いのですが…後もう少し、もう少しでとして粘っていましたが、結局デバッグした方が早かったですが・・・(おっしゃる様にマニュアルを読むようにと反省していますυ) PreTranslateMessage()の中でcolumnのクリックを検出するのは難しい(特に型を合わすのが、私にとってはまだ難しい)ので、カミナリマーク(管理イベント)で「OnLvnColumnclickList」を追加して、無事ソート機能は完成しました。 参考URL→ http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_LVitemsort.html 後はチェックボックスあり(LVS_EX_CHECKBOXES)にした方が見栄えが良いので あり にします。(表示はなしですが、XP、Vista、7共に具合が良いので) チェックボックスなしにしたら、勿論、統一感がありますが、(解像度の問題があるので、)今の所は良しとして下さいm(_ _)m (古いXP機が廃れて使われなくなったら、また考えます。) ご回答有難うございました。

その他の回答 (4)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.4

>case LVN_COLUMNCLICK: >で、pNMLV->iSubItemを取得できるみたいですが、それでソートするのばかり、 ああ、そっち用のかも知れないですな。 アイテムを追加したときはLVN_INSERTITEMで、削除したときはLVN_DELETEITEMで取れますが… サブアイテムとかのテキストの変更は通知がなさそうですね。 MFCなのでしたら…… CListCtrlを継承したクラスを作って、SetItemText()に細工を入れる…というのはどうでしょう? もっとも、テキストの変更がCListCtrl::SetItemText()をコールして行っている場合に限りますが。

psychang
質問者

補足

ちょっと書き忘れて、繰り返しになってしまうのですが・・・ BOOL CFileListCreatorDlg::PreTranslateMessage(MSG* pMsg) のMSG* pMsgとあったので・・・参考サイトを元にに「pMsg->」を追加したのですが、うんともすんともいわないです。 switch (pMsg->message) { //←先程は書き忘れていました。  case WM_NOTIFY://http://gurigumi.s349.xrea.com/programming/visualcpp/sdk_dialog_listview3.html   switch(((LPNMHDR)pMsg->lParam)->idFrom).//※pMsg->   {    case IDC_LIST: //IDC_LIST←これは間違っていないと思うのですが・・・・     switch (((LPNMLISTVIEW)pMsg->lParam)->hdr.code) //※pMsg->     {       case LVN_ITEMCHANGED:       LPNMLISTVIEW pNMLV;       pNMLV = (LPNMLISTVIEW) pMsg->lParam; //pMsg->lParamがうまく取得できてない??       MessageBox(_T("ここすら通ってないです。"));       //if (pNMLV->hdr.code == LVN_ITEMCHANGED){        if (pNMLV->iSubItem == 2 || pNMLV->iSubItem == 3 || pNMLV->iSubItem == 8){          MessageBox(_T("勿論ここも"));        }       //}      break;     }   }  break; OnLvnItemchangingListでもOnLvnItemchangedListでもpNMLV->iSubItem==0なので、 正しく書いたとしても、意味がない気もしますが、もしお時間があればお教え下さい。 カラム10を作って、時刻を挿入して、現在時刻と比べて、一つでも更新時刻が新しいのなら、 編集したとみなしますか・・・余り時間がかかるなら、毎回保存するようにします。 あともう一歩の気がするのですが、まさか、lvi.mask = LVIF_TEXT| LVCF_SUBITEM;をどこかに書かなければいけないのでしょうか、ListInsertItem()の中に書いてみましたが、pNMLV とどこで関連付けるのかが分かりません。 また、以下のLVS_EX_FULLROWSELECT取ってみてもpNMLV->iSubItem==0でしたυ  m_xcList.SetExtendedStyle( LVS_EX_FULLROWSELECT |  LVS_EX_GRIDLINES); //LVS_EX_CHECKBOXES | //コメント化 2012.05.19 ちなみに、以前質問をして、 http://oshiete.goo.ne.jp/qa/6734007.html で、オーバーロードはうまくいったのですが。。。 (ずっと質問に付き合っていただいてすみません。)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.3

>XP対策で、RedrawWindow();を結構使っているのですが、 >データに変化がなくても、RedrawWindow();を行うと >OnLvnItemchangedList()イベントが発生するのでしょうか? ユーザー操作であろうと、プログラム中での変更であろうと通知されたかと。 # ListView_SetCheckState()でチェックボックスの状態を変更したモノは…通知されてますね。 >ファイル名と備考欄が変更された時のみ、 >つまり、データ変更検知対象をカラムで指定できると助かるのですが・・・ LVIS_FOCUSEDとLVIS_SELECTEDの変動は無視してしまえば良いのではないですか? pNMLV->iSubItemにカラム番号とか入っていたりしませんか? >( pNMLV->uChanged == LVIF_STATE && pNMLV->uNewState == 4096 && pNMLV->uOldState == 0 ) >の4096とは何を表わしているのでしょうか? LVIS_STATEIMAGEMASKで調べるコトをお勧めします。 # LVIS_OVERLAYMASKなんてのもありますのでご注意を。 というか… ># チェックボックスとかつけていたり、設定しているイメージリストによっては他のところも変わりますので、ビット演算で判定して下さいな。 と回答していたりするのですが……LVS_EX_CHECKBOXES付いていたりしませんか? >(!LVIS_FOCUSED | !LVIS_SELECTED) >   と >!(LVIS_FOCUSED | LVIS_SELECTED) >   はとっちが正しい書き方なのでしょうか? 私なら後者で書きますかね。 >リスト上のあるセルの値 と 同じ値 を(同セルに)上書きした場合、チェンジイベントは発生しますか? 変更内容までは関知していなかった…と思いますのでおそらく通知されるでしょう。 # 実際のところはSpy++などで確認を。

psychang
質問者

補足

色々教えていただいて有難うございます。 >LVIS_FOCUSEDとLVIS_SELECTEDの変動は無視してしまえば良いのではないですか? そうですね、その方向で行きたいと思います。 >pNMLV->iSubItemにカラム番号とか入っていたりしませんか? これ、聞きたいです! 私もpNMLV->iSubItemが、使えると思って、 TRACEしてみたのですが、常に0で、インターネットで調べると・・・ case LVN_COLUMNCLICK: で、pNMLV->iSubItemを取得できるみたいですが、それでソートするのばかり、 ヒットしますし、私の考えでは、コラムのキャプション(項目名が書いてある部分)を クリックしたときしか検知できないという風に思いました。 もし、pNMLV->iSubItemを指定できるのなら、 void CFileListCreatorDlg::OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult){}内で・・・  if (pNMLV->iSubItem == 2 || pNMLV->iSubItem == 3 || pNMLV->iSubItem == 8){  //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報 ・・・でカラムを指定しているつもりなのですが、できませんでした。 なにか他にも記述すべきなのでしょうか? 以下も試してみました。 BOOL CFileListCreatorDlg::PreTranslateMessage(MSG* pMsg) {}内で・・・ クリックではなく、データ変更通知を受け取りたいですυ  case WM_NOTIFY: //http://gurigumi.s349.xrea.com/programming/visualcpp/sdk_dialog_listview3.html   switch(((LPNMHDR)pMsg->lParam)->idFrom)   {    case IDC_LIST:     switch (((LPNMLISTVIEW)pMsg->lParam)->hdr.code)     {       case LVN_ITEMCHANGED:       LPNMLISTVIEW pNMLV;       pNMLV = (LPNMLISTVIEW) pMsg->lParam; //pMsg->lParamがうまく取得できてない??       //if (pNMLV->hdr.code == LVN_ITEMCHANGED){        if (pNMLV->iSubItem == 2 || pNMLV->iSubItem == 3 || pNMLV->iSubItem == 8){          MessageBox(_T("1111"));        }       //}      break;     }   }  break; >LVIS_STATEIMAGEMASKで調べるコトをお勧めします。 ># LVIS_OVERLAYMASKなんてのもありますのでご注意を。 >というか… >># チェックボックスとかつけていたり、設定しているイメージリストによっては他のところも変わりますので、ビット演算で判定して下さいな。 と回答していたりするのですが……LVS_EX_CHECKBOXES付いていたりしませんか?  m_xcList.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT |  LVS_EX_GRIDLINES); あ!、使ってます。チェックボックスは画面に表示されていませんが、 プロジェクト全体を検索したら、ずっと前の残骸があり、驚きました。 (同じ事を聞いてすみません。削除します) void CFileListCreatorDlg::OnNMClickList(NMHDR *pNMHDR, LRESULT *pResult){}内で、 最後にクリックした行とカラムは取得できているのですが、関係ないですよね。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

>lParamが何を意味しているか?分からないです。教えて下さい。 リストコントロールにアイテムを追加した時に設定した値…ですね。 MFCだとどのように扱われるのか不明ですが。 http://msdn.microsoft.com/ja-jp/library/8b9s12fc.aspx で、maskにLVIF_PARAMが指定してある必要はありますが。 どの形式でアイテムの追加を行ったか…が問題でしょうかね。 # 特に指定していないのであればLVIF_PARAMは付与されていないでしょうからlParamにも値が設定されていない(0が設定されているというべきか)かと。 ちなみに私だと…リストコントロールに追加した情報(たいてい構造体)へのポインタを設定していたりします。 カラムクリックでソートとかする場合にデータ自体へのアクセスが容易になるので。 もちろん32Bitの値であればなんでも設定できます。 プロジェクトがx86の場合ですが。

psychang
質問者

お礼

お礼欄に失礼します。 どうやら、LVIS_SELECTEDで判断するのは、無理っぽいです。 例えば、「検索」機能でも一旦・・・  m_Dlg->m_xcList.SetItemState(m_Dlg->FindIDX, // 非フォーカス&非選択状態にしたいアイテムのインデックス  !LVIS_FOCUSED | !LVIS_SELECTED, // 状態  LVIS_FOCUSED | LVIS_SELECTED); // マスク ・・・にして、  m_Dlg->m_xcList.SetItemState(index, // フォーカス&選択状態にしたいアイテムのインデックス  LVIS_FOCUSED | LVIS_SELECTED, // 状態  LVIS_FOCUSED | LVIS_SELECTED); // マスク で、一個一個選択しながら、進んで末尾までいったら、終了します。故意に選択状態と非選択状態に しているので、そこで(リスト上のデータに変化はないのですがυ)検出してしまいます。 例えば、(↓)では・・・   if ( ( pNMLV->uChanged == LVIF_PARAM && pNMLV->uNewState == 0 && pNMLV->uOldState == 0)    || ( pNMLV->uChanged == LVIF_STATE && pNMLV->uNewState == 4096 && pNMLV->uOldState == 0 )    || ( pNMLV->uChanged == LVIF_STATE && pNMLV->uNewState == 0 && pNMLV->uOldState == (LVIS_FOCUSED | LVIS_SELECTED) )){        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 (*)"));   } ・・・とすると、FINDの2個目で (*) が付いてしまいます。 REPLACEしないFINDは、(*)がついて欲しくないです。 XP対策で、RedrawWindow();を結構使っているのですが、 データに変化がなくても、RedrawWindow();を行うと OnLvnItemchangedList()イベントが発生するのでしょうか? ファイル名と備考欄が変更された時のみ、 つまり、データ変更検知対象をカラムで指定できると助かるのですが・・・ ( pNMLV->uChanged == LVIF_STATE && pNMLV->uNewState == 4096 && pNMLV->uOldState == 0 ) の4096とは何を表わしているのでしょうか? (!LVIS_FOCUSED | !LVIS_SELECTED)    と !(LVIS_FOCUSED | LVIS_SELECTED)    はとっちが正しい書き方なのでしょうか? リスト上のあるセルの値 と 同じ値 を(同セルに)上書きした場合、チェンジイベントは発生しますか? //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報 パラメーターの書式情報は、文字として、カラム9に退避しているので、リストコントロールの文字が変化したことさえ分かればいいです。なにか、もっと簡単な方法はあるでしょうか? 選択状態やフォーカスは自分で変えないほうがいいのでしょうか。。。 これでは、各機能に、編集中フラグを一個一個立てたほうが早いです。 本当は、自分で検証するべき物もありますが、質問ばかりですみません、一部でも教えてくださると嬉しいです。

psychang
質問者

補足

色々試行錯誤してて、時間がかかってすみません。 書式情報を数値にしていれています。その数値がlParam:に出て・・・  CFileListCreatorDlg::m_xcList.SetItemData(index,FormatDataNum); この数字が出ているようです。 もう少し、粘ってみます。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>OnLvnItemchangedList()であっているのでしょうか? 変更が完了した時に通知されるもの…ですね。 変更があった時だとLVN_ITEMCHANGING(MFCだとOnLvmItemChanging~()かな)ですね。 >あとは、pNMLV->uChanged などの 4とか8とか、定数で記述したいです。 定数というか…マジックナンバーなのはどうかと……4、8とかの値だけでどういう意味か理解はできないでしょう? # そういうのをマジックナンバーと言います。可読性を著しく低下させます。 http://www.geocities.co.jp/SiliconValley-PaloAlto/6827/Programing/NMLISTVIEW.htm とか、MSDNの日本語でのページとか……探せばあるかと思いますけど…。 #define LVIF_TEXT 0x00000001 #define LVIF_IMAGE 0x00000002 #define LVIF_PARAM 0x00000004 #define LVIF_STATE 0x00000008 とかになっていますね。 変更に関してはLVN_ITEMCHANGEDで通知されますので、pNMLV->uOldStateやpNMLV->uNewStateを参照して、何が変更されたのか……を判定して、処理することになるでしょう。 入る値は… #define LVIS_FOCUSED 0x0001 #define LVIS_SELECTED 0x0002 等になります。 # チェックボックスとかつけていたり、設定しているイメージリストによっては他のところも変わりますので、ビット演算で判定して下さいな。

psychang
質問者

補足

OnLvnItemchangingList() もありました。 でも、OnLvnItemchangingList()の後に必ずOnLvnItemchangedList()が来るのではと 思いました。 TRACE(↓)してみましたが、OnLvnItemchangingList()内でも、 リストに行を追加、置換、選択されている行を置換、すべてを置換において・・・  if (( pNMLV->uChanged == 4 && pNMLV->uNewState == 0 && pNMLV->uOldState == 0 )) 必ずTRUEになります。ただ、クリックしただけでも、また、データが変わらなくても該当してしまいます。 クリックした時、FALSEにしたいんですが・・・難しいです。 書式情報を数値にしていれています。その数値がlParam:に出ています。   if (FormatDataStr == _T("NORMAL,BLACK,")){    FormatDataNum = 11;   }   if (FormatDataStr == _T("BOLD,BLACK,")){    FormatDataNum = 12;   }   if (FormatDataStr == _T("NORMAL,RED,")){    FormatDataNum = 21;   }   if (FormatDataStr == _T("BOLD,RED,")){    FormatDataNum = 22;   }   CFileListCreatorDlg::m_xcList.SetItemData(index,FormatDataNum); ・・・という風にです。 マジックナンバーというんですか、初めて聞きました、有難うございますm(_ _)m 自分は、#define で定義した(数値と対応させた)定数といいたかったです。 LVIS_SELECTEDとかの方は、なんというか知りたかったです。 #define LVIS_FOCUSED 0x0001 #define LVIS_SELECTED 0x0002 #define LVIS_CUT 0x0004 #define LVIS_DROPHILITED 0x0008 #define LVIS_GLOW 0x0010 #define LVIS_ACTIVATING 0x0020 #define LVIS_OVERLAYMASK 0x0F00 #define LVIS_STATEIMAGEMASK 0xF000 ビット演算で判定 ・・・という事は、  pNMLV->u○○○State & LVIS_FOCUSED && pNMLV->u○○○State & LVIS_SELECTED フォーカスがあり、かつ、選択状態にあるという意味がu○○○Stateが3という意味ですね。 LVIS_□□□□ (ごめんなさい、自分が一番初めに載せたホームページにも少し載ってました。) ・・・で少し、イメージが付きやすくなりました。 フォーカスと選択状態を処理対象行に移すようにコーディングする方向で行こうと思いますが、 まちがった方向に行こうとしているなら、アドバイス下さい。 (ただ、たまたま、これから置換しようとする行にフォーカスや選択状態がある場合は、データが 変わったことを(行を)検出する事は出来ない気が・・・) マジックナンバーのままで、すみません、うまく動いたら直します。 ========================================TRACE===========================================  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);  TRACE(tempStr);

関連するQ&A

  • 仮想リストコントロールの表示

    お世話になります、fujitomoです。 今回ご意見を頂きたいと思い、質問させて頂きましたのはVCでの仮想リストコントロールにデータを表示する件に関してです。 具体的に申し上げますと、 あるデータが記述されたcsvファイルがあり、そのcsvファイルのある位置から200件のデータを仮想リストコントロールに表示させたいと思っています。 そこで、私が考えたアプリケーションの作りとして、初めにcsvファイルからデータを読み込んでCStringの二次元配列に各セルのデータを保存します。 そしてLVN_GETDISPINFOを受ける関数を作成し、そこでリストコントロールにCStringの二次元配列の値を当てはめていこうと思っています。つまり、関数内でリストの項目とCStringの二次元配列を1対1に対応させています。 しかしここで、LVN_GETDISPINFOを受ける関数は常にCStringの二次元配列の1行目から見てしまい、例えば、リストコントロールに100行目からのデータを表示させたいと思い、LVN_GETDISPINFOを受ける関数内でリストコントロールに表示させる開始行を指定したとしても0~99行目までが空白となって表示されてしまいます。目的の動作としては100行目からの200行をリストに表示させたいと思っているのでこれではダメです。 仮想リストコントロールを使うのは初めてで、どのように使うのが定石なのか分からない為悩んでいるのですが、私の目的の動作を達成させるためには表示させたい200行分のデータをその都度CStringの二次元配列に格納し、その配列とリストの項目をLVN_GETDISOINFOを受ける関数内で対応させるべきなのでしょうか? 文章だけではかなり分かりづらいと思うので、大雑把にですがソースを載せます。 //メンバ変数 CString data[gyo][row] //データを保存するCString二次元配列 CListCtrl m_list; //リストコントロールのコントロール変数 int start; //リスト表示行 //ダイアログの初めに BOOL C***Dlg::OnInitDialog() { CDialog::OnInitDialog(); Read_File(); //csvファイルをCStringの二次元配列に保存 m_list.SetItem(200);//200件表示に設定 return TRUE; } LRESULT C***Dlg::DefWindowProc(UINT message,WPARAM wParam,LPARAM lParam) { switch(message) case WM_NOFITY: return OnGetListInfo(lParam); } return CDialog::DefWindowProc; } LRESULT C***Dlg::OnGetListInfo(LPARAM lParam) { LPNMHDR lpnmh = (LPNMHDR)lParam; CWnd* hwndListView = GetDlgItem(IDC_LIST1); LV_DISPINFO* lpDInfo; switch(lpnmh->code){ case LVN_GETDISPINFO: lpDInfo = (LV_DISPINFO*)lParam; if(lpDInfo->iItem.mask & LVIF_TEXT){ if(lpDInfo->item.iItem >= start){     switch(lpDInfo->item.iSubItem){ case 0: _tcscpy_s(lpDInfo->item.pszText,256, data[lpDinfo->item.iItem][lpDinfo->item.iSubItem]; break; } } } break; } return 0; } といったソースとなっています。 ご意見を宜しくお願い致します。 尚、開発環境は Windows CE 6.0 Visual Studio 2005 です。 ご回答をお待ちしております。

  • アドレス

    利用環境は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のリストビューの内容をうけとりそれを新しくダイアログを作って そちらに移すプログラムです。

  • 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; }

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

    時刻の日時指定コントロールで実行エラー 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; } どなたか教えてください。 お願いします。

  • リストコントロールにセットするイメージリストについて

    こんにちは。 Windowsでレポート状態表示のリストコントロールについて質問です。 リストコントロールははオーナーデータで表示しています。 一覧でアイテムの横にアイコン(ビットマップ)を表示しています。 またソートできるようにし、コラム部分には昇順か降順か分かるように▲▼が 表示されるようにしようと思っています。 リストコントロールに表示するアイテム用のイメージリストとヘッダー コントロール用のイメージリストを用意し、リストコントロールと リストコントロールから取得したヘッダーコントロールにそれぞれ 追加したのですが、 Header_SetImageList(ヘッダーコントロールのウィンドウハンドル) ; ListView_SetImageList(リストコントロールのウィンドウハンドル) ; 上記の順番では後から追加したイメージリストで上書きされてしまいました。 Header_GetImageListでイメージリストを取るとListView_SetImageListで セットしたイメージリストのハンドルが取得されます。 リストコントロールでイメージリストを取り扱う場合はリストアイテムも ヘッダーも一つのイメージリストで管理しなければならないのでしょうか ?

  • SPREADとCDialogのCREATE

    システムを開発中で困った事が起きているので質問してみました。 開発環境は.NET2008でC++、MFCアプリケーションのプロジェクトです。 SPREADのバージョンは3.0.0.52(SPR32X30.ocx)です。 簡潔に言うと、SPREADを貼ったダイアログが出力出来ません。 1.SPREADを貼る前(m_dlgはCDialog *m_dlgとして親Dialogで定義) m_dlg->Create(ID, this);(この時ちゃんとm_hWndに値が入る) m_dlg->ShowWindow(SW_SHOW); で問題なく出力されます。 2.SPREADをm_dlgに貼った場合 m_dlg->Create(ID, this); は通るには通るのですが、m_hWndがNULLのままなので、 m_dlg->ShowWindow(SW_SHOW); でハンドルが無いので落ちてしまう。 この2つを比較すると、後者は dlgcore.cppの311行目 hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate, pParentWnd->GetSafeHwnd(), AfxDlgProc); で値が取れていないようです。 他の.Net2008プロジェクトでは問題なく使えていますが、今回問題となっているプロジェクトは、 「VC6から.Net2008に置換」 しています。 何か悪影響があるのでしょうか? 因みに、置換する前はSPREAD関係は何も使っていません。

  • list構造。。。

    リストの末尾にデータを追加すると、最後に追加したデータで今までのリストのデータが上書きされてしまいます。。 以下に、ソースを掲載させていただきます。 void SetNode(List* node_first, List* node_second, int *data) { node_first->move = data; node_first->next = node_second; return ; } /*末尾に挿入*/ void Insert_Tail(List **head, int* data) { List *ptr = *head; if(ptr == NULL){ *head = (List*)calloc(1,sizeof(List)); SetNode(*head, NULL, data); return ; }else{ while(ptr->next != NULL){ ptr = ptr->next; } ptr->next = (List*)calloc(1,sizeof(List)); SetNode(ptr->next, NULL, data); } return ; } void show_list(List *list) { List *ptr = list; while(ptr != NULL){ printf("%d\n",*(ptr->move)); ptr = ptr->next; } return ; } int main(int argc, char** argv) { /*宣言*/ Node* root; /**/ List* top; /* 手順のリスト */ int judge; top = NULL; do{ printf("num:"); scanf("%d",&judge); switch(judge){ case 1: /*データを末尾に追加*/ printf("mem:"); scanf("%d",mem); root->board = mem; Insert_Tail(&top, root->board); break; case 2: /*リストを頭から表示*/ show_list(top); break; default: break; } }while(judge != 0); return 0; } 自分は最後のリストまでたどって、callocしたつもりなのですが、どうもそうではないようで、困っています。 どうか、御指導の程、お願いします。

  • リストボックスとDataGridコントロールについて

    「Microsoft Visual Basic 2008 Express Edition」と「Microsoft SQL Server 2005」を使用して開発することになり勉強を始めている初心者です。 リストボックスとDataGridコントロールの違いについて教えて下さい。 テーブルからある条件のデータを一覧表示して、データの追加、修正、削除処理を行いたいと思っています。 追加、修正、削除処理は、別画面で行います。 この場合の一覧表示にはリストボックスとDataGridコントロールのどちらを使用する方がよいでしょうか?

  • リストボックスに関連してファイルの行削除

    VisualC++ 6.0でMFCを利用しています. あるテキストファイルの中身が表示されているリストボックスがあります. そのリストボックスのある行をダブルクリックすると, 対応した行のテキストファイル,リストボックス両方の行が削除されるプログラムを組んでいます. リストボックスの行は削除できるのですが,テキストファイルのほうは削除する手段がわかりません. void CModel03Dlg::OnDblclkMyList02() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください CModel03Dlg::List_Selected(fp); int label_number; label_number = m_sList02.GetCurSel(); char input[256], string[256]; m_sList02.GetText(label_number, input); while(fgets(string, 256, fp) != NULL){ if(input==string){ //string = "\0"; //この辺りがわからない MessageBox(input); // Boxが表示されないのでif文の評価がfalseだと } } m_sList02.DeleteString(label_number); } どうすればテキストファイルの内容を削除できるのでしょうか?教えてください.

  • List構造

    Listの尻にノードを追加する関数で困っています。 以下に、ソースの一部を掲載させていただきます。 typedef struct __node{ int data; struct __node *next; }Node; ... /*リストの尻にノードを追加する関数 * 引数: head. リストの先頭ノードのポインタ data. リストの尻に追加したいint型の変数*/ void Insert_Tail(Node *head, int data) { Node *ptr = head; if(ptr == NULL){ /*<ノードが存在しない時には追加されない>*/ /*領域の確保*/      head = (Node*)calloc(1,sizeof(Node)); /*データをセット*/ head->data = data; head->next = NULL; return ; }else{ /*<ノードが存在するときには正常に動作>*/ while(ptr->next != NULL){ ptr = ptr->next; } /*領域の確保*/ ptr->next = (Node*)calloc(1,sizeof(Node));      /*データのセット*/ ptr->next->data = data; ptr->next->next = NULL; } } コメントアウトにも書かせていただきましたが、ノードがすでに存在するときには、正常にノードの最後に追加してくれるのですが、ノードが存在しない時にはリストに追加してくれません。 どうかご指導、ご指摘の程お願いします。