我在运行时将此示例用于更改类:
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;
我的问题是TMyButton Size与TButton不同因为我将这个NotifyEvent添加到TMyButton。 我的问题是如何重新调整NewClass相同实例的内存分配。 : - )
答案 0 :(得分:1)
您尝试做的事情是不切实际的。如果可以找到对象的所有引用,也可以这样做。您需要这样做,因为重新分配可能导致内存驻留在不同的地址。因此您需要更新这些参考文献。
所以你需要找到:
后者要困难得多。父母持有对其子女的引用。按钮的所有者保存引用。如果我没记错的话,行动框架可以包含参考文献。我确信还有其他地方可以参考。
如果您能找到所有参考文献,那么您需要:
坦率地说,这是测试UI事件的一种可怕方式。你有很多更好的选择:
你真的应该放弃目前解决问题的方法。
答案 1 :(得分:1)
虽然我同意其他人的意见 - 你应该重新考虑一下你的方法,因为这闻起来有点俗气。但是我喜欢讨厌的东西 - 所以我要告诉你如何实现你所要求的。
关键是不要在新类中放置任何东西(因为InstanceSize需要相同)把它放在其他地方 - 如果你使用的是更新的Delphi版本(2010或更高版本),你可以这样做。否则你需要修改一下代码,但我想你明白了:
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;