Delphi-TListView在虚拟模式下的问题
在虚拟模式下设置ListView后,ListView1.Selected.Top始终返回0。我在双击列表视图时使用该属性在该位置显示编辑框 我如何解决这个问题 下面是.pas和.dfm文件的示例。我想在双击的位置打开编辑框Delphi-TListView在虚拟模式下的问题,listview,delphi,Listview,Delphi,在虚拟模式下设置ListView后,ListView1.Selected.Top始终返回0。我在双击列表视图时使用该属性在该位置显示编辑框 我如何解决这个问题 下面是.pas和.dfm文件的示例。我想在双击的位置打开编辑框 unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Cont
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.
单元1;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
控件、窗体、对话框、控件、集合、默认值;
类型
TLVData=记录
第0列:字符串;
第1列:字符串;
第2列:字符串;
结束;
类型
TForm1=类(TForm)
ListView1:TListView;
编辑1:TEdit;
过程列表视图1DBLclick(发送方:ToObject);
程序NewEntry(i:整数);
程序表单显示(发送方:TObject);
过程列表视图1数据(发送方:ToObject;项:TListItem);
私有的
{私有声明}
公众的
{公开声明}
结束;
变量
表1:TForm1;
LVDataList:TList;
实施
{$R*.dfm}
过程TForm1.NewEntry(i:整数);
变量
LVData:TLVData;
开始
如果未分配(LVDataList),则LVDataList:=TList.Create;
LVData.Column0:=“Column0:”+IntToStr(i);
LVData.Column1:=“Column1:”+IntToStr(i);
LVData.Column2:='Column2:'+IntToStr(i);
LVDataList.Add(LVData);
结束;
程序TForm1.FormShow(发送方:TObject);
变量
i:整数;
开始
对于i:=0到9 do
新条目(i);
ListView1.Items.Count:=LVDataList.Count;
结束;
过程TForm1.ListView1数据(发送方:ToObject;项:TListItem);
varⅠ:整数;
开始
如果未分配(项目),则退出;
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);
结束;
程序TForm1.ListView1DblClick(发送方:ToObject);
开始
Edit1.Text:=ListView1.Selected.SubItems[0];
Edit1.Top:=ListView1.Top+ListView1.Selected.Top-2;
编辑1.宽度:=100;
编辑1.表演;
Edit1.SetFocus;
结束;
结束。
和.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
对象格式1:t格式1
左=0
Top=0
标题='Form1'
ClientHeight=412
ClientWidth=784
颜色=clBtnFace
Font.Charset=默认字符集
Font.Color=clWindowText
字体高度=-11
Font.Name='Tahoma'
Font.Style=[]
OldCreateOrder=False
OnShow=FormShow
PixelsPerInch=96
text高度=13
对象列表视图1:TListView
左=0
Top=0
宽度=784
高度=412
Align=alClient
列=<
项目
自动调整大小=真
标题='Column0'
最小宽度=100
结束
项目
自动调整大小=真
标题='Column1'
最小宽度=100
结束
项目
自动调整大小=真
标题='Column2'
最小宽度=100
结束>
网格线=真
HideSelection=False
多选=真
OwnerData=True
只读=真
RowSelect=True
TabOrder=0
ViewStyle=vsReport
OnData=ListView1Data
OnDblClick=ListView1DblClick
结束
对象Edit1:TEdit
左=360
Top=168
宽度=121
高度=21
TabOrder=1
Text='Edit1'
可见=假
结束
结束
我可以重现您的问题。我找到了一个解决方法:使用所选项目的显示矩形:
procedure TForm1.ListView1DblClick(Sender: TObject);
var
Rect : TRect;
begin
Rect := ListView1.Selected.DisplayRect(drBounds);
Edit1.Text := ListView1.Selected.SubItems[0];
Edit1.Top := ListView1.Top + Rect.Top - 1;
Edit1.Width :=100;
Edit1.Show;
Edit1.SetFocus;
end;
如果要获取子项,则必须遍历列以查找用户单击的列。我们需要确定鼠标的位置,以便安装OnMouseDown事件处理程序来保存鼠标坐标,并使用它来查找列
private
FMouseDown : TPoint;
procedure TForm1.ListView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
FMouseDown.X := X;
FMouseDown.Y := Y;
end;
procedure TForm1.ListView1DblClick(Sender: TObject);
var
Rect : TRect;
I : Integer;
X1, X2 : Integer;
Col : Integer;
begin
if not Assigned(ListView1.Selected) then
Exit;
Rect := ListView1.Selected.DisplayRect(drBounds);
X1 := 0;
X2 := 0;
Col := -1;
for I := 0 to ListView1.Columns.Count - 1 do begin
X2 := X2 + ListView1.Columns[0].Width;
if (FMouseDown.X >= X1) and (FMouseDown.X < X2) then begin
Col := I;
break;
end;
X1 := X2;
end;
if Col < 0 then
Exit;
Edit1.Text := ListView1.Selected.SubItems[0];
Edit1.Top := ListView1.Top + Rect.Top - 1;
Edit1.Left := X1;
Edit1.Width := X2 - X1; // Same width as column
Edit1.Show;
Edit1.SetFocus;
end;
private
FMouseDown:TPoint;
程序TForm1.ListView1MouseDown(发送方:ToObject;按钮:TMouseButton;
移位:t移位状态;X,Y:整数);
开始
FMouseDown.X:=X;
FMouseDown.Y:=Y;
结束;
程序TForm1.ListView1DblClick(发送方:ToObject);
变量
Rect:TRect;
I:整数;
X1,X2:整数;
Col:整数;
开始
如果未分配(ListView1.选中),则
出口
Rect:=ListView1.Selected.DisplayRect(drBounds);
X1:=0;
X2:=0;
Col:=-1;
对于I:=0到ListView1.Columns.Count-1,请不要开始
X2:=X2+ListView1。列[0]。宽度;
如果(FMouseDown.X>=X1)和(FMouseDown.X
你在用这些信息做什么。知道这一点可能会帮助人们想出一个替代方案。我在那个位置显示编辑框。你们能提供一个最小但完整的,可复制的例子,我们可以玩吗?编辑您的问题以发布该示例的.pas和.dfm文件。添加了简单示例。在使用虚拟模式时,TListView
必须使用临时的TListItem
,以满足选定的,项[]
等属性。我发现这往往会导致微妙/不必要的副作用,因此,我通常在虚拟模式下忽略这些属性,直接转到Win32 API以获取所需的信息,如ListView\u GetNextItem(LVNI\u SELECTED)
和ListView\u GetItemRect()
,等等。附加问题:如何获取列的左位置?网格处于行选择模式。有什么更好的方法可以从每一列的宽度计算出来吗?编辑了我的答案。顺便说一句,下次你提问的时候,你应该更好地阐述你的问题。