TProc to TNotifyEvent
Plus de cela post dont la réponse acceptée reste très cryptique:
@Button1.OnClick := pPointer(Cardinal(pPointer( procedure (sender: tObject) begin ((sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!' end )^ ) + C)^;
je me demande si il est possible de concevoir un plus simple et simple et élégant qui ressemble à:
Button.OnClick :=
AnonProc2NotifyEvent (
procedure (Sender: TObject)
begin
((Sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!'
end
);
afin d'atteindre le même but et où AnonProc2NotifyEvent est une méthode du propriétaire de bouton avec la signature suivante:
TOwnerOfButton = class(TForm)
Button: TButton;
...
private
...
protected
function AnonProc2NotifyEvent(aProc: TProc<TObject>): TNotifyEvent;
public
...
end;
est-ce réalisable et, dans l'affirmative, comment le mettre en œuvre ?
2 réponses
Ce sera de faire le travail assez facilement:
type
TNotifyEventWrapper = class(TComponent)
private
FProc: TProc<TObject>;
public
constructor Create(Owner: TComponent; Proc: TProc<TObject>);
published
procedure Event(Sender: TObject);
end;
constructor TNotifyEventWrapper.Create(Owner: TComponent; Proc: TProc<TObject>);
begin
inherited Create(Owner);
FProc := Proc;
end;
procedure TNotifyEventWrapper.Event(Sender: TObject);
begin
FProc(Sender);
end;
function AnonProc2NotifyEvent(Owner: TComponent; Proc: TProc<TObject>): TNotifyEvent;
begin
Result := TNotifyEventWrapper.Create(Owner, Proc).Event;
end;
Owner
paramètre AnonProc2NotifyEvent
permet de gérer la durée de vie de l'objet wrapper. Sans quelque chose comme ça, vous divulgueriez des exemples de TNotifyEventWrapper
.
Pass Owner
, le composant auquel vous connectez l'événement. Par exemple:
Button1.OnClick := AnonProc2NotifyEvent(
Button1,
procedure(Sender: TObject)
begin
(Sender as TButton).Caption := 'Clicked';
end
);
Donc, lorsque le bouton est détruit, le TNotifyEventWrapper
seront également détruites. L'objet de wrapper doit vivre au moins aussi longtemps que l'objet de dont les événements sont associés. Et donc, le choix du Button1
comme le propriétaire est le naturel et évident.
Pour faire référence à ce à quoi je veux en venir, j'ai étudié Barry Kellyblog post référencé dans le précédent so post mentionné ci-dessus et a trouvé cette solution:
function TMainForm.Proc2NotifyEvent(const aProc: TNotifyReference): TNotifyEvent;
type
TVtable = array[0..3] of Pointer;
PVtable = ^TVtable;
PPVtable = ^PVtable;
begin
TMethod(Result).Code := PPVtable((@aProc)^)^^[3];
TMethod(Result).Data := Pointer((@aProc)^);
end;
Encore cryptique mais encapsuled, facilitant la tâche du codeur par rapport à la méthode initiale.
j'ai essayé de mettre de l'ordre MethRefToMethPtr et MakeNotify et mettez tout cela dans une méthode.
remarquez qu'il y avait (un léger) changement dans la signature de la méthode, l'argument aProc est devenu const.