宜しくお願いします。
環境はVC++6.0 MFC ダイアログベース、です。
ボタンを押すと、関連するアイテムをリストビューに表示したいのですが、
アイテムが一番左しか表示されません。
しかも2回目を押すと、何も表示されなくなってしまいます。
(リストビューはレポート形式です)
どこか間違えているのだと思いますが、どこか分からず困っています。
宜しければご教示お願いしますm(_ _)m
// 使うクラス(適切な値が入っています)
CListCtrl* pListCtrl; // リストビュークラスのポインタ
CStringArray itemArray; // ヘッダ配列
CMapStringToOb itemMap; // CString がキーであるCStringArrayのアイテム配列
CStringArray idArray; // マップ用のキー配列
// ヘッダを削除する
CHeaderCtrl* headerCtrl = pListCtrl->GetHeaderCtrl();
for (i = 0, j = headerCtrl->GetItemCount(); i < j; i ++) {
headerCtrl->DeleteItem(itemId);
}
// アイテムを削除する
pListCtrl->DeleteAllItems();
// ヘッダを作成する
HDITEM hdItem;
hdItem.mask = LVCF_TEXT | LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH;
hdItem.fmt = LVCFMT_CENTER;
hdItem.cxy = 48;
for (i = 0, j = itemArray.GetSize(); i < j; i ++) {
CString item = itemArray.GetAt(i);
hdItem.pszText = item.GetBuffer(item.GetLength() + 1);
headerCtrl->InsertItem(i, &hdItem);
item.ReleaseBuffer();
}
// アイテムを作成する
LVITEM lvItem;
lvItem.mask = LVIF_PARAM | LVIF_TEXT;
for (i = 0, j = idArray.GetSize(); i < j; i ++) {
CObject* pObject;
itemMap.Lookup(idArray.GetAt(i), pObject);
lvItem.iItem = i;
lvItem.lParam = i;
for (int p = 0, q = ((CStringArray *)pObject)->GetSize(); p < q; p ++) {
CString item = ((CStringArray *)pObject)->GetAt(p);
int length = item.GetLength();
lvItem.cchTextMax = length;
lvItem.pszText = item.GetBuffer(length + 1);
lvItem.iSubItem = p;
if (! p) {
pListCtrl->InsertItem(&lvItem);
} else {
pListCtrl->SetItem(&lvItem);
}
item.ReleaseBuffer();
}
}
ヘッダはしっかりと表示出来ていますが、
headerCtrl ではなく、pListCtrl からアイテムを追加すると、
一度だけ正常にアイテムが表示されます。
しかし、すみませんが、
問題の原因と関係あるのか分からないのです。
ミスがありました、申し訳ありません。
headerCtrl->DeleteItem(itemId);
は間違いで、正しくは
headerCtrl->DeleteItem(0);
です。
あとインデントが消えてしまって見辛いのですが、
宜しくお願いします。
> HDITEM hdItem;
> hdItem.mask = LVCF_TEXT | LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH;
> hdItem.fmt = LVCFMT_CENTER;
HDITEM と LVCOLUMN を混同しないでくださいね。
> hdItem.pszText = item.GetBuffer(item.GetLength() + 1);
些細な問題ですが、
hdItem.pszText = const_cast< LPTSTR >( static_cast< LPCTSTR >( item ) );
とでもすべきかと。
> lvItem.cchTextMax = length;
アイテムの追加時にはこのメンバを設定する必要はありません。
> lvItem.pszText = item.GetBuffer(length + 1);
上に同じく、GetBuffer の使用は適切ではありません。
> if (! p) {
> pListCtrl->InsertItem(&lvItem);
> } else {
> pListCtrl->SetItem(&lvItem);
> }
たぶんここが最大の問題ですが、InsertItem と SetItem が逆ではありませんか?
シャノンさん返信ありがとうございます。
見事解決することが出来ました!
また
> HDITEM と LVCOLUMN を混同しないでくださいね。
> const_cast< LPTSTR >( static_cast< LPCTSTR >( item ) );
> アイテムの追加時にはこのメンバを設定する必要はありません。
すべてにのご指摘、とても勉強になりました。
特にCStringからのキャストは感動的でした。
調べていてGetBufferメソッドを見つけたので使っていた次第です。
ところで、
> InsertItem と SetItem が逆
これは逆ではないような気がします。
サンプルを読んでいて
アイテム追加(InsertItem)⇒アイテム設定(SetItem)
のように設定すればよいと把握しております。
※「for (int p = ・・・」のループの1回目だけinsertで残りはsetしています。
それでその後も色々と試していたのですが、
どうやら SetItem 時には lvItem.mask にLVIF_PARAM を含ませては
ならないらしいことが分かりました。
それを取ると、正常に動作致しました。
全項目に対してソートを実装しているので、サブアイテムにもLVIF_PARAMが
必要だろうと勘違いしておりました。
大変いい勉強になりました。
どうもありがとうございますm(_ _)m
今後も宜しくお願い致します。
> これは逆ではないような気がします。
うん、ごめん。俺の勘違いです。
個人的に、整数やポインタに対して ! っていう書き方はしないので読み間違えました。
> どうやら SetItem 時には lvItem.mask にLVIF_PARAM を含ませては
> ならないらしいことが分かりました。
俺は全然お役に立てませんでしたorz
参考までに、MSDNから引用。
> To set the text of a subitem, set the iItem and iSubItem members to indicate the specific subitem, and use the pszText member to specify the text.
> Alternatively, you can use the ListView_SetItemText macro to set the text of a subitem. You cannot set the state or lParam members for subitems because subitems do not have these attributes.
http://msdn2.microsoft.com/en-us/library/bb775091.aspx
ばっちり書いてありました。
解決のチェック付け忘れてました(汗
> 俺は全然お役に立てませんでした
そんなことないです。
シャノンさんのおかげで、アイテムを作るところに問題がある
ことが分かりました。
> ばっちり書いてありました。
MSDNも調べたつもりだったのですが、調べ不足でした。すみません。
あとintに対しての ! 演算子使うべきではありませんでした。
特に質問する掲示板で。
スマートに書こうと思ってこうなってしまいました。
以後気を付けたいと思います。
どうもありがとうございました。
ツイート | ![]() |