listview - TListView:已添加项目?

标签 listview delphi delphi-7 tlistview

当项目添加到 TListView 时,如何捕获事件?

根据文档,我认为 OnInsert 事件可以完成这项工作。它甚至将实际的 TListItem 对象传递给处理程序:

OnInsert Occurs immediately after a new item is inserted into the list view.

Write an OnInsert event handler to respond when an item has just been added to the list. The Item parameter is the TListItem object that was added to the Items property

这是我的代码:

procedure TForm1.Button1Click(Sender: TObject);
begin
  with ListView1.Items.Add do
  begin
     Caption := 'foo';
     SubItems.Add('bar');
  end;
end;

procedure TForm1.TListView1Insert(Sender: TObject; Item: TListItem);
begin
   //Item is empty
   ShowMessage(Item.Caption);
end;

但令人惊讶的是,Item.Caption 始终为空。对我来说似乎是无稽之谈。

编辑:

按照建议切换到 Items.AddItem() 会导致另一个奇怪的问题。 OnInsert 事件处理程序现在按预期工作,但 TListView 不显示 TListItem.Caption

procedure TForm1.Button1Click(Sender: TObject);
begin
  with ListView1.Items.Add do
  begin
     Caption := 'foo1';
     SubItems.Add('bar1');
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  item: TListItem;
begin
  item := TListItem.Create(ListView1.Items);
  item.Caption := 'foo2';
  item.Subitems.Add('bar2');
  ListView1.Items.AddItem(item);
end; 

procedure TForm1.ListView1Insert(Sender: TObject; Item: TListItem);
begin
  //this now works as expected
  ShowMessage(Item.Caption);
end;

image

这是为什么?

最佳答案

TListView.OnInsert当新项目添加到 ListView 时,事件确实会被触发。然而,ItemTListView.Items.Add() 时添加到 ListView被调用,而不是在 Button1Click() 时调用退出。 OnInsertLVN_INSERTITEM 时调用事件处理程序(响应 Add() 通知)仍在运行。所以,当然是ItemOnInsert事件处理程序将始终为空,因为您尚未为其分配任何值。

<小时/>

更新:当 TListItem添加到 ListView 后,LVIF_TEXT底层证券标志 LVITEM 未启用。显示TListItem.CaptionTListItem.SubItems文本,TListView设计依赖 ListView_SetItemText() LPSTR_TEXTCALLBACK改为标记:

This parameter can be LPSTR_TEXTCALLBACK to indicate a callback item for which the parent window stores the text. In this case, the list-view control sends the parent an LVN_GETDISPINFO notification code when it needs the text.

如果您分配TListItem.CaptionTListItem.SubItems属性(property)而TListItem实际上还没有在 ListView 中,LPSTR_TEXTCALLBACK标志不会应用于这些字段。 LVN_GETDISPINFO不会查询TListView对于没有 LPSTR_TEXTCALLBACK 的第一列文本(因为第 0 列在操作系统层具有特殊含义),但它确实查询第二列的文本(即使 LPSTR_TEXTCALLBACK 未应用于它)。这就是为什么你的第二个例子缺少 'foo2' UI 中的标题文本,但不是 'bar2'文本。

实际'foo2'标题字符串存储在TListItem中对象,这就是为什么你的 ShowMessage()可以工作。

所以,如果您创建一个新的 TListItem并修改其Caption在将项目添加到 ListView 之前,您必须调用 ListView_SetItemText()手动启用 LPSTR_TEXTCALLBACK标题标志,例如:

uses
  Commctrl;

procedure TForm1.Button2Click(Sender: TObject);
var
  item: TListItem;
begin
  item := TListItem.Create(ListView1.Items);
  item.Caption := 'foo2';
  item.Subitems.Add('bar2');
  ListView1.Items.AddItem(item);
  ListView_SetItemText(ListView1.Handle, item.Index, 0, LPSTR_TEXTCALLBACK);
end; 

或者,重置 Caption临时属性值(属性 setter 在调用 ListView_SetItemText() 之前检查重复字符串):

procedure TForm1.Button2Click(Sender: TObject);
var
  item: TListItem;
begin
  item := TListItem.Create(ListView1.Items);
  item.Caption := 'foo2';
  item.Subitems.Add('bar2');
  ListView1.Items.AddItem(item);
  item.Caption := '';
  item.Caption := 'foo2';
end; 

请注意,无论哪种方式,TListItem.Caption直到 OnInsert 之后文本才会出现在 UI 中首先调用事件,因为它是在 AddItem() 时触发的。正在运行。

我在 XE2 中重现了这个。如果问题在10.2东京仍然出现,我建议filing a bug report与内河码头。 AddItem()可能应该强制LPSTR_TEXTCALLBACK插入任何已分配的字符串字段后,或至少 Caption无论如何。

关于listview - TListView:已添加项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45806324/

相关文章:

Delphi,如何在鼠标移动时显示覆盖控件

listview - Xamarin 和 MVVM 如何?

android - 从 customAdapter 中的 ListView 获取文本

delphi - For循环用于编辑中的反向单词

http - Delphi Indy HTTPS 检测来自 Web 服务器的最新文件

delphi - 从 Firebird 数据库中删除垃圾

delphi - 如何禁用 PNG 的透明度

android - notifyDataSetChanged() - IndexOutOfBoundException

android - espresso 长按菜单项和弹出菜单

delphi - 在 Delphi 中使用 OPOS 驱动程序检查打印机消息