Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Post Message posts two messages???

Status
Not open for further replies.

AP81

Programmer
Apr 11, 2003
740
0
0
AU
Hi Guys,

I have made a DLL (global keyhook) which uses PostMessage to post a message back to my main program.

This is all working fine, however for some reason PostMessage posts four messages ( 2 x key up, 2 x key down) for every complete key press, however there should only be two messages 1x key up, 1x key down from every complete key press.

Below is the dll unit. It is very simple. The line:
Code:
        PostMessage(HWND_BROADCAST,HookMsg,wParam,lParam);
is what it causing problems.

Code:
library keyhook;

uses
  SysUtils, windows, messages;

var
  CurrentHook: HHook;
  HookMsg: cardinal;

function GlobalKeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
begin
  result := 0;
  if (code < 0) then
    begin
       { if code is <0 your keyboard hook should always run CallNextHookEx and then return the value from it.}
      result:=CallNextHookEx(CurrentHook,code,wParam,lparam);
    end
  else
    begin
      if (code = HC_ACTION) then
        PostMessage(HWND_BROADCAST,HookMsg,wParam,lParam);  { post the wParam and lParam keys }
    end;
end;


procedure SetHookHandle(HookHandle: HHook); stdcall;
begin
  CurrentHook := HookHandle;
end;

exports
  GlobalKeyBoardHook, // index 1,
  SetHookHandle;      // index 2;

begin
  HookMsg := RegisterWindowMessage('keyhookdll_hookmsg');
end.


Here is the code segment from the main application which is using the keyhook (for reference), however the problem is with PostMessage in the DLL.
Note that both the dll and the application use:
Code:
   HookMsg := RegisterWindowMessage('keyhookdll_hookmsg');
to register a constant for the PostMessage call.

Code:
// this is the SetHookHandle procedure in the dll.
type
  TInitializeHook = procedure(HookHandle: HHook); stdcall;
  
type
  TfrmMain = class(TForm)
  ...
  ...
  	procedure InitialiseDLL;
  private
    { Private declarations }
    procedure DLLMessage(var Msg: TMsg; var Handled: Boolean);                      // this the is the message returned from keyhook.dll containing the keycode/scancodes
  public
    { Public declarations }
    LibHandle: HModule;                                                             // keyhook.dll handle
    HookProcAddress: pointer;                                                       // memory address of hook procedure in windows
    InitializeHook: TInitializeHook;                                                // address of the initial call procedure
  end;


var
  HookMsg: cardinal;
  
(* ------------------------------------------------------------------------------
procedure : InitialiseDLL
Purpose   : This initialises the keyhook.dll
------------------------------------------------------------------------------ *)
procedure TfrmMain.InitialiseDLL;
var
  currenthook :integer;
begin
  Application.OnMessage := DllMessage;

  {To install a global keyboard hook,
   1. Load the DLL containing the hook procedure.
   2. Get the addresses of the initial procedure to be called to initialise
      the hook and the procedure to be called when a key is pressed.
   3. Call "SetWindowsHookEx" specifying "WH_KEYBOARD" as the hook type and the
      addresses obtained in step 2.  Set "threadid" to 0 to indicate a global hook.
   4. Call the hook initialisation procedure.
  }
  {1}
   LibHandle:=LoadLibrary('keyhook.dll');
   if LibHandle=0 then
   begin  {if loading fails, exit and return false}
     showmessage('Failed to load ''keyhook.dll''');
     halt;
   end;
   {2}
   HookProcAddress  :=  GetProcAddress(LibHandle, pchar('GlobalKeyBoardHook'));
   InitializeHook   :=  GetProcAddress(LibHandle,pchar('SetHookHandle'));       

   if (HookProcAddress=nil)or(addr(InitializeHook)=nil) then
   begin  {if loading fails, unload library, exit and return false}
     showmessage('Hook procedure addresses could not be obtained, halted');
     halt;
   end;
   {3}
   CurrentHook:=SetWindowsHookEx(WH_KEYBOARD,HookProcAddress,LibHandle,0);
   {4}
   InitializeHook(CurrentHook);
end;  


(* ------------------------------------------------------------------------------
procedure : DLLMessage
Purpose   : Process the keys pressed
------------------------------------------------------------------------------ *)
procedure TfrmMain.DLLMessage(var Msg: TMsg; var Handled: Boolean);
var
  AKeyStates: TKeyStates;
  //vk_code: word;
  scan_code: longword;
begin

  if Msg.message = HookMsg then
    begin
    	...
    end;
end;


// register the keyhook.dll 'keyhookdll_hookmsg' message so this unit can listen
// for any messages that come from keyhook.dll
initialization
   HookMsg := RegisterWindowMessage('keyhookdll_hookmsg');


Any ideas, I've been trying to resolve this for a while and can't figure out what I have been doing wrong.
 
I managed to get this working using a FileMap and posting a message to the file map.

Seeing as I spent so much time perfecting this, I might make a FAQ for a system-wide keyhook.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top