Solved

Passing a callback pointer within a class = Exception ?

Posted on 2012-03-21
1
476 Views
Last Modified: 2016-09-29
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
Comment
Question by:rotem156
1 Comment
 
LVL 19

Accepted Solution

by:
Thommy earned 500 total points
ID: 37751573
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

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Printing problem 2 79
Downloading email attachments 2 66
Moving (cutting/pasting) controls in a TTabbedNotebook... 7 27
CheckListBox usage 3 48
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.
A company’s greatest vulnerability is their email. CEO fraud, ransomware and spear phishing attacks are the no1 threat to a company’s security. Cybercrime is responsible for the largest loss of money to companies today with losses projected to r…

943 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

4 Experts available now in Live!

Get 1:1 Help Now