p1ato has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to use the Win32::GUI module to handle popup menus with a system tray icon. The problem is that when I give the menu items callbacks to execute when clicked, the callbacks don't execute until TrackPopupMenu is called a second time. I don't understand why this is happening. Here is a simple example:
use Win32::GUI (); my $window = Win32::GUI::Window->new(); my $menu = Win32::GUI::Menu->new(-name => "TestMenu"); $menu->{"TestMenu"}->AddMenuItem( -item => 0, -id => 14, -text => "Exit", -name => "randomName", -onClick => sub { exit; }, ); #$window->SetForegroundWindow(); $window->TrackPopupMenu($menu->{"TestMenu"}, 20, 20); #$window->PostMessage("Msg", 0, 0); #$window->TrackPopupMenu(Win32::GUI::Menu->new(-name => "dummyMenu"), +20, 20); while (1) { sleep(1); }
Notice that while the second TrackPopupMenu call is commented, the subroutine for the menu is not called. Uncomment the second call to $window->TrackPopupMenu(...) to see how the second call will trigger the subroutine that should have executed immediately after the first call. Adding in SetForegroundWindow/PostMessage doesn't help. If someone knows how to make the subroutine get called without a second call to TrackPopupMenu I would appreciate it. Thanks!

Replies are listed 'Best First'.
Re: TrackPopupMenu delay
by Anonymous Monk on Aug 19, 2008 at 04:34 UTC
      That is what I am doing (except I am using "-onClick => $callback, -onRightClick => $callback2" in "$window->AddNotifyIcon(...);" instead of using Name_Event). The example I gave was just simplified to show the problem and nothing else. When I use TrackPopupMenu in either case, the menu callback doesn't execute until TrackPopupMenu is called a second time, as illustrated by the simplified example.
        Hello, I got this to work by creating the menu outside of the subroutine, then calling the menu inside of the subroutine. Here's what I mean: use Win32::GUI (); ... my $menu = Win32::GUI::Menu->new(-name => "TestMenu"); $menu->{"TestMenu"}->AddMenuItem( -item => 0, -id => 14, -text => "Exit", -onClick => sub { $win->Hide(); undef $win; exit(0); }, ); sub Tray_RightClick { $win->TrackPopupMenu($menu->{"TestMenu"}, Win32::GUI::GetCursorPos()); return 1; } ... Hope this helps you... ~Morpheous1129
Re: TrackPopupMenu delay
by Anonymous Monk on Aug 19, 2008 at 04:52 UTC
    Hi ! I found nothing (sorry ...) For information, even a simple "$window->TrackPopupMenu();" , with nothing more, after the complete one make it work ! If it can help ... Didess
      Using '$window->TrackPopupMenu();' with no arguments causes an error.
Re: TrackPopupMenu delay
by Anonymous Monk on Oct 08, 2008 at 15:56 UTC
    Hello,
    
    I got this to work by creating the menu outside of the subroutine, then calling the menu inside of the subroutine.  Here's what I mean:
    
    use Win32::GUI();
    
    ...
    
    my $menu = Win32::GUI::Menu->new(-name => "TestMenu");
    $menu->{"TestMenu"}->AddMenuItem(
         -item => 0,
         -id => 14,
         -text => "Exit",
         -onClick => sub { $win->Hide(); undef $win; exit(0); },
    );
    
    sub Tray_RightClick {
      $win->TrackPopupMenu($menu->{"TestMenu"}, Win32::GUI::GetCursorPos());
      return 1;
    }
    
    ...
    
    
    Hope this helps you...
    
    P.S.: Sorry about the re-post, I didn't know realize I could format with HTML tags.
    
    ~Morpheous1129