Событие списка обмена, компонент
Я хочу сделать компонент на основе TListBox
,
Когда Items.Count
изменения, я хочу обновить Caption
из TLabel
:
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.
1 ответ
TListBox
наследует защищенный Changed()
метод из TControl
, который отправляет CM_CHANGED
сообщение для производных классов. TListBox
звонки Changed()
в ответ на LBN_SELCHANGE
, Вам не нужно определять свой собственный Change()
метод, просто справиться CM_CHANGED
вместо.
TListBox.SetItemIndex()
отправляет LB_SETCURSEL
сообщение в ListBox HWND
, Это сообщение не срабатывает LBN_SELCHANGE
так что вам придется обнаружить ItemIndex
изменить себя. Что вы пытались сделать.
Однако эти проблемы относятся только к изменениям выбора, а не к Item.Count
изменения. Изменение ItemIndex
не меняет Items.Count
, Если ваша цель просто показать новый Items.Count
всякий раз, когда элемент добавляется или удаляется из ListBox, вам нужно обрабатывать LB_ADDSTRING
, LB_INSERTSTRING
, LB_DELETESTRING
а также LB_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;