In sub WindowProc, you need to unpack $lParam, which is a pointer to a struct of type MSG.
You then need to check the message field in MSG to see if the message is of type WM_HOTKEY.

Here are the minimum changes to make your code work.
Add this to your constant section:

use constant WM_HOTKEY => 0x0312;
Add this to the middle of sub WindowProc:
my ($hwnd, $message, $msg_wParam, $msg_lParam, $time, $pt) = unpack 'L L L l L L ', unpack( 'P24', pack('L', $lParam) ); if ( $message == WM_HOTKEY ) { print "**************************\n"; }

These are some thoughts I had during my research of this problem:

  1. use Tk; is not needed in your example code.
  2. Sub KeyboardHook, and all of the code to hook it to the WH_KEYBOARD message, can be removed.
  3. If you read 'When to use Prototypes?', I think you will want to remove the ($$$) from your subs.
  4. According to this MSDN article, you should unregister your hotkey before exiting your program.
  5. You don't have to cheat and use $mw_win32->{-handle}; you can get the window handle with GetActiveWindow() as long as it is run *after* Show().
  6. The MSG structure could be decoded using Win32::API::Struct, but WindowProc gets called for *all* the window's messages and needs to perform quickly, so manual unpacking seems best.
  7. Your WindowProc() is a callback function of type GetMsgProc. The MSDN page on GetMsgProc seems to say that parameters $nCode and $wParam, along with the return value, should be considered (by comparing with HC_* and PM_* constants) to determine whether to call CallNextHookEx or not. You are not doing so, but your code is working, and the MS docs are very unclear to me, so I can't recommend a more "correct" solution. If the program gets twitchy under a heavy load, this is a good place to start looking for the problem.

Refactored, working, tested code:

use strict; use warnings; use Win32::GUI; use Win32::API; use Win32::API::Callback; # From PlatformSDK/Include/WinUser.h use constant MOD_CONTROL => 2; use constant KEY_A => ord('A'); use constant MY_HOTKEY_ID => 99; use constant { # Codes for SetWindowHook WH_GETMESSAGE => 3, # Window Messages WM_HOTKEY => 0x0312, ### # Hook Codes ### HC_ACTION => 0, ### HC_GETNEXT => 1, ### HC_SKIP => 2, ### HC_NOREMOVE => 3, ### HC_SYSMODALON => 4, ### HC_SYSMODALOFF => 5, ### ### # PeekMessage() Options ### PM_NOREMOVE => 0x0000, ### PM_REMOVE => 0x0001, ### PM_NOYIELD => 0x0002, }; sub WindowProc { my ( $nCode, $wParam, $lParam ) = @_; # See http://msdn.microsoft.com/library/en-us/winui/winui/windowsu +serinterface/windowing/messagesandmessagequeues/messagesandmessageque +uesreference/messageandmessagequeuestructures/msg.asp # typedef struct { # HWND hwnd; # UINT message; # WPARAM wParam; # Unsigned # LPARAM lParam; # Signed # DWORD time; # POINT pt; # } MSG, *PMSG; my ( $msg_hwnd, $msg_message, $msg_wParam, $msg_lParam, $msg_time, + $msg_pt ) = unpack 'L L L l L L ', unpack( 'P24', pack('L', $lParam) ); if ( $msg_message == WM_HOTKEY ) { print "**************************\n"; } CallNextHookEx( 0, $nCode, $wParam, $lParam ); } my $WinProc = Win32::API::Callback->new( \&WindowProc, 'NNN', 'N' ); Win32::API->Import( kernel32 => GetCurrentThreadId => '', 'N' ) or + die; Win32::API->Import( user32 => SetWindowsHookEx => 'NKNN', 'N' ) or + die; Win32::API->Import( user32 => CallNextHookEx => 'PNNN', 'N' ) or + die; Win32::API->Import( user32 => RegisterHotKey => 'NNNN', 'N' ) or + die; Win32::API->Import( user32 => UnregisterHotKey => 'NN', 'N' ) or + die; my $ThreadId = GetCurrentThreadId() or die; SetWindowsHookEx( WH_GETMESSAGE, $WinProc, 0, $ThreadId ) or die $^E; my $mw_win32 = Win32::GUI::Window->new( -name => 'MainWindow', -title => 'This is a test!', -width => 100, -height => 100, ); $mw_win32->Show(); my $mw_handle = $mw_win32->GetActiveWindow(); RegisterHotKey( $mw_handle, MY_HOTKEY_ID, MOD_CONTROL, KEY_A ) or die +$^E; Win32::GUI::Dialog(); UnregisterHotKey( $mw_handle, MY_HOTKEY_ID ) or die $^E;


In reply to Re: Continueing the Quest to get RegisterHotKey to work! by Util
in thread Continueing the Quest to get RegisterHotKey to work! by eric256

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.