作者:水晶玻璃新座 | 来源:互联网 | 2023-01-22 09:41
将项目添加到TListView时如何捕获事件?
OnInsert
根据文件,我认为该活动将起到作用.它甚至将实际TListItem
对象传递给处理程序:
OnInsert在将新项插入列表视图后立即发生.
编写一个OnInsert事件处理程序,以便在项刚刚添加到列表时进行响应.Item参数是添加到Items属性的TListItem对象
这是我的代码:
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;
![图片](https://img.php1.cn/3cd4a/94ce/a6e/865776f6fe3d5f59.jpeg)
为什么是这样?
1> Remy Lebeau..:
将TListView.OnInsert
新项添加到ListView时,确实会触发该事件.但是,在调用时会将其Item
添加到ListView中TListView.Items.Add()
,而不是在Button1Click()
退出时添加到ListView中.该OnInsert
事件处理函数(响应LVN_INSERTITEM
通知),同时Add()
仍在运行.因此,当然Item
在OnInsert
事件处理程序将永远是空的,因为你还没有分配任何值呢.
更新:当a TListItem
添加到ListView时,未启用LVIF_TEXT
基础的标志LVITEM
.要显示TListItem.Caption
和TListItem.SubItems
文本,TListView
旨在依靠ListView_SetItemText()
与LPSTR_TEXTCALLBACK
标志来代替:
此参数可以是LPSTR_TEXTCALLBACK,以指示父窗口存储文本的回调项.在这种情况下,列表视图控件LVN_GETDISPINFO
在需要文本时向父级发送通知代码.
如果在尚未实际位于ListView中的情况下分配TListItem.Caption
or TListItem.SubItems
属性TListItem
,则该LPSTR_TEXTCALLBACK
标志将不会应用于这些字段. LVN_GETDISPINFO
不会查询TListView
的第一列中没有文本LPSTR_TEXTCALLBACK
(如0列有在OS层特殊的含义),但它确实查询中第二列的文本(即使LPSTR_TEXTCALLBACK
不应用到它).这就是为什么你的第二个例子缺少'foo2'
UI中的标题文本,而不是'bar2'
文本.
实际的'foo2'
标题字符串存储在TListItem
对象中,这就是您ShowMessage()
能够工作的原因.
因此,如果您在将项目添加到ListView之前创建新的TListItem
并修改它Caption
,则必须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
文本都不会出现在UI中,直到OnInsert
首先调用该事件,因为它在AddItem()
运行时被触发.
我在XE2中重现了这一点.如果问题仍然发生在10.2东京,我建议向 Embarcadero 提交一份错误报告. AddItem()
应该LPSTR_TEXTCALLBACK
在插入任何已经分配的字符串字段之后强制执行,或者至少应该强制执行Caption
.
设置项目并使用AddItem.