高見知英のかいはつにっし(β)

高見知英のアプリケーション開発日誌 のほか、地域活動などの活動報告ブログ。

仮想リストボックスコンポーネント

 たとえば指定ディレクトリ内のファイルを表示するリストボックスを作るとします。表示するだけなら別にいいのですが、各ファイルに付加情報(サイズなど)を記憶しておいて、描画に反映させたいのなら、従来通りItemsに格納していくだけではちょっと不便です、かといってTStringsのObjectsプロパティを使うと、リストアイテムの追加や削除の度に解放しなければならず、それもまた不便です。
 そこで、仮想リストボックスの出番です。TObjectListにファイルの情報を格納し、仮想にしたリストボックスでそれを参照すれば、いちいち情報保持用のオブジェクトを解放しなくても、各アイテムに好きなだけ情報を付加することができます。
でも、ここで問題が発生します。いつStyleを設定し、ファイルリストを読み込むのか?
ふつうに考えたらLoadedメソッドを使いますね、

  inherited;
  Style := lbVirtualOwnerDraw;
  Refresh; // ファイルリストの更新&リストボックスの表示更新

でも、これだとなぜかうまくいきません、Refreshメソッドの最後に

  Self.Count := FileList.Count;

などとするとエラーになります。

 リストボックス (ShellFileListBox1) の Count を設定するには Virtual スタイルでなければなりません。

 Styleプロパティの値が反映されていないようですねぇ。Styleプロパティの中でCreateWndを呼び出しているので、その辺が鍵になっている?ような気もしますが…(そもそもLoadedメソッドはいつ呼ばれるのやら?VCLソースを探してみてもわからなかったし…)。
 ――で、試行錯誤の末、上のコードをそのままCreateWndメソッドの中に置くと、うまくいくようです*1。なぜかはよく分りませんが、「なるものはなる」ということで覚えておくほかないのでしょうか(^_^;)これまたStyleプロパティ変更後にはCreateWndが呼ばれる というのと何か関係あるのかもしれませんが…。

*1:SetParentなんかでもいいんですが、どうやらDestroyの前後にも呼ばれるようで、その処理がある分、こっちよりは手間がかかります