delphionclicksubclassonchangetlistbox

Delphi TListBox OnClick / OnChange?


Is there a trick to getting "OnChange" type of functionality with a TListBox? I can subclass the component and add a property, etc then only carry out OnClick code if the Index changes... I can also hack it with a form level variable to store the current index but just wondering if I'm overlooking the obvious before I go one way or the other.


Solution

  • There seems to be no way other than implementing this by yourself. What you need is to remember the currently selected item and whenever the ItemIndex property is changed from code or whenever the control receives the LBN_SELCHANGE notification (which currently fires the OnClick event), you will compare the item index you stored with item index which is currently selected and if they differ, fire your own OnChange event. In code of an interposed class it could be:

    type
      TListBox = class(StdCtrls.TListBox)
      private
        FItemIndex: Integer;
        FOnChange: TNotifyEvent;
        procedure CNCommand(var AMessage: TWMCommand); message CN_COMMAND;
      protected
        procedure Change; virtual;
        procedure SetItemIndex(const Value: Integer); override;
      published
        property OnChange: TNotifyEvent read FOnChange write FOnChange;
      end;
    
    implementation
    
    { TListBox }
    
    procedure TListBox.Change;
    begin
      if Assigned(FOnChange) then
        FOnChange(Self);
    end;
    
    procedure TListBox.CNCommand(var AMessage: TWMCommand);
    begin
      inherited;
      if (AMessage.NotifyCode = LBN_SELCHANGE) and (FItemIndex <> ItemIndex) then
      begin
        FItemIndex := ItemIndex;
        Change;
      end;
    end;
    
    procedure TListBox.SetItemIndex(const Value: Integer);
    begin
      inherited;
      if FItemIndex <> ItemIndex then
      begin
        FItemIndex := ItemIndex;
        Change;
      end;
    end;