リストビュー(オーナードロー中)で特定の行を非表示にするには?

解決


n/a  2012-02-06 10:15:49  No: 73182  IP: 192.*.*.*

オーナードロー中のリストビューにて、
「文字列'foo'が含まれない場合は非表示」
のようなフィルタリングの実装のため、特定のアイテムを非表示にしたいのですが、どのようにすればよいのでしょうか?

検索しても、「オーナードローを使え」とあるばかりで、実際どのようにすればよいのかは書かれていないので困っています。

宜しくお願いします。

編集 削除
仲澤@失業者  2012-02-06 11:01:24  No: 73183  IP: 192.*.*.*

本来は
  1.ListCtrl::DeleteAllItems()してから、
  2.全ての行をListCtrl::InsertItem()する
しか方法はありません。
当然ですが、2.のとき「特定のアイテム」を除外するわけですね。
この方法の場合、オーナードローかどうかは関係ありません。

オーナードローの場合で使えるテクニックとしては
  1.全てのアイテムのリストを作っておく(全体リスト)。
  2.特定のアイテムを除外したアイテムのリスト(表示リスト)も
    作っておく。
  3.InsertItem()では「全体リスト」の数分のダミー行を挿入する。
  4.DrawItem()では「表示リスト」の方を表示対象とする。
で、できますよね。ただしこの場合削除した数分の余計な
スクロールが発生します。
なので、それを解決するには結局
  3.InsertItem()でも「表示リスト」の数分のダミー行を挿入する。
をやらざるを得ません。んで、結局最初の「本来は・・」になるわ
けです。つまり本件の場合LVS_OWNERDRAWFIXEDであることは
何の解決にもなりません。

本件を根本的に解決するには「InsertItem()しなくてすむ方法」を
とらざるを得ません。従って

  5.LVS_OWNERDATAを使用する

が、最終的な解になると思われます。この方法なら、
LVM_SETITEMCOUNTするだけで、アイテム数を設定できるからです。
当然表示対象になるのは「表示リスト」の方ですね。

編集 削除
仲澤@失業者  2012-02-06 11:10:08  No: 73184  IP: 192.*.*.*

おっと、言い忘れ。orz.
当然ですが、LVS_OWNERDRAWFIXEDも必要ですね。

編集 削除
n/a  2012-02-06 12:31:57  No: 73185  IP: 192.*.*.*

回答有難うございます。

質問なのですが、「全体リスト」の「リスト」はリストビューのことでしょうか?
それとも、データの入った構造体のことでしょうか?

構造体のことであれば、
・LVN_GETDISPINFOでの「表示用リスト」の処理
・ListView_SetItemCountEx()
で、希望通りの動作となりそうなのですが、
追伸の「LVS_OWNERDRAWFIXEDも必要」がよくわかりません。

再度、宜しくお願いします。

編集 削除
仲澤@失業者  2012-02-06 14:47:02  No: 73186  IP: 192.*.*.*

>質問なのですが、「全体リスト」の「リスト」はリストビューのことでしょうか?
>それとも、データの入った構造体のことでしょうか?

「表示対象としている元データの一覧」のことです。
InsertItem()ではLVITEMを使うと思いますが、
LVS_OWNERDATAの場合InsertItem()自体を行いません。
表示すべきデータはCListView(CListCtrl)に与える必要が
ないので当たり前ですね。逆に言うとCListCtrlに標示データ
を保管(移管)しておくことは出来ないということです。
データの一覧はCListViewのあづかりしらないところで
管理しなければなりません。

>・LVN_GETDISPINFOでの「表示用リスト」の処理

それでやりたければそれでも良いですが、
すでにLVS_OWNERDRAWFIXEDしてあったら外す必要はないということです。
自分は、LVS_OWNERDRAWFIXEDの方が、つまりDrawItem()を
ハンドリングしたほうが表示をコントロールしやすいと思います。
コードも単純になるのではないでしょうか。
まぁ実際に両者ともコードしてみたらどうでしょう。

個人的な感想ですがLVN_GETDISPINFOを使うのははっきり言って
「うんざり」ですね。つまり自分のコードでは常に
void  MyListView::OnLvnGetdispinfo(
  NMHDR *pNMHDR, LRESULT *pResult)
{ *pResult = 0;}
です(笑)。

編集 削除
n/a  2012-02-07 01:26:50  No: 73187  IP: 192.*.*.*

成程。確かにDrawItem()内で一気に処理した方が分かりやすそうです。

詳しい解説ありがとうございました。
これにて解決とさせていただきます。

編集 削除