我想找到一种方法来了解表单是在运行时创建的(或销毁的)。 这适用于Delphi或fpc。 非常感谢
PS:有没有办法检索所有对象的信息?
答案 0 :(得分:5)
我希望有一个事件告诉我一个新对象刚刚在运行时创建(或被破坏)。
创建或销毁对象时,不会触发内置事件。
因为我喜欢编写代码钩子,所以我提供以下单元。这会挂钩_AfterConstruction
单元中的System
方法。理想情况下它应该使用蹦床但我从未学会如何实施这些。如果您使用了真正的挂钩库,那么您可以做得更好。无论如何,这是:
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
事件处理程序。
请注意,我并不是说这种做法是件好事。我只是回答你提出的直接问题。您可以自己决定是否要使用它。我知道我不会这样做!
答案 1 :(得分:0)
使用TForm
的{{1}}事件以您想要的任何方式通知您。
答案 2 :(得分:0)
在MS Windows中,您可以使用以下小模板挂钩流程事件:
{$mode objfpc}{$H+}
uses
Windows, JwaWinUser;
function ShellProc(nCode: longint; wParam: WPARAM; lParam: LPARAM): longint; stdcall;
var
wnd: HWND;
begin
Result := 0;
case nCode of
HSHELL_WINDOWCREATED:
begin
wnd := wParam;
// Check window
// Get task handle
// Get window icon
// Add task to the list
// Call event
end;
HSHELL_WINDOWDESTROYED:
begin
wnd := wParam;
// Check window
// Get task handle
// Get window icon
// Remove task to the list
// Call event
end;
HSHELL_LANGUAGE:
begin
// Get language
// Call event
end;
HSHELL_REDRAW:
begin
// Call event
end;
HSHELL_WINDOWACTIVATED:
begin
// Get language
// Call event
end;
//HSHELL_APPCOMMAND:
//begin
// { TODO 1 -ond -csys : Specify return value for this code }
// Result := -1;
//end;
end;
// Call next hook in the chain
Result := CallNextHookEx(
0,
nCode,
wParam,
lParam);
end;
var
FCallbackProc: HOOKPROC;
function InitShellHook(AProc: HOOKPROC): HHOOK; stdcall; export;
begin
FCallbackProc := AProc;
Result := SetWindowsHookEx(WH_SHELL, @ShellProc, 0, 0);
end;
procedure DoneShellHook(AHook: HHOOK); stdcall; export;
begin
UnhookWindowsHookEx(AHook);
end;
HSHELL_WINDOWCREATED将通知您,您的流程是创建新窗口。
使用您的程序地址致电InitShellHook
(请参阅HOOCPROC
声明)。