user1175743
user1175743

Reputation:

TCustomListBox - How to introduce OnInsert and OnRemove methods?

I want to introduce some new methods into a custom control I am deriving from TCustomListBox.

What I want is a method that can be used when a item is added/inserted into the listbox, and a method for when an item is removed from the listbox.

What would be a good place to start with this? I know controls like TListView for example have an OnInsert event but I cannot see anything for listbox?

I wanted to introduce into my control for example:

OnInsert
OnRemove

Would I need to use some kind of API or Messages to detect when items are added/removed and then take it from there? Is there an easier way to do this or does it require some difficulty?

I tried looking at some of the VCL source but most of it is confusing for me.

Thanks in advance.

Upvotes: 2

Views: 226

Answers (1)

Deltics
Deltics

Reputation: 23056

The API you need already exists.

If you inspect the source of a TCustomListBox you will see that the mechanism by which items are added, inserted or removed from a list is implemented using window messages. For example in TListBoxString.Add() as well as house-keeping code you will see that the string is eventually added by sending a message to the control:

 Result := SendTextMessage(ListBox.Handle, LB_ADDSTRING, 0, S);

Delphi provides various mechanisms for providing handlers on control and window classes that respond to specific messages. Perhaps the most straightforward and appropriate, for adding a simple notification mechanism such as your require, is to implement a specific message handler method.

You provide a message handler procedure and declare which message it responds to. In your case, for example, you could add your own handling of the LB_ADDSTRING message:

TChattyList = class(TCustomListbox)
  procedure LBAddString(var aMessage: TMessage); message LB_ADDSTRING;
end;

The parameters of the message (wParam and lParam) are packaged up inside the TMessage record passed as the by reference parameter to your handler). You will need to consult the Windows API documentation for the message in question to determine the use of these parameters.

You can do pretty much whatever you want in your message handler although you should always pay close attention to what a window is expected to do in response to documented messages, including any return values (set in the Result field of the TMessage parameter, which is why it is passed by reference, as var.

In this trivial example, the new handler calls inherited to ensure that the inherited implementation is allowed to respond by actually adding the new item string and then crudely pops up a message box to let us know that an item was added:

procedure TChattyList.LBAddString(var aMessage: TMessage);
begin
  inherited;
  ShowMessage('item added');
end;

In essence your event mechanism will do exactly the same, but instead of presenting a message box you would trigger your new event after allowing the inherited implementation to do it's work (and checking the result code set, to ensure that it was successful, according to the expected return values for the message in question):

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;

If the inherited handler failed to add an item then according to the documentation it should set the result to LB_ERR or LB_ERRSPACE, so we test for these values and exit if they are found. Otherwise we call the appropriate event handler, if one is assigned.

This assumes that for your purposes a simple TNotifyEvent is sufficient and that you do not discriminate between an item being inserted vs an item being added. You could of course have separate events or provide some indication in parameters to a specialised event type.

Which messages you choose to handle and expose as which sorts of events is then a question of exactly what your requirements are, but based on what you have stated in your question, at a minimum I think you will need message handlers for LB_ADDSTRING, LB_INSERTSTRING and LB_DELETESTRING.

You may need to handle additional messages and should consult the Windows API documentation for listbox controls for further information.

Upvotes: 6

Related Questions