| Store | Cart

Re: Calling SetWindowsHookEx()?

From: Veli-Pekka Tätilä <vtat...@mail.student.oulu.fi>
Tue, 20 Jun 2006 19:33:56 +0300
Lyle Kopnicky wrote:
> It appears the code only needs to be in a DLL if you want to create a> system level hook. I only need a thread level hook.
Correct, to my knowledge at least. I wass thinking of system wide hooks 
mainly and failed to point that out. So I suppose your Perl solution should 
work.

> Listed below is what I have so far. It waits for a few seconds, then > quits. <code relocated>
OK I took a quick glance at it and a couple of more or less trivial 
questions and observations came to mind.

The MSDN docs state specifically that if the hook code is negative, no 
processing should be done except to pass on the parameters to CallNextHookX 
and return its return value. I suppose it doesn't really matter here but 
that's one minor detail of the "hook contract", which your testing code 
violates.

Also the question of how to get the HINSTANCE and ThreadId parameters using 
Perl has been bothering me, too. Are you sure that the GetCurrentThreadId 
function you import from kernel32 does get the same thread in which your 
application actually runs? I suppose Perl might be multi-threaded, am not 
certain about this, though, or some of the TK or Win32 stuff might have some 
event handling threads. I know next to nothing about how those modules are 
implemented, these are just wild guesses. I do know Java has multiple 
threads running starting from the garbage collector, which caused me to 
extrapolate here.

Finally, where did you get the magic number for the low-level keyboard hook? 
Are you sure its correct? Silly question, I know, but sometimes silly things 
do happen (like mistyping JDBC as JBDC and wondering why things don't work). 
My oldish MSDN collection says, by the way, that low-level keybord hooks are 
only supported in NT. You aren't running Win 9X by any chance, are you?

> If I change the return type of SetWindowsHookEx from 'P' to 'N', my> main window will open, but I still don't get any calls to KeyboardHook.
Umm, the fact that changing the prototype affects program behavior here 
might be a sign of a wrong prototype. I've only imported very basic 
functions with Win32::API so far, so I cannot be of much help with Perlish 
callbacks to Win32 functions, I'm afraid.

Your code:
use warnings;
use strict;
use Tk;
use Win32::API;
use Win32::API::Callback;

my $WH_KEYBOARD_LL = 13;

my $GetCurrentThreadId
   = new Win32::API('kernel32', 'GetCurrentThreadId', '', 'N');
my $SetWindowsHookEx =
   new Win32::API('user32', 'SetWindowsHookEx', 'NKPP', 'P');
Win32::API->Import('user32', 'HHOOK SetWindowsHookEx(int idHook,
HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId)');
my $CallNextHookEx =
   new Win32::API('user32', 'CallNextHookEx', 'PNNN', 'N');

sub KeyboardHook($$$) {
   my ($nCode, $wParam, $lParam) = @_;

   print "nCode=$nCode, wParam=$wParam, lParam=$lParam\n";
   $CallNextHookEx->Call(0, $nCode, $wParam, $lParam);
}

my $KeyboardHookCallback =
   new Win32::API::Callback(\&KeyboardHook, 'NNP', 'N');
my $ThreadId = $GetCurrentThreadId->Call();
my $Hook = $SetWindowsHookEx->Call($WH_KEYBOARD_LL, $KeyboardHookCallback,
   0, $ThreadId);

my $win = MainWindow->new();
MainLoop();
End code.

-- 
With kind regards Veli-Pekka Tätilä (vtat...@mail.student.oulu.fi)
Accessibility, game music, synthesizers and programming:
http://www.student.oulu.fi/~vtatila/ 

Recent Messages in this Thread
Lyle Kopnicky Jun 16, 2006 10:40 pm
Veli-Pekka Tätilä Jun 18, 2006 11:46 am
Lyle Kopnicky Jun 19, 2006 06:21 pm
Veli-Pekka Tätilä Jun 20, 2006 04:33 pm
Messages in this thread