-
Нужно расширить список событий компоненту TButton например, добавив событие OnTagChange, для отлавливания изменений свойства Tag.
В модуле компонента делаю так: private FOnTagChange: TNotifyEvent; .. published property OnTagChange: TNotifyEvent read FOnTagChange write FOnTagChange;
Хочу отлавливать изменения через WndProc, но при инициации изменений свойства Tag вход в WndProc не происходит. Подскажите как тогда отлавливать изменение?
-
... write SetTagValueProc;
-
но при инициации изменений свойства Tag вход в WndProc не происходит.
Не должно и не происходит. Странно да?
-
У свойства по записи должна быть процедура меняющая значение вместо простого write FOnTagChange; Внутри процедуры смотрим, что новое значение отличается от текущего, проверяем, что назначен обработчик, вызваем обработчик. Ну и конечно не забываем измсенить само значение тэга на новое. Все как учили в автошколе.
-
> при инициации изменений свойства Tag вход в WndProc не происходит
А кто сказал, что должен происходить? Никто. И не должен.
Свойство Tag появляется у класса TComponent. А у этого класса никаких WndProc нет. И куда же тогда входить? Некуда.
Посмотрите объявление свойства TComponent.Tag. Если там стоит write SetTag и метод SetTag - виртуальный или динамический, то отловить изменение Tag можно, перекрыв этот метод.
Если же метода SetTag нет, либо он статический, то никак Вы это изменение не отловите. И, соответственно, никакого события не возбудите.
Да и стоит ли переопределять документированное поведение свойства Tag? Не лучше ли ввести свое, новое свойство? Тогда и проблем никаких, и документации ничто противоречить не будет.
-
Спасибо за пояснение. В итоге вместо tag создал свое свойство сам, на него завязал обрабочтик изменения, такой вариант тоже устроил.
type TRxSpeedButtonEx = class(TRxSpeedButton) private FParamsID: integer; FOnSetParamsID: TNotifyEvent; protected procedure SetParamsID(ID: Integer); published property ParamsID: Integer read FParamsID write SetParamsID default 0; property OnParamsIDChange: TNotifyEvent read FOnSetParamsID write FOnSetParamsID;
procedure TRxSpeedButtonEx.SetParamsID(ID: Integer); begin FParamsID:=ID; if assigned(FOnSetParamsID) then FOnSetParamsID(self); end;
-
а где проверка на то, что новое значение отличается от старого?
-
Вот "классический" вариант:
type
TRxSpeedButtonEx = class(TRxSpeedButton)
private
FParamsID: integer;
FOnParamsIDChange: TNotifyEvent;
procedure SetParamsID(const Value: Integer);
protected
procedure DoParamsIDChange; dynamic;
published
property ParamsID: Integer read FParamsID write SetParamsID default 0;
property OnParamsIDChange: TNotifyEvent read FOnParamsIDChange write FOnParamsIDChange;
end;
procedure TRxSpeedButtonEx.SetParamsID(const Value: Integer);
begin
if FParamsID <> Value
begin
FParamsID := Value;
DoParamsIDChange
end
end;
procedure TRxSpeedButtonEx.DoParamsIDChange;
begin
if Assigned(FParamsIDChange) then
FParamsIDChange(Self)
end;
Основное отличие в том, что потомок (возможность появления которого всегда надо предполагать), перекрыв метод DoParamsIDChange (так называемый метод диспетчеризации события), может включить свой код в цепочку обработки события без риска нарушить работу компонента.
-
> procedure DoParamsIDChange; dynamic;
Почему не virtual? Чем вы руководствовались?
-
> Kolan © (02.11.07 17:37) [8]
Если предполагается, что метод в потомках будет замещаться часто, то выгоднее virtual, если редко - то dynamic.
-
> Юрий Зотов © (02.11.07 17:48)
Буду знать, а то отличие вроде знаю, а когда конкретно что использовать поянть не мог
-
Можно "перекрыть" свойство Tag написав такое же одноимённое
TButton = class(StdCtrls.TButton)
private
fOnTagGhange: TNotifyEvent;
function GetTag: integer;
procedure SetTag(const Value: integer);
published
property Tag: integer read GetTag write SetTag;
property OnTagGhange: TNotifyEvent read fOnTagGhange write fOnTagGhange;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
public
procedure DoTagGhange(Sender: TObject);
end;
var
Form1: TForm1;
implementation
function TButton.GetTag:integer;
begin
Result := inherited Tag;
end;
procedure TButton.SetTag(const Value: integer);
begin
inherited Tag := Value;
if Assigned(OnTagGhange) then OnTagGhange(self);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.OnTagGhange := DoTagGhange;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Tag := Button1.Tag + 1;
end;
procedure TForm1.DoTagGhange(Sender: TObject);
begin
ShowMessage('DoTagGhange');
end;
-
> DimaBr © (05.11.07 08:43) [11]
А как насчет вот такой проверки:
procedure TForm1.Button1Click(Sender: TObject); begin with TComponent(Sender) do Tag := Tag + 1 end;
-
И еще: уносим новую кнопку в юнит MyButton. А в модуле с Form1 перечисляем юниты сначала в таком порядке: uses ..., MyButton, ..., StdCtrls, ...; а потом в таком: uses ..., StdCtrls, ..., MyButton, ...; и сравниваем результаты.
-
На счёт [12] абсолютно согласен, посему и написал "перекрыть" На счёт [13] - естественно пишем новый компонент, регистрируем и пользуемся, это так для примера. Само собой что прирегатива за последним юнитом, самые частые грабли - TBitMap.
-
> DimaBr © (05.11.07 12:21) [14]
Дим, это я к тому, что форум читают люди всякие, и среди них немало тех, кто в разработке компонентов искушен еще слабовато (но научиться хочет), а потому советы и пример людей в синих штанах воспринимает буквально. Так что это... немного осторожности не помешает... :о)
-
Хорошо, извиняюсь, вот так работает :))) with TButton(Sender) do
Tag := Tag + 1
-
> DimaBr © (05.11.07 12:30) [16]
До тех пор, пока новая кнопка в одном модуле с формой. А если в разных, то или работате, или не работает. Зависит от порядка перечисления модулей в uses. И если возникнет ошибка (а она в таком случае ОЧЕНЬ вероятна), то вылавливать ее будет непросто.
В общем, согласись, что код ненадежный, потому что его поведение неоднозначно и зависит от внешних факторов.
-
Если учесть вопрос автора Нужно расширить список событий компоненту TButton например, добавив событие OnTagChange, для отлавливания изменений свойства Tag. то думаю подразумевался новый компонент - наследник TButton с введением нового события.
-
> DimaBr © (05.11.07 12:56) [18]
Что, собственно, и было сделано.
|