I Use This Sample for Change Class at run-time :
procedure PatchInstanceClass(Instance: TObject; NewClass: TClass);
type
PClass = ^TClass;
begin
if Assigned(Instance) and Assigned(NewClass)
and NewClass.InheritsFrom(Instance.ClassType)
and (NewClass.InstanceSize = Instance.InstanceSize) then
begin
PClass(Instance)^ := NewClass;
end;
end;
type
TMyButton = class(TButton)
Private
FLogEvent : TNotifyEvent;
public
Property Log : TNotifyEvent Read FLogEvent Write FLogEvent;
procedure Click; override;
end;
procedure TMyButton.Click;
begin
Inherited;
if Assigned(FLogEvent) then
FLogEvent(Self);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
PatchInstanceClass(Button1, TMyButton);
end;
My Problem is that TMyButton Size is different with TButton Because I Add this a NotifyEvent to TMyButton. My Question is how can I Re-size memory Allocation for NewClass same Instance. :-)
While I agree with the others - you should rethink your approach, as this smells a bit hacky. However I like hacky things - so I am going to show you how you can achieve what you are asking for.
The key is to not put anything inside your new class (as the InstanceSize needs to be the same) put it somewhere else - if you are using a newer Delphi version (2010 or higher) you can do it like this. Otherwise you need to modify the code a bit but I guess you get the idea:
uses
Generics.Collections;
procedure PatchInstanceClass(Instance: TObject; NewClass: TClass);
begin
if Assigned(Instance) and Assigned(NewClass)
and NewClass.InheritsFrom(Instance.ClassType)
and (NewClass.InstanceSize = Instance.InstanceSize) then
begin
PPointer(Instance)^ := NewClass;
end;
end;
type
TMyButton = class(TButton)
private
function GetLogEvent: TNotifyEvent;
procedure SetLogEvent(const Value: TNotifyEvent);
public
destructor Destroy; override;
procedure Click; override;
property LogEvent: TNotifyEvent read GetLogEvent write SetLogEvent;
end;
TMyButtonHelper = class helper for TMyButton
private
class var fLogEvents: TDictionary<TObject, TNotifyEvent>;
public
class constructor Create;
class destructor Destroy;
end;
{ TMyButtonHelper }
class constructor TMyButtonHelper.Create;
begin
fLogEvents := TDictionary<TObject, TNotifyEvent>.Create;
end;
class destructor TMyButtonHelper.Destroy;
begin
fLogEvents.Free;
end;
{ TMyButton }
destructor TMyButton.Destroy;
begin
fLogEvents.Remove(Self);
inherited;
end;
procedure TMyButton.Click;
begin
inherited;
if Assigned(LogEvent) then
LogEvent(Self);
end;
function TMyButton.GetLogEvent: TNotifyEvent;
begin
fLogEvents.TryGetValue(Self, Result);
end;
procedure TMyButton.SetLogEvent(const Value: TNotifyEvent);
begin
fLogEvents.AddOrSetValue(Self, Value);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
PatchInstanceClass(Button1, TMyButton);
TMyButton(Button1).LogEvent := Button1Click;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With