冥界3大法王 发表于 2024-3-10 21:50

大事不好了!控件神经了!输出结果时好时坏!

本帖最后由 冥界3大法王 于 2024-3-10 21:56 编辑

控件需要在此下载:https://www.alphaskins.com/dwnld.php不然没有sShellListView1这个控件哟~~

故事是这样的,我要加一个编辑框过滤文件的功能{:301_974:}

uses
   IOUtils, Types;

procedure TMainForm.File_Filter_EditKeyPress(Sender: TObject; var Key: Char);
var
dir: TDirectory;
files: TStringDynArray;
str: string;
List: TListItem;====================================>后来单独加的
begin
sShellListView1.clear;
if Key = #13 then
begin
    files := dir.GetFiles(数据路径);      
    for str in files do
    begin
//       showmessage(str);                                    文件全路径
//       showmessage(ExtractFileName(str));          只取文件名
      if Pos(File_Filter_Edit.text, ExtractFileName(str)) > 0 then
      begin
      List.SubItems.Add(str);==============================>后来单独加的
//       sShellListView1.AddItem(ExtractFileName(str), sShellListView1); //神经的代码在这句上,时而过滤输出结果是正确的
//      Memo1.Lines.Add(str);         算法是对的!上一句有问题!Add加到Memo上没问题啊!!!
      end;
      ShowMessage(List.ToString);===========================>后来单独加的
//   List.SubItems.Assign(sShellListView1.Items);=================>后来单独加的
    end;
end;
end;


开始以为是因为
if Pos(File_Filter_Edit.text, ExtractFileName(str)) > 0 then 这句造成的,所以后来加了红字部分
因为确实会不严谨,所以后来加了为了局部匹配对比

爱飞的猫 发表于 2024-3-11 01:47

本帖最后由 爱飞的猫 于 2024-3-11 01:54 编辑

因为你没有提供最小复现的项目代码,我也不懂 Delphi 的 IDE。

你文中提到的 AlphaSkins 是控件皮肤库,和 Delphi 本身没啥关系。本身应继承自 `TShellList` 控件。

---

网上晃悠了一圈,发现 Lazarus 使用的 Free Pascal 自带了这个 `TShellList` 控件而且不用额外配置,所以我就用它了。

(1) 第一种方法是利用 `FileUtil.FindAllFiles` 来进行过滤,但 Delphi 好像没这个东西:

```
procedure TForm1.BtnFilterClick(Sender: TObject);
var
i: Integer;
ListOfFiles: TStringList;
begin
   ListOfFiles := TStringList.Create;
   FileUtil.FindAllFiles(ListOfFiles, Dir_Input.Directory, Edit_Filter.Text, False, faAnyFile);

   shellListView.Clear;
   for i := 0 to ListOfFiles.Count - 1 do
   begin
       shellListView.AddItem(ExtractFileName(ListOfFiles), TStringWrapper.Create(ListOfFiles));
   end;
end;
```

(2) 第二种方法则是用 `System.SysUtils` 中的 `FindFirst`/`FindNext`/`FindClose` 来查找信息:

```
procedure TForm1.BtnFilter2Click(Sender: TObject);
var
SearchRecord: TSearchRec;
FilePath: String;
begin
   shellListView.Clear;
   if FindFirst(Dir_Input.Directory + DirectorySeparator + Edit_Filter.Text, faAnyFile, SearchRecord) = 0 then
   begin
       repeat
         if (SearchRecord.Attr and faDirectory) <> 0 then continue;
         FilePath := Dir_Input.Directory + DirectorySeparator + SearchRecord.Name;
         shellListView.AddItem(SearchRecord.Name, TStringWrapper.Create(FilePath));
       until FindNext(SearchRecord) <> 0;
       FindClose(SearchRecord);
   end;
end;
```

实测效果如下:

![](https://imgsrc.baidu.com/forum/pic/item/4bed2e738bd4b31ca6910a81c1d6277f9e2ff85f.png)

完整项目代码(使用 Lazarus IDE 编译)和编译后的文件:(https://pan.baidu.com/s/12uHi8taR-tKTpZrXQXVzyg?pwd=wfcg)

冥界3大法王 发表于 2024-3-11 09:52

@爱飞的猫
我去搜索这个控件名

搜索出来的东西外来安装的控件

如图所示,我觉得最有问题可能的就是最后一个参数。它说的是啥?对象。
如果输出结果到Memo1,则和预期结果一样。
我现在严重怀疑这个对象我的写法有问题。
明明上面POS函数对比的结果是对的。可是不对的结果为啥反而添加到了文件列表?可是为啥Memo1中添加来的却又是对的?
所以综合而看,我方认为最后一个参数对象,我写得有问题。改成啥呢?

https://static.52pojie.cn/static/image/hrline/2.gif

其实我也可以直接扔一个JamExplorerBrowser1控件,选项中开启显示文件路径、过滤栏即可。一行代码也不用写。

冥界3大法王 发表于 2024-3-11 10:02

现在得到新结论:
我尝试把最后一个 对象参数修改为其他任意的控件名,都能调试通过。
但最终输出结果还是时对时不对。
所以,是不是 sShellListView1.AddItem 这个方法用的不对?

爱飞的猫 发表于 2024-3-11 11:11

冥界3大法王 发表于 2024-3-11 10:02
现在得到新结论:
我尝试把最后一个 对象参数修改为其他任意的控件名,都能调试通过。
但最终输出结果还 ...

你应当参考库的文档。通常第二个参数的对象通常是与该项目相关联的数据,方便取 `.Selected.Data` 的时候用。

另外如果只是过滤到列表,你也可以考虑用回标准的 `TListView` 控件。

冥界3大法王 发表于 2024-3-11 11:14

本帖最后由 冥界3大法王 于 2024-3-11 11:26 编辑

@爱飞的猫
我又换了个写法: 还是输出效果时而抽风。算了,扔个简单的实现控件就不纠结了,以后有时间再说。
感谢版主哥解答。
procedure TMainForm.File_Filter_EditKeyPress(Sender: TObject; var Key: Char);
var
dir: TDirectory;
files: TStringDynArray;
str: string;
ListItem: TListItem;
begin
sShellListView1.clear;
Memo1_BaoPo.Clear;                               //仅为测试
if Key = #13 then
begin
    files := dir.GetFiles(数据路径);   
    for str in files do
    begin
      if Pos(File_Filter_Edit.text, ExtractFileName(str)) > 0 then
      begin
//sShellListView1.AddItem(ExtractFileName(str), sShellListView1);                           //版本1写法时对时错
      ListItem := sShellListView1.Items.Add;
      ListItem.Caption := str;                                                                              //版本2写法时对时错
      Memo1_BaoPo.Lines.Add(str);            //仅为测试
      end;
    end;
end;
end;

wyw6813 发表于 2024-3-11 13:44

你的用法可能不对,VCL框架下TListView用法如下,你的那个控件可能继承自TListView,用法应该类似。
uses
Vcl.ComCtrls;

procedure TForm1.AddDataToListView;
var
ListItem: TListItem;
I: Integer;
begin
ListView1.Items.BeginUpdate;

try
    for I := 0 to 5 do
    begin
      ListItem := ListView1.Items.Add;
      ListItem.Caption := 'Item ' + IntToStr(I);
      ListItem.SubItems.Add('Detail of Item ' + IntToStr(I));
      // 可以根据需要添加更多子项
    end;
finally
    ListView1.Items.EndUpdate;
end;
end;

冥界3大法王 发表于 2024-3-11 16:47

本帖最后由 冥界3大法王 于 2024-3-11 16:56 编辑

@wyw6813
我试着把你的代码的控件名修改了一下,没报错,也没刷新。
然后编译debug版,32位发布版本,64位的竟然把IDE卡死了。
控件需要在此下载:https://www.alphaskins.com/dwnld.php不然没有sShellListView1这个控件哟~~

procedure TForm2.Button1Click(Sender: TObject);
var
ListItem: TListItem;
I: Integer;
begin
sShellListView1.Items.BeginUpdate;
try
    for I := 0 to 5 do
    begin
      ListItem := sShellListView1.Items.Add;
      ListItem.Caption := 'Item ' + IntToStr(I);
      ListItem.SubItems.Add('Detail of Item ' + IntToStr(I));
      // 可以根据需要添加更多子项
    end;
finally
    sShellListView1.Items.EndUpdate;
end;
sShellListView1.Refresh;
end;
应该你说的对。这个控件里这部分帮助的方法啥的说的极少,应该是继承关系。
页: [1]
查看完整版本: 大事不好了!控件神经了!输出结果时好时坏!