我想要一个事件告诉我一个新对象刚刚在运行时创建(或销毁)。
没有在创建或销毁对象时触发的内置事件。
因为我喜欢写代码钩子,所以我提供以下单元。这会在System 单元中挂钩_AfterConstruction 方法。理想情况下,它应该使用蹦床,但我从未学会如何实现这些。如果您使用真正的挂钩库,您将能够做得更好。无论如何,这里是:
unit AfterConstructionEvent;
interface
var
OnAfterConstruction: procedure(Instance: TObject);
implementation
uses
Windows;
procedure PatchCode(Address: Pointer; const NewCode; Size: Integer);
var
OldProtect: DWORD;
begin
if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
begin
Move(NewCode, Address^, Size);
FlushInstructionCache(GetCurrentProcess, Address, Size);
VirtualProtect(Address, Size, OldProtect, @OldProtect);
end;
end;
type
PInstruction = ^TInstruction;
TInstruction = packed record
Opcode: Byte;
Offset: Integer;
end;
procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
NewCode: TInstruction;
begin
NewCode.Opcode := $E9;//jump relative
NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;
function System_AfterConstruction: Pointer;
asm
MOV EAX, offset System.@AfterConstruction
end;
function System_BeforeDestruction: Pointer;
asm
MOV EAX, offset System.@BeforeDestruction
end;
var
_BeforeDestruction: procedure(const Instance: TObject; OuterMost: ShortInt);
function _AfterConstruction(const Instance: TObject): TObject;
begin
try
Instance.AfterConstruction;
Result := Instance;
if Assigned(OnAfterConstruction) then
OnAfterConstruction(Instance);
except
_BeforeDestruction(Instance, 1);
raise;
end;
end;
initialization
@_BeforeDestruction := System_BeforeDestruction;
RedirectProcedure(System_AfterConstruction, @_AfterConstruction);
end.
将处理程序分配给OnAfterConstruction,并且每当创建对象时都会调用该处理程序。
我将其作为练习留给读者添加OnBeforeDestruction 事件处理程序。
请注意,我并不是说这种方法是一件好事。我只是回答你问的直接问题。您可以自己决定是否要使用它。我知道我不会这样做!