• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 549
  • Last Modified:

Passing a callback pointer within a class = Exception ?

Hi, i'm using SetWindowsHookEx and i have placed my hook proc under private declaration within my hook class...

when ever i call it like this

SetWindowHookEx( @THookClass.HookProc ) it grants an exception @ run time, why ?

placing it outside the form works well...

unit uHook;

interface

uses
  Windows,
  dialogs,
  Classes,
  Messages;

type
  THookClass = class(TObject)
    private
      TempBuf: string;

      function LLKeybdProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT stdcall;
    public
      property FinalBuf: string read TempBuf;

      procedure Stop;
      constructor Create;
  end;

var
  HookClass: THookClass;

  HookBuf: TStringList; // holds captured keys
  keybdHook: HHOOK; // hook handle

implementation

// converts h/w scan code to key name
Function VKtoStr(AScanCode: Cardinal): String;
var
  Buffer: array [0..255] of Char;
begin
  Result := '';

  if (AScanCode <> 0) then
  begin
    GetKeyNameText(AScanCode shl 16, Buffer, SizeOf(Buffer));
    Result := Buffer;
  end;
end;

function THookClass.LLKeybdProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT stdcall;
type
  PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT;
  TKBDLLHOOKSTRUCT = packed record
    vkCode: DWORD;
    scanCode: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;
var
  pkbhs: PKBDLLHOOKSTRUCT;
begin
  Result := CallNextHookEx(keybdHook, nCode, wParam, lParam);

  if (nCode < 0) then // do not process message
    exit;

  pkbhs := PKBDLLHOOKSTRUCT(lParam);

  case wParam of
    WM_KEYUP:
    case pkbhs^.scanCode of
      $39: HookBuf.Append(' '); // Spacebar (VK_BACK)
      else
        HookBuf.Append(VKtoStr(pkbhs^.scanCode));
    end;
  end;
end;

procedure THookClass.Stop;
begin
  if (keybdHook <> INVALID_HANDLE_VALUE) then
    UnhookWindowsHookEx(keybdHook);

  if (HookBuf.Count > 0) then
    TempBuf := HookBuf.Text;

  if (HookBuf <> nil) then
    HookBuf.Free;
end;

constructor THookClass.Create;
begin
  inherited;

  HookBuf := TStringList.Create;
  HookBuf.LineBreak := '';

  keybdHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LLKeybdProc, 0, 0);
end;

end.

Open in new window

0
rotem156
Asked:
rotem156
1 Solution
 
ThommyCommented:
Check, if this helps you:

Let's say you want a WH_CALLWNDPROC hook in a class. You define your hook function, a pointer variable (that will be a
pointer to the method) and a hook handle (so you can correctly chain the hook events):

     type
       TMyClass = class (TWhat)
     ....
       private
         ThisHook : hHook;
         HookProc : pointer;
     ....
        function MyHookProc (var HookCall: THookCall);
     ....
       end;

And in the class constructor, you create a pointer to the class method and set the hook running with a call to the API:

       HookProc := MakeHookInstance (MyHookProc);
       ThisHook := SetWindowsHookEx (WH_CALLWNDPROC, HookProc, HInstance, GetCurrentThreadID);

And next you must define your hook function, which is now a method:

     function TMyClass.MyHookProc (var HookCall: THookCall);
     begin
     ....
       with HookCall do
         Result := CallNextHookEx (ThisHook, Code, wParam, lParam);
     ....
     end;

Finally, in the destructor, you clean up:

       UnhookWindowsHookEx (ThisHook);
       FreeHookInstance (HookProc);

So, in conclusion...

No global variables! No stand alone hook function! The hook function can easily reference the class methods!

Open in new window

Above description is extracted from http://www.fortunecity.com/skyscraper/linux/1344/dc000015.html
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now