Delphi TCustomListBox-如何引入OnInsert和OnRemove方法?

Delphi TCustomListBox-如何引入OnInsert和OnRemove方法?,delphi,delphi-xe,Delphi,Delphi Xe,我想在我从TCustomListBox派生的自定义控件中引入一些新方法 我想要的是一个在列表框中添加/插入项目时可以使用的方法,以及一个从列表框中删除项目时可以使用的方法 从什么地方开始比较好?我知道像TListView这样的控件有一个OnInsert事件,但是我看不到listbox的任何内容 例如,我想在我的控制中引入: OnInsert OnRemove 我是否需要使用某种API或消息来检测何时添加/删除项目,然后从中获取?有没有更简单的方法,或者需要一些困难 我试着看了一些VCL源代码,

我想在我从
TCustomListBox
派生的自定义控件中引入一些新方法

我想要的是一个在列表框中添加/插入项目时可以使用的方法,以及一个从列表框中删除项目时可以使用的方法

从什么地方开始比较好?我知道像
TListView
这样的控件有一个
OnInsert
事件,但是我看不到listbox的任何内容

例如,我想在我的控制中引入:

OnInsert
OnRemove
我是否需要使用某种API或消息来检测何时添加/删除项目,然后从中获取?有没有更简单的方法,或者需要一些困难

我试着看了一些VCL源代码,但大部分都让我感到困惑


提前感谢。

您需要的API已经存在

如果检查TCustomListBox的源,您将看到添加、插入或删除列表项的机制是使用窗口消息实现的。例如,在TListBoxString.Add()以及house keeping code中,您将看到通过向控件发送消息最终添加了字符串:

 Result := SendTextMessage(ListBox.Handle, LB_ADDSTRING, 0, S);
Delphi提供了各种机制,为响应特定消息的控件和窗口类提供处理程序。对于添加一个简单的通知机制(如require),最直接、最合适的方法可能是实现一个特定的消息处理程序方法

您提供了一个消息处理程序过程,并声明它响应的消息。例如,在您的情况下,您可以添加自己对LB_ADDSTRING消息的处理:

TChattyList = class(TCustomListbox)
  procedure LBAddString(var aMessage: TMessage); message LB_ADDSTRING;
end;
消息的参数(wParamlParam)打包在TMessage记录中,作为by-reference参数传递给处理程序)。您需要查阅有关消息的Windows API文档,以确定这些参数的使用

在消息处理程序中,您几乎可以做任何您想做的事情,尽管您应该始终密切关注窗口在响应文档化的消息时应该做什么,包括任何返回值(在TMessage参数的Result字段中设置,这就是它作为var通过引用传递的原因

在这个简单的示例中,新处理程序调用inherited,以确保允许继承的实现通过实际添加新项字符串来响应,然后粗略地弹出一个消息框,让我们知道已添加项:

procedure TChattyList.LBAddString(var aMessage: TMessage);
begin
  inherited;
  ShowMessage('item added');
end;
本质上,您的事件机制将执行完全相同的操作,但在允许继承的实现完成其工作(并根据相关消息的预期返回值检查结果代码集以确保其成功)后,您将触发新事件,而不是显示消息框:

如果继承的处理程序未能添加项,则根据文档,它应将结果设置为LB_ERRLB_ERRSPACE,因此我们测试这些值,如果找到它们,则退出。否则,如果分配了相应的事件处理程序,则调用相应的事件处理程序

这假设就您的目的而言,一个简单的事件就足够了,并且您不会区分插入的项目和添加的项目。当然,您可以有单独的事件,或者在参数中为专门的事件类型提供一些指示

您选择将哪些消息作为何种类型的事件进行处理和公开,这是一个您的需求到底是什么的问题,但根据您在问题中所述,我认为您至少需要LB_ADDSTRINGLB_INSERTSTRINGLB_DELETESTRING的消息处理程序

您可能需要处理其他消息,并应咨询

procedure TChattyList.LBAddString(var aMessage: TMessage);
begin
  inherited;

  if (aMessage.Result = LB_ERR) or (aMessage.Result = LB_ERRSPACE) then
    EXIT;

  if Assigned(fOnInsert) then
    fOnInsert(self);
end;