列表框 onchange 事件,组件

Listbox Onchange Event, component

我想做一个基于TListBox的组件。

Items.Count改变时,我想更新TLabelCaption:

Label1.Caption := IntToStr(ListBox1.Items.Count);

我制作了下面的组件,但它不起作用:

unit UChangeListBox;

interface

uses
  Classes, StdCtrls, Messages;

type
  TChListBox = class(StdCtrls.TListBox)
  private
    FItemIndex: Integer;
    FOnChange: TNotifyEvent;
    procedure CNCommand(var AMessage: TWMCommand); message CN_COMMAND;
  protected
    procedure DoChange; virtual;
    procedure SetItemIndex(const Value: Integer); override;
  published
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

procedure Register;

implementation

procedure TChListBox.DoChange;
begin
  if Assigned(FOnChange) then
    FOnChange(Self);
end;

procedure TChListBox.CNCommand(var AMessage: TWMCommand);
begin
  inherited;
  if (AMessage.NotifyCode = LBN_SELCHANGE) and (FItemIndex <> ItemIndex) then
  begin
    FItemIndex := ItemIndex;
    DoChange;
  end;
end;

procedure TChListBox.SetItemIndex(const Value: Integer);
begin
  inherited;
  if FItemIndex <> ItemIndex then
  begin
    FItemIndex := Value;
    DoChange;
  end;
end;

procedure Register;
begin
  RegisterComponents('MyComponents',[TChListBox]);
end;

end.

TListBoxTControl 继承了一个受保护的 Changed() 方法,它向派生的 类 发送 CM_CHANGED 消息。 TListBox 调用 Changed() 回复 LBN_SELCHANGE。您不需要定义自己的 Change() 方法,只需处理 CM_CHANGED 即可。

TListBox.SetItemIndex() 向列表框 HWND 发送 LB_SETCURSEL 消息。该消息不会触发 LBN_SELCHANGE,因此您必须自己检测 ItemIndex 更改。你试图做的。

但是,这些问题仅适用于选择更改,不适用于Item.Count更改。更改 ItemIndex 不会更改 Items.Count。如果您的目标只是在列表框中添加或删除项目时显示新的 Items.Count,则需要处理 LB_ADDSTRINGLB_INSERTSTRINGLB_DELETESTRINGLB_RESETCONTENT 消息。

试试像这样的东西:

type
  TChListBox = class(TListBox)
  private
    FOnItemCountChange: TNotifyEvent;
  protected
    procedure WndProc(var Message: TMessage); override;
  published
    property OnItemCountChange: TNotifyEvent read FOnItemCountChange write FOnItemCountChange;
  end;

procedure TChListBox.WndProc(var Message: TMessage);
var
  OldCount: Integer;
begin
  case Message.Msg of
    LB_ADDSTRING, LB_INSERTSTRING, LB_DELETESTRING:
    begin
      // for LB_(ADD|INSERT)STRING, Message.Result is the 0-based
      // index of the added string, or a LB_ERR... error code.
      //
      // for LB_DELETESTRING, Message.Result is the number of items
      // remaining in the list, or a LB_ERR... error code.
      //
      inherited;
      if (Message.Result >= 0) and Assigned(FOnItemCountChange) then
        FOnItemCountChange(Self);
    end;
    LB_RESETCONTENT:
    begin
      // the Message.Result is not used in this message.
      //
      OldCount := Items.Count;
      inherited;
      if (OldCount <> Items.Count) and Assigned(FOnItemCountChange) then
        FOnItemCountChange(Self);
    end;
  else
    inherited;
  end;
end;