ファイル検索をしてファイル名やパスの結果を、大量表示の時の表示速度が速いということなのでListViewに仮想リストビューとして表示したいのですが、調べてみましたがいまいち使い方が分からずうまくいきません。
皆様アドバイスをお願いします
google にて「delphi + 仮想リストビュー」等のキーワードで調べてみた
ら,いくつかサンプルが出てきました。
ここで聞くよりもはやいかと思いますので,そちらを参照されてはどうで
しょうか。
もしまたわからないということであれば,わからないポイントを絞って質
問するとスムーズに回答が貰えると思います。
まことさんありがとうございます。
もう一度調べ直して、こちらのサイトを参考にある程度動くようなのを作ってみました。
http://www.occn.zaq.ne.jp/maekawa/delphitip/index.html#c031
それで、下記のコードを書いてみましたが、SubItemに検索したファイルのファイルパスを表示したいのですが、やり方がよくわからないのでアドバイスをお願いします。
unit Unit0;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls;
type
TForm0 = class(TForm)
Button1: TButton;
Edit1: TEdit;
ListView1: TListView;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ListView1Data(Sender: TObject; Item: TListItem);
private
{ Private 宣言 }
vListViewItems : TList;
procedure FileFind(const S: String);
public
{ Public 宣言 }
end;
var
Form0: TForm0;
implementation
{$R *.dfm}
procedure TForm0.Button1Click(Sender: TObject);
var
S: String;
begin
vListViewItems.Clear;
S := Edit1.Text;
if IsDelimiter('\', S, Length(S)) then
SetLength(S, Length(S) - 1);
FileFind(S);
end;
procedure TForm0.FileFind(const S: String);
var
SR: TSearchRec;
NewListItem: TListItem;
begin
if FindFirst(S + '\*.*', faAnyFile, SR) = 0 then
begin
repeat
if (SR.Name <> '.') and (SR.Name <> '..') then
if (SR.Attr and faDirectory) <> 0 then
begin
FileFind(S + '\' + SR.Name);
NewListItem := TListItem.Create(ListView1.Items);
NewListItem.Caption := SR.Name;
vListViewItems.Add(NewListItem);
end
else
begin
NewListItem := TListItem.Create(ListView1.Items);
NewListItem.Caption := SR.Name;
vListViewItems.Add(NewListItem);
end;
ListView1.Items.Count := vListViewItems.Count;
until FindNext(SR) <> 0;
FindClose(SR);
end;
end;
procedure TForm0.FormCreate(Sender: TObject);
begin
vListViewItems := TList.Create;
Edit1.Text := 'C:\text'
end;
procedure TForm0.ListView1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := TListItem(vListViewItems[Item.index]).Caption;
end;
end.
調べて実際に動くところまでいったのですね。お疲れ様でした。
質問の内容についてですが,たぶんファイル検索の再帰処理(サブフォルダ
の中まで次々と検索を行っていくルーチン)の部分がよくわからないポイン
トであるように思いました。
とりあえず,参考になるかと思いますので,以前タブブラウザを作成した
ときに書いた,お気に入りメニューバー作成のコードを掲載しておきます。
新規作成フォーム上にMainMenu1をおき,N1という名前のメニューを作って
ください。また,Button1もおいてください。後は以下のコードを入力するだ
けです。
private
procedure EnumFiles(DirectoryName: string; BaseMenuItem: TMenuItem);
procedure TForm1.EnumFiles(DirectoryName: string; BaseMenuItem: TMenuItem);
var
SearchRec: TSearchRec;
MenuItem{, SubMenuItem}: TMenuItem;
SL1, SL2: TStringList;
i: Integer;
begin
if Copy(DirectoryName,Length(DirectoryName),1)<>'\' then DirectoryName:=DirectoryName+'\';
//ファイルとフォルダでは,作成するメニューのタイプが違うので,別々に管理する。
SL1 := TStringList.Create;
SL2 := TStringList.Create;
if FindFirst(DirectoryName+'*.*', faAnyFile-faHidden, SearchRec) = 0 then
try
repeat
if SearchRec.Attr and faDirectory <> 0 then begin
if not ((SearchRec.Name = '.') or (SearchRec.Name = '..')) then begin
//フォルダはSL1へ。
SL1.Add(SearchRec.Name);
end;
end else begin
//ファイルはSL2へ。
SL2.Add(SearchRec.Name);
end;
until FindNext(SearchRec) <> 0;
SL1.Sort;
SL2.Sort;
for i := 0 to SL1.Count - 1 do begin
MenuItem := TMenuItem.Create(Self);
MenuItem.Caption := SL1.Strings[i];
BaseMenuItem.Add(MenuItem);
//フォルダなら再度メニュー作成処理へ。
EnumFiles(DirectoryName + SL1.Strings[i] +'\', MenuItem);
end;
for i := 0 to SL2.Count - 1 do begin
MenuItem:=TMenuItem.Create(Self);
MenuItem.Caption := SL2.Strings[i];
//ファイルなら単純にメニューを作って終了。
BaseMenuItem.Add(MenuItem);
end;
finally
FindClose(SearchRec);
end;
SL1.Free;
SL2.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//↓IEの「お気に入り(&A)」に相当するメニュー。メニューアイテムなら何でもよいです。
N1.Clear;
//↓フォルダパスは適当に書き換えてください。
EnumFiles('C:\Documents and Settings\Owner\Favorites', N1);
end;
申し訳ありませんが,的外れな回答をしてしまったかもしれません。
もし間違っていたらご容赦ください。単純にファイル名の代わりにパス
を表示したいということであれば,S + '\' + SR.Name でいけます。
まことさん、すみません説明不足でうまく伝わっていなかったかもしれません。
ListViewがvsReportの時のリストでFileFindで出てきたデータで「ファイル名」と「ファイルパス」のカラムのリストを作りたい時
仮想リストビューじゃないときは
FileFindにある
NewListItem := TListItem.Create(ListView1.Items);
NewListItem.Caption := SR.Name;
vListViewItems.Add(NewListItem);
の場所のコードに
NewListItem := ListView1.Items.Add;
NewListItem.Caption := SR.Name;
NewListItem.SubItems.Add(S);
という風に書いていたのを、多数のファイル情報の表示を早くするためにこれを仮想リストビューの形で表示したく上記のコードにしてみたのですが
仮想リストビューじゃない時のNewListItem.SubItems.Add(S);の部分を仮想リストビューでどうやって表示するかのわかりません。
もう一度アドバイスお願いします。
procedure TForm0.ListView1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := TListItem(vListViewItems[Item.index]).Caption;
Item.SubItems.Assign(TListItem(vlistViewItems[Item.Index]).SubItems);
end;
で、いいんじゃないの?
風来坊さん、ありがとうございます。
FileFindを
NewListItem := TListItem.Create(ListView1.Items);
NewListItem.Caption := SR.Name;
NewListItem.SubItems.Add(S);
vListViewItems.Add(NewListItem);
にして
ListView1Dataに
Item.SubItems.Assign(TListItem(vlistViewItems[Item.Index]).SubItems);
を加えて試してみました。
目的の値自体は表示することができたのですが、リストがちらつくようになりました。
XPスタイルの仮想リストビューでちらつきをなくすには?
https://www.petitmonte.com/bbs/answers?question_id=4225
仮想リストビューのちらつきという事で、上のようなのを見つけたのですが原因も違うみたいですし
載っていた対応も試してみましたが改善できませんでした。
他に手段、又はちらつきを無くす方法があれば助言をお願いします
VirtualTreeview
http://www.lischke-online.de/
敷居は高いかもしれませんがいいですよ。
リストビューとしても使えますし…
>ListView1Dataに
> Item.SubItems.Assign(TListItem(vlistViewItems[Item.Index]).SubItems);
素直に Item.SubItems.Add()を使えばチラツキは解決。
Data保持にはTListItemでなく自前のRecordの方がいいと思うけど。
風来坊さん、aサインは×さんありがとうございます
VirtualTreeviewはだいぶ高機能そうですけど、今のところListViewを使用していきたいと思っているので、すみません。
Item.SubItems.Add()やRecordをつかうのですね。
仮想リストビュー時の動作の流れや、Recordでどんな風にデータ保持をすればいいのか分からないのでもう少し調べて試してみます
ついいまし方,仮想リストビューで指定フォルダ内のファイル一覧を取得
するサンプルをUPしました.参考になれば幸いです
http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/T_ListView.htm#01
説明するまでもありませんが,このリスト1のメソッドSetFilesListToItemsの
引数が指定のフォルダ名です.したがって,取得したファイル名の前に付加す
ればフルパスとなります.
Mr.XRAYさん、ありがとうございます。
まだ色々詰まっていましたので大変参考になりました。
ツイート | ![]() |