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:
is what it causing problems.
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:
to register a constant for the PostMessage call.
Any ideas, I've been trying to resolve this for a while and can't figure out what I have been doing wrong.
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);
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');
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.