【问题标题】:Copy Sub Item Of List View Delphi Into Clipboard将列表视图 Delphi 的子项复制到剪贴板
【发布时间】:2016-11-02 18:53:57
【问题描述】:

我有一个包含八列和一个弹出菜单的列表视图。 [截图]

I have this code which is work great to copy into clipboard all items and sub items when a row or all rows selected.

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;

我需要的是,我只想复制第一列的标题(“标题”列)及其子项 [0],并复制第 8 列的标题(“URL”列)及其子项 [ 7] 进入剪贴板,当一行或所有行被选中时。

有时 sub items[7] 是空的,它不应该得到 index out of bounds (7) 错误消息。

从我上面的截图中,当我复制第一行时,结果应该像这样返回

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。我如何实现这一点?任何帮助将不胜感激。

【问题讨论】:

  • 是什么阻止你复制你想要的东西?
  • @SertacAkyuz 使用上面的代码,我复制了所有子项目,如下所示:No : 2, Title : 10 Things You Didn't Know..., Quality : webm 256x144, Size : 3.09 MB, % : 100.0%, Speed : 568.05 KB/s, ETA : 00:00 , status : Done...!, URL : https://www.example.com 而我只需要Title : 10 Things You Didn't Know... URL : https://www.example.com
  • 你必须写出你想要的代码。您可能想开始阅读if statement
  • 我已经了解了 if 语句。但是作为初学者,我无法正确弄清楚。我试过这样写for f := 0 to lv.Items.Count - 1 do beginif lv.Items[f].Selected thens := 'Title :' + lv.Items[f].SubItems[0] + 'URL : ' +lv.Items[f].SubItems[7]; 。似乎确实有效,但是当 subitems[7] 为空时,我会从债券中获取索引
  • 这就是你要使用'if'的地方。测试是否有子项[7],如果有则继续粘贴的行,如果没有,使用s := 'Title :' + lv.Items[f].SubItems[0] + 'URL :

标签: listview delphi copy clipboard subitem


【解决方案1】:

您的剪贴板文本包含所有列值,因为您正在循环遍历所有 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;

话虽如此,另一种选择是在虚拟模式下使用TListViewOwnerData=True),您可以将所有数据存储在单独的列表中。然后您可以直接访问您的数据列表,而无需触摸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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多