【发布时间】:2021-05-16 07:01:37
【问题描述】:
在虚拟模式下设置 ListView 后,ListView1.Selected.Top 始终返回 0。我在双击列表视图时使用该属性以在该位置显示编辑框。
我该如何解决这个问题?
.pas 和 .dfm 文件的示例在这里。我想在双击的位置打开编辑框。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls,Generics.Collections,Generics.Defaults;
type
TLVData = record
Column0: string;
Column1: string;
Column2: string;
end;
type
TForm1 = class(TForm)
ListView1: TListView;
Edit1: TEdit;
procedure ListView1DblClick(Sender: TObject);
procedure NewEntry(i: integer);
procedure FormShow(Sender: TObject);
procedure ListView1Data(Sender: TObject; Item: TListItem);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
LVDataList : TList<TLVData>;
implementation
{$R *.dfm}
procedure TForm1.NewEntry(i: integer);
var
LVData:TLVData;
begin
if not Assigned(LVDataList) then LVDataList := TList<TLVData>.Create;
LVData.Column0 := 'Column0:' + IntToStr(i);
LVData.Column1 := 'Column1:' + IntToStr(i);
LVData.Column2 := 'Column2:' + IntToStr(i);
LVDataList.Add(LVData);
end;
procedure TForm1.FormShow(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 9 do
NewEntry(i);
ListView1.Items.Count := LVDataList.Count;
end;
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
var i: integer;
begin
if not Assigned(Item) then Exit;
Item.Caption := LVDataList.Items[Item.Index].Column0;
Item.SubItems.Add(LVDataList.Items[Item.Index].Column0);
Item.SubItems.Add(LVDataList.Items[Item.Index].Column1);
Item.SubItems.Add(LVDataList.Items[Item.Index].Column2);
end;
procedure TForm1.ListView1DblClick(Sender: TObject);
begin
Edit1.Text:=ListView1.Selected.SubItems[0];
Edit1.Top:=ListView1.Top+ListView1.Selected.Top-2;
Edit1.Width:=100;
Edit1.Show;
Edit1.SetFocus;
end;
end.
还有.dfm:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 412
ClientWidth = 784
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object ListView1: TListView
Left = 0
Top = 0
Width = 784
Height = 412
Align = alClient
Columns = <
item
AutoSize = True
Caption = 'Column0'
MinWidth = 100
end
item
AutoSize = True
Caption = 'Column1'
MinWidth = 100
end
item
AutoSize = True
Caption = 'Column2'
MinWidth = 100
end>
GridLines = True
HideSelection = False
MultiSelect = True
OwnerData = True
ReadOnly = True
RowSelect = True
TabOrder = 0
ViewStyle = vsReport
OnData = ListView1Data
OnDblClick = ListView1DblClick
end
object Edit1: TEdit
Left = 360
Top = 168
Width = 121
Height = 21
TabOrder = 1
Text = 'Edit1'
Visible = False
end
end
【问题讨论】:
-
你在用这些信息做什么。了解这一点可能有助于人们想出替代方案。
-
我在那个位置显示编辑框。
-
您能否制作一个我们可以玩的最小但完整、可重现的示例?编辑您的问题以发布该示例的 .pas 和 .dfm 文件。
-
添加了简单的例子。
-
使用虚拟模式时,
TListView必须使用临时的TListItem来满足Selected、Items[]等属性。我发现这往往会导致微妙/不需要的副作用,所以我通常只是在虚拟模式下忽略这些属性,直接去 Win32 API 获取我需要的信息,比如ListView_GetNextItem(LVNI_SELECTED)和ListView_GetItemRect()等