【发布时间】:2014-02-06 11:28:25
【问题描述】:
将 ListView 中的 Items.Count 设置为超过 100,000,000 的任何数字与将计数设置为 0 的结果相同 - 这是底层 Windows 控件的限制,还是特定于 Delphi?我预计限制为 20 亿左右,因为 Delphi XE4 的文档说限制是(签名)DWORD 的大小(即:2^31 - 1)。
简单示例:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls;
type
TForm1 = class(TForm)
ListView1: TListView;
procedure ListView1Data(Sender: TObject; Item: TListItem);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// Assumes ListView1.OwnerData := True;
ListView1.Items.Count := 100000001; // Works if 100000000 is used instead
end;
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := Item.Index.ToString();
end;
end.
我做了一些探索,将 LVM_SETITEMCOUNT 直接发送到底层控件,但它会返回任何超过 100,000,000 的 LPARAM 的错误并将内部计数设置为 0,这让我相信这是底层控件的限制。我在任何地方都找不到这个文档——尽管我认为拥有这么多项目并不常见。假设这是控件的限制,可能应该提交 Delphi 错误报告,因为调用失败时 TListView 不会引发异常 - 它只是默默地破坏了一切。
目前,我正在通过将列表视图保持在虚拟模式之外来解决这个问题,根据添加到列表中的控件的大小(即:VisibleRowCount 属性)准确地保持可见的项目数,维护一个偏移到我的数据中,并循环遍历列表中的项目以填充列表,其方式与虚拟模式列表基本相同,使用我自己的滚动条来控制偏移,以实际使限制达到约 20 亿。
有没有办法解决这种行为?任何有处理大量数据和 ListView 经验的人有什么见解吗?
【问题讨论】:
-
为什么VirtualTreeView不在listview模式下?
-
我尝试过使用 VirtualTreeView,但缺乏正确使用它的经验 - 虽然它很快,但从我目前所做的来看,它为列表中的每个项目分配了一个小结构,所以我遇到了大约 4000 万个项目标记的内存问题。链接到使用它的教程,以便它像虚拟列表视图一样工作?
-
@Chrisgbk:只是好奇:用户将如何浏览包含 10^8 个项目的列表视图?
-
好的,这对我来说更有意义。坦率地说,我认为我会为此选择一个完整的自定义控件,而不是从列表视图中挤出意义。很有意思。我喜欢这个问题!
标签: windows delphi listview windows-7 delphi-xe4