On 11/07/07, Robert May <[EMAIL PROTECTED]> wrote:
On 11/07/07, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:
> I have a small program which can be minimized to the tray.
> Now I want to have an accelerator which fires to minimize the program to the
> tray => this works fine.
> But now I want to restore the window with an accelerator anytime.
> It should work if I'm writing a text or in internet explorer or firefox ... 
everytime.
> is this possible?
> how can I install the accelerator so that it can be activated?

I'll attach some code that shows the WM_SETHOTKEY method to this mail
- it doesn't quite meet your requirements, but it's close and can be
done with Win32::GUI alone.  I'll follow-up with code that uses the
Win32 RegisterHotKey() function - I think it exactly meets what you
want to do, but needs Win32::API() to call the functions that are
missing from Win32::GUI.

This is the follow-up using RegisterHotKey() and WM_HOTKEY.  It's a
bit more complex than the last example:

#!perl -w
use strict;
use warnings;

# What this script does:
# Creates a Window, and a notify icon.
# Register a Hotkey (Ctrl-A) for the window.
# When the window is minimised, it is hidden.
# Left-clicking on the notify icon, or pressing the
# Hotkey combination will Show the window again.
# Pressing the HotKey when the window is visible
# hides it.

# We can't use WM_SETHOTKEY, as we never see any WM_SYSCOMMAND
# once the window is hidden, so we use Win32::API to give
# us access to RegisterHotKey/UnregisterHotKey and catch
# the WM_HOTKEY messages to o our bidding.

use Win32::API();
Win32::API->Import('user32', 'RegisterHotKey', 'LiII', 'I');
Win32::API->Import('user32', 'UnregisterHotKey', 'Li', 'I');

use Win32::GUI 1.05 qw( CW_USEDEFAULT
                       WM_HOTKEY
                       VK_A
                       IDI_DEFAULTICON );

# Some constants missing from Win32::GUI::Constants
sub MOD_ALT()     {0x001} # Alt key
sub MOD_CONTROL() {0x002} # Ctrl key
sub MOD_SHIFT()   {0x004} # Shift key
sub MOD_WIN()     {0x008} # Windows key

my $HOTKEY_ID = 0x1234; # Any unique number for this app - need
                       # a different number for each hotkey

my $mw = Win32::GUI::Window->new(
   -title => 'HotKey demonstration',
   -left  => CW_USEDEFAULT,
        -size  => [400,300],
   -onMinimize => \&toggle_show_state,
);

# We need to catch WM_HOTKEY messages
$mw->Hook(WM_HOTKEY, \&handle_wm_hotkey);

my $icon = Win32::GUI::Icon->new(IDI_DEFAULTICON);

$mw->AddNotifyIcon(
   -icon => $icon,
   -onClick => \&toggle_show_state,
);

set_hotkey($mw, $HOTKEY_ID, VK_A, MOD_CONTROL);

$mw->Show();
Win32::GUI::Dialog();

# Before we exit we must remove the hotkey, else it won't be available
# for other apps, and we'll leak system memory
# Using and END block to that this get called, even if we exit other
# than by falling off the end here.
END { unset_hotkey($mw, $HOTKEY_ID); }

sub toggle_show_state {
   my ($win) = @_;

   # Less obviously written as:
   # $win->Show(!$win->IsVisible());
   if($win->IsVisible()) {
       $win->Hide();
   }
   else {
       $win->Show();
   }

   return 0;
}

# Set the hotkey for a window (or replace it if this is called
# more than once)
sub set_hotkey {
   my ($win, $id, $key, $modifiers) = @_;
   # $win - any top level window
   # $id  - unique identifier for the hotkey
   # $key - any virtual keycode (VK_*) except F12 (and others??)
   # $modifiers - any combination of the MOD_* constants (or 0 for no modifier)

   if(!RegisterHotKey($win->{-handle}, $id, $modifiers, $key)) {
       die("set_hotkey() failed to register the hotkey - $^E");
   }

   return;
}

sub unset_hotkey {
   my ($win, $id) = @_;
   # $win - any top level window
   # $id  - unique identifier for the hotkey

   if(!UnregisterHotKey($win->{-handle}, $id)) {
       die("unset_hotkey() failed to unregister the hotkey - $^E");
   }

   return;
}

sub handle_wm_hotkey {
   my ($win, $id, $lparam, $type, $msgcode) = @_;
   return unless $type == 0;
   return unless $msgcode == WM_HOTKEY;

   # decode virtual key and modifiers from lparam:
   # my ($modifiers, $key) = unpack("SS", pack("L", $lparam));
   # my $mod = '';
   # $mod .= "A" if($modifiers & MOD_ALT);
   # $mod .= "C" if($modifiers & MOD_CONTROL);
   # $mod .= "S" if($modifiers & MOD_SHIFT);
   # $mod .= "W" if($modifiers & MOD_WIN);
   # print "Saw WM_HOTKEY with id: $id (vkey: $key, mod: $mod)\n";

   # should really check ID to determine what to do, but we can get
   # away without that, as we only have one hotkey
   toggle_show_state($win);

   return;
}

Reply via email to