listview - Delphi - 虚拟模式下的 TListView 问题
问题描述
在虚拟模式下设置 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
解决方案
我可以重现你的问题。我找到了解决方法:使用所选项目的显示矩形:
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;
推荐阅读
- azure - 哪种消息服务可与 Azure 函数扇出模式一起使用而无需扇回?
- docker - Docker 应用的 Nginx SSL
- django - Django 多对多 - 你如何对关系应用过滤器
- python - If 语句嵌套在 For 循环中 - 获取错误 = Series 的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()
- python - 使用PostgreSQL时如何将变量插入python
- path - PyCharm 远程解释器 [Errno 2] 没有这样的文件或目录:nvcc
- mule - 是否有 DataWeave 1.0“for”运算符?
- c# - 使用扩展授权的身份服务器 4 Windows 身份验证不起作用
- google-chrome - Chrome 未在网络推送通知中打开链接
- c# - .net:如何使用 C# 将用户添加到 Active Directory 安全组?