はじめまして。
いつも参考にさせて頂いておりますが、今回初質問です。
CSVファイルを読み込んでダイアログ上に配置したCListCtrlにCSVの内容を表示するMFCダイアログベースのアプリを作成しています。
CListCtrlには拡張スタイル(LVS_EX_CHECKBOXES)をセットしており、そのチェック状態をメンバ(vector<BOOL> m_vChk;)に保存しています。
(CSVファイルのデータは別のCString型のvector 2次元配列 m_vStrに保存している)
大まかな動きは以下の通りです。
-----
1.CSVファイルを読み込んでm_vStrに保存
2.m_vChkにm_vStrの行数分だけ要素を追加(デフォルトのため値は全行ともTRUE)
3.m_vStr、m_vChkの値をCListCtrlにInsertItem()、SetItem()して表示
------
上記のstep.3のm_vChkの値をCListCtrlにセットする処理
for(int i = 0; i < m_vChk.size(); i++) {
BOOL bCheck = m_vChk.at(i);
CListCtrl.SetCheck(i, bCheck); ←ここ
}
の中の「←ここ」の行を実行直後にm_vChkのデータが壊れてしまいます。
具体的にはbCheckの値がTRUEでSetCheckした場合のみ
添え字iの次以降のすべての要素の値が-1など別な値になってしまいます。
(FALSEでSetCheckしても壊れない)
vectorを初めて使うものでお作法通りとなっていないかもしれません。
どなたかご存知の方、同じ状況になったことのある方、
アドバイス頂ければ幸いです。
よろしくお願いします。
自己解決しました。
メモリリークかSTLのワナかと思い静的コード解析など試しておりましたが、単純なバグでした。
お恥ずかしい限りです。
CListCtrl::SetCheckをしてもOnLvnItemchangedが発生するのですね。
CListCtrlのチェック状態の変化をOnLvnItemchangedで取得していましたが、その中で変化があったItemだけでなくすべてのItemのチェック状態をCListCtrlから取得してm_vChkにセットしていました。
そのためm_vChkの中でTRUEになっていたものもSetCheckする前の状態(FALSE)を取得してm_vChkに値をセットしてしまいFALSEになっていました。
(-1になったのは更にCListCtrlにSubItemを追加していない範囲までGetCheckしていたためでした)
この処理を
-----
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
bool bOld = ((pNMLV->uOldState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2));
bool bNew = ((pNMLV->uNewState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2));
if(bOld != bNew) {
int iItem = pNMLV->iItem;
m_vChk[iItem] = bNew;
}
-----
とすることで、対象を変化があったItemのみとし、CListCtrlからチェック状態を取得せずにメッセージで飛んでくる正しい値をm_vChkにセットするようにしました。
ツイート | ![]() |