将列表视图 Delphi 的子项复制到剪贴板
Copy Sub Item Of List View Delphi Into Clipboard
我有一个包含八列的列表视图和一个弹出菜单。
[屏幕截图]
我有这段代码,它非常适合在选中一行或所有行时将所有项目和子项目复制到剪贴板。
procedure TForm1.CopyURL1Click(Sender: TObject);
var
lv : TbsSkinListView;
s : string;
c,f,k : integer;
begin
lv := bsSkinListView1;
Clipboard.Clear;
s := '';
for f := 0 to lv.Items.Count - 1 do
begin
k := 0;
if lv.Items[f].Selected then
begin
s := s + Format('%s : %s, ',[lv.Columns[k].Caption, lv.Items[f].Caption]);
for c := 0 to lv.Items[f].SubItems.Count - 1 do
begin
Inc(k);
s := s + Format('%s : %s, ',[lv.Columns[k].Caption, lv.Items[f].SubItems[c]]);
end;
SetLength(s, Length(s) - 2);
s := s + #$D#$A;
end;
end;
clipboard.AsText := s;
end;
我需要的是只复制第一列(第 "Title" 列)的标题及其子项 [0],并复制第 8 列的标题(第 "URL" 列) ) 将它的子项 [7] 放入剪贴板,当一行或所有行被选中时。
也有的时候子项[7]是空的,应该不会得到index out of bounds (7)错误信息。
从我上面的屏幕截图来看,当我复制第一行时,结果应该 return 像这样
Title : 10 Things You Didn't Know... URL : <=== this is an empty sub items [7]
复制第二行时:
Title : 10 Things You Didn't Know... URL : http://www.example.com
已选择所有行:
Title : 10 Things You Didn't Know... URL :
Title : 10 Things You Didn't Know... URL : http://www.example.com
我试过这个 link 但它不符合我的需要或无法正常工作。我正在使用 Delphi XE 4。我该如何实现?任何帮助将不胜感激。
您的剪贴板文本包含所有列值,因为您正在遍历所有 TListItem.SubItems
值。如果您不想要所有的值,只需不再循环即可。只需访问您想要的特定项目。
试试像这样的东西:
procedure TForm1.CopyURL1Click(Sender: TObject);
var
s : string;
item: TListItem;
begin
s := '';
item := bsSkinListView1.GetNextItem(nil, sdAll, [isSelected]);
while item <> nil do
begin
s := s + Format('Title : %s, ', [item.Caption]);
if item.SubItems.Count > 7 then
s := s + Format('URL : %s, ', [item.SubItems[7]]);
s[Length(s)-1] := #$D;
s[Length(s)] := #$A;
item := bsSkinListView1.GetNextItem(item, sdAll, [isSelected]);
end;
Clipboard.Open;
try
Clipboard.Clear;
Clipboard.AsText := s;
finally
Clipboard.Close;
end;
end;
话虽如此,另一种选择是在虚拟模式 (OwnerData=True
) 中使用 TListView
,将所有数据存储在单独的列表中。然后您可以直接访问您的数据列表,而无需触摸 TListView
。例如:
type
PMyData = ^TMyData;
TMyData = record
Selected: Boolean;
Title: String;
...
URL: string;
end;
TForm1 = class(TForm)
...
private
MyData: TList;
...
end;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
MyData := TList.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
I: Integer;
begin
for I := 0 to MyData.Count-1 do
Dispose(PMyData(MyData[I]));
MyData.Free;
end;
procedure TForm1.bsSkinListView1Data(Sender: TObject; Item: TListItem);
var
Data: PMyData;
begin
Data := PMyData(MyData[Item.Index]);
Item.Caption := Data.Title;
Item.SubItems.Add(...);
...
Item.SubItems.Add(Data.URL);
Item.Data := Data;
end;
procedure TForm1.TForm1.bsSkinListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
var
I: Integer;
begin
if Item <> nil then
Item.Selected := Selected
else
begin
for I := 0 to MyData.Count-1 do
PMyData(MyData[I]).Selected := Selected;
end;
end;
procedure TForm1.TForm1.bsSkinListView1DataStateChange(Sender: TObject; StartIndex, EndIndex: Integer; OldState, NewState: TItemStates);
var
I: Integer;
begin
if (OldState * [isSelected]) <> (NewState * [isSelected]) then
begin
for I := StartIndex to EndIndex do
PMyData(MyData[I]).Selected := (isSelected in NewState);
end;
end;
procedure TForm1.AddItem1Click(Sender: TObject);
var
Data: PMyData;
begin
New(Data);
try
Data.Selected := False;
Data.Title := ...;
...
Data.URL := ...;
MyData.Add(Data);
except
Dispose(Data);
raise;
end;
bsSkinListView1.Items.Count := MyData.Count;
end;
procedure TForm1.CopyURL1Click(Sender: TObject);
var
s : string;
Data: PMyData;
I: Integer;
begin
s := '';
for I := 0 to MyData.Count-1 do
begin
Data := PMyData(MyData[I]);
if Data.Selected then
begin
s := s + Format('Title : %s, ', [Data.Title]);
if item.URL <> '' then
s := s + Format('URL : %s, ', [Data.URL]);
s[Length(s)-1] := #$D;
s[Length(s)] := #$A;
end;
end;
Clipboard.Open;
try
Clipboard.Clear;
Clipboard.AsText := s;
finally
Clipboard.Close;
end;
end;
我有一个包含八列的列表视图和一个弹出菜单。
[屏幕截图]
我有这段代码,它非常适合在选中一行或所有行时将所有项目和子项目复制到剪贴板。
procedure TForm1.CopyURL1Click(Sender: TObject);
var
lv : TbsSkinListView;
s : string;
c,f,k : integer;
begin
lv := bsSkinListView1;
Clipboard.Clear;
s := '';
for f := 0 to lv.Items.Count - 1 do
begin
k := 0;
if lv.Items[f].Selected then
begin
s := s + Format('%s : %s, ',[lv.Columns[k].Caption, lv.Items[f].Caption]);
for c := 0 to lv.Items[f].SubItems.Count - 1 do
begin
Inc(k);
s := s + Format('%s : %s, ',[lv.Columns[k].Caption, lv.Items[f].SubItems[c]]);
end;
SetLength(s, Length(s) - 2);
s := s + #$D#$A;
end;
end;
clipboard.AsText := s;
end;
我需要的是只复制第一列(第 "Title" 列)的标题及其子项 [0],并复制第 8 列的标题(第 "URL" 列) ) 将它的子项 [7] 放入剪贴板,当一行或所有行被选中时。
也有的时候子项[7]是空的,应该不会得到index out of bounds (7)错误信息。
从我上面的屏幕截图来看,当我复制第一行时,结果应该 return 像这样
Title : 10 Things You Didn't Know... URL : <=== this is an empty sub items [7]
复制第二行时:
Title : 10 Things You Didn't Know... URL : http://www.example.com
已选择所有行:
Title : 10 Things You Didn't Know... URL :
Title : 10 Things You Didn't Know... URL : http://www.example.com
我试过这个 link 但它不符合我的需要或无法正常工作。我正在使用 Delphi XE 4。我该如何实现?任何帮助将不胜感激。
您的剪贴板文本包含所有列值,因为您正在遍历所有 TListItem.SubItems
值。如果您不想要所有的值,只需不再循环即可。只需访问您想要的特定项目。
试试像这样的东西:
procedure TForm1.CopyURL1Click(Sender: TObject);
var
s : string;
item: TListItem;
begin
s := '';
item := bsSkinListView1.GetNextItem(nil, sdAll, [isSelected]);
while item <> nil do
begin
s := s + Format('Title : %s, ', [item.Caption]);
if item.SubItems.Count > 7 then
s := s + Format('URL : %s, ', [item.SubItems[7]]);
s[Length(s)-1] := #$D;
s[Length(s)] := #$A;
item := bsSkinListView1.GetNextItem(item, sdAll, [isSelected]);
end;
Clipboard.Open;
try
Clipboard.Clear;
Clipboard.AsText := s;
finally
Clipboard.Close;
end;
end;
话虽如此,另一种选择是在虚拟模式 (OwnerData=True
) 中使用 TListView
,将所有数据存储在单独的列表中。然后您可以直接访问您的数据列表,而无需触摸 TListView
。例如:
type
PMyData = ^TMyData;
TMyData = record
Selected: Boolean;
Title: String;
...
URL: string;
end;
TForm1 = class(TForm)
...
private
MyData: TList;
...
end;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
MyData := TList.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
I: Integer;
begin
for I := 0 to MyData.Count-1 do
Dispose(PMyData(MyData[I]));
MyData.Free;
end;
procedure TForm1.bsSkinListView1Data(Sender: TObject; Item: TListItem);
var
Data: PMyData;
begin
Data := PMyData(MyData[Item.Index]);
Item.Caption := Data.Title;
Item.SubItems.Add(...);
...
Item.SubItems.Add(Data.URL);
Item.Data := Data;
end;
procedure TForm1.TForm1.bsSkinListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
var
I: Integer;
begin
if Item <> nil then
Item.Selected := Selected
else
begin
for I := 0 to MyData.Count-1 do
PMyData(MyData[I]).Selected := Selected;
end;
end;
procedure TForm1.TForm1.bsSkinListView1DataStateChange(Sender: TObject; StartIndex, EndIndex: Integer; OldState, NewState: TItemStates);
var
I: Integer;
begin
if (OldState * [isSelected]) <> (NewState * [isSelected]) then
begin
for I := StartIndex to EndIndex do
PMyData(MyData[I]).Selected := (isSelected in NewState);
end;
end;
procedure TForm1.AddItem1Click(Sender: TObject);
var
Data: PMyData;
begin
New(Data);
try
Data.Selected := False;
Data.Title := ...;
...
Data.URL := ...;
MyData.Add(Data);
except
Dispose(Data);
raise;
end;
bsSkinListView1.Items.Count := MyData.Count;
end;
procedure TForm1.CopyURL1Click(Sender: TObject);
var
s : string;
Data: PMyData;
I: Integer;
begin
s := '';
for I := 0 to MyData.Count-1 do
begin
Data := PMyData(MyData[I]);
if Data.Selected then
begin
s := s + Format('Title : %s, ', [Data.Title]);
if item.URL <> '' then
s := s + Format('URL : %s, ', [Data.URL]);
s[Length(s)-1] := #$D;
s[Length(s)] := #$A;
end;
end;
Clipboard.Open;
try
Clipboard.Clear;
Clipboard.AsText := s;
finally
Clipboard.Close;
end;
end;