Set HOOK to local method

I'm creating a component, that must process parent's messages. I would like to use hooks, but I don't know, how to set hook to local (component's) method ...

function Mycomponent.MessageHookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): lResult stdcall;

constructor Mycomponent.create(AOwner : TComponent);

SetWindowsHookEx(WH_CallWndProc, MessageHookProc, 0, GetCurrentThreadId);


Global method is not a solution, since the method is only one and I will have more than one instances on different forms. Any Hint ? thanx
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

rpoConnect With a Mentor Commented:
You can use following unit to make posiible to set a method as a hook function.

example :
TForm1 : class(TForm)
  HookProc : pointer;
  ThisHook : Handle;

procedure TForm1.MyHook (var HookCall: THookCall);
....{the hook comes here}

procedure TForm1.SetHook;
  HookProc := MakeHookInstance (MyHook);
  ThisHook := SetWindowsHookEx (WH_CALLWNDPROC,

procedure TForm1.UnsetHook;
-------- end of example ---------

-- the unit containinig MakeHookInstance and FreeHookInstance --
 //                        HOOK METHOD INSTANCE
 // These few lines of code implement for windows hooks what MakeObjectInstance
 // and FreeObjectInstance do for windows message functions.  They allow a method
 // to be written and passed into the SetWindowsHookEx API function rather than a
 // stand alone function which cannot directly access variables or methods.
 // An example of use is in the IDE Peek expert.
 // The code is based entirely on the MakeObjectInstance and FreeObjectInstance
 // in the Delphi Forms unit.  In fact my only input has been to change a few
 // names and make it work for Hook calls rather than Message calls.  So I don't
 // claim a lot.  Borland's ownership of this code is recognised and I hope
 // noone there minds my borrowing it and bodging it for this purpose!
 // This way of writing a hook function is a bit wasteful of memory for what you
 // are doing (but hell, what's 4KB nowadays!, this isn't a Z80 and CPM).
 // Only tested under Delphi 3.02
 // Version 1.00 5-2-98 Grahame Marsh
 // Freeware - you get it for free, I take nothing, I make no promises!
 // Please feel free to contact me:




   THookCall = packed record
     Code   : integer;
     WParam : WPARAM;
     LParam : LPARAM;
     Result : LResult

   THookMethod = procedure (var HookCall: THookCall) of object;

 function  MakeHookInstance (Method: THookMethod): pointer;
 procedure FreeHookInstance (ObjectInstance: pointer);


   InstanceCount = 313;  // set so that sizeof (TInstanceBlock) < PageSize

   PObjectInstance = ^TObjectInstance;
   TObjectInstance = packed record
     Code: Byte;
     Offset: Integer;
     case Integer of
       0: (Next: PObjectInstance);
       1: (Method: THookMethod);

   PInstanceBlock = ^TInstanceBlock;
   TInstanceBlock = packed record
     Next: PInstanceBlock;
     Code: array[1..2] of Byte;
     WndProcPtr: Pointer;
     Instances: array[0..InstanceCount] of TObjectInstance;

   InstBlockList : PInstanceBlock  = nil;
   InstFreeList  : PObjectInstance = nil;

 function StdHookProc (Code, WParam: WPARAM; LParam: LPARAM): LResult; stdcall; assembler;
         XOR     EAX,EAX
         PUSH    EAX
         PUSH    LParam
         PUSH    WParam
         PUSH    Code
         MOV     EDX,ESP
         MOV     EAX,[ECX].Longint[4]
         CALL    [ECX].Pointer
         ADD     ESP,12
         POP     EAX

 { Allocate a hook method instance }

 function CalcJmpOffset(Src, Dest: Pointer): Longint;
   Result := Longint(Dest) - (Longint(Src) + 5);

 function MakeHookInstance(Method: THookMethod): Pointer;
   BlockCode: array [1..2] of Byte = ($59, $E9);
   PageSize = 4096;
   Block: PInstanceBlock;
   Instance: PObjectInstance;
   if InstFreeList = nil then
     Block := VirtualAlloc (nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     Block^.Next := InstBlockList;
     Move(BlockCode, Block^.Code, SizeOf(BlockCode));
     Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdHookProc));
     Instance := @Block^.Instances;
       Instance^.Code := $E8;
       Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);
       Instance^.Next := InstFreeList;
       InstFreeList := Instance;
       Inc(Longint(Instance), SizeOf(TObjectInstance));
     until Longint(Instance) - Longint(Block) >= SizeOf(TInstanceBlock);
     InstBlockList := Block
   Result := InstFreeList;
   Instance := InstFreeList;
   InstFreeList := Instance^.Next;
   Instance^.Method := Method

 { Free a hook method instance }

 procedure FreeHookInstance (ObjectInstance: Pointer);
   if ObjectInstance <> nil then
     PObjectInstance(ObjectInstance)^.Next := InstFreeList;
     InstFreeList := ObjectInstance


Credits to Grahame Marsh for providing the solution.

These functions chacked and they work fine.

AleqAuthor Commented:
Or else - I need to catch form's events from my component which user puts on this form.
When you say events, do you mean windows messages, or things like OnClick etc...


AleqAuthor Commented:
Wow ! It looks very promising.
I'll try it ASAP
AleqAuthor Commented:
Wow ! It looks very promising.
I'll try it ASAP
All Courses

From novice to tech pro — start learning today.