Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know that a form was created?

I want to find a way to know that a form was created at run time (or destroyed). This for Delphi or fpc. Many thanks

PS : Is there a way to retrieve that info for all objects ?

like image 982
user2418856 Avatar asked Oct 19 '25 01:10

user2418856


1 Answers

I want to have a event that tells me that a new object was just created at run time (or destroyed).

There are no built in events that fire whenever an object is created or destroyed.

Because I like writing code hooks, I offer the following unit. This hooks the _AfterConstruction method in the System unit. Ideally it should use a trampoline but I've never learnt how to implement those. If you used a real hooking library you'd be able to do it better. Anyway, here it is:

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.

Assign a handler to OnAfterConstruction and that handler will be called whenever an object is created.

I leave it as an exercise to the reader to add an OnBeforeDestruction event handler.

Note that I am not saying that such an approach is a good thing to do. I'm just answering the direct question that you asked. You can decide for yourself whether or not you want to use this. I know I would not do so!

like image 156
David Heffernan Avatar answered Oct 22 '25 05:10

David Heffernan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!