You can subscribe to this list here.
2001 |
Jan
(226) |
Feb
(139) |
Mar
(156) |
Apr
(95) |
May
(181) |
Jun
(166) |
Jul
(80) |
Aug
(59) |
Sep
(69) |
Oct
(83) |
Nov
(142) |
Dec
(33) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(42) |
Feb
(91) |
Mar
(76) |
Apr
(113) |
May
(67) |
Jun
(68) |
Jul
(37) |
Aug
(41) |
Sep
(16) |
Oct
(135) |
Nov
(51) |
Dec
(21) |
2003 |
Jan
(37) |
Feb
(36) |
Mar
(37) |
Apr
(103) |
May
(68) |
Jun
(70) |
Jul
(77) |
Aug
(12) |
Sep
(9) |
Oct
(53) |
Nov
(88) |
Dec
(63) |
2004 |
Jan
(263) |
Feb
(106) |
Mar
(36) |
Apr
(21) |
May
(21) |
Jun
(34) |
Jul
(33) |
Aug
(34) |
Sep
(35) |
Oct
(21) |
Nov
(43) |
Dec
(63) |
2005 |
Jan
(28) |
Feb
(42) |
Mar
(29) |
Apr
(14) |
May
(41) |
Jun
(20) |
Jul
(65) |
Aug
(136) |
Sep
(41) |
Oct
(74) |
Nov
(34) |
Dec
(94) |
2006 |
Jan
(85) |
Feb
(94) |
Mar
(68) |
Apr
(103) |
May
(66) |
Jun
(51) |
Jul
(24) |
Aug
(56) |
Sep
(57) |
Oct
(85) |
Nov
(73) |
Dec
(68) |
2007 |
Jan
(59) |
Feb
(32) |
Mar
(13) |
Apr
(32) |
May
(36) |
Jun
(36) |
Jul
(64) |
Aug
(35) |
Sep
(19) |
Oct
(10) |
Nov
(13) |
Dec
(20) |
2008 |
Jan
(26) |
Feb
(41) |
Mar
(19) |
Apr
(24) |
May
(16) |
Jun
(33) |
Jul
(34) |
Aug
(4) |
Sep
(11) |
Oct
|
Nov
(26) |
Dec
(23) |
2009 |
Jan
(5) |
Feb
(2) |
Mar
(21) |
Apr
(16) |
May
(13) |
Jun
(6) |
Jul
(34) |
Aug
(2) |
Sep
(1) |
Oct
(7) |
Nov
(5) |
Dec
(24) |
2010 |
Jan
(3) |
Feb
(5) |
Mar
(6) |
Apr
(6) |
May
(14) |
Jun
(6) |
Jul
(1) |
Aug
(12) |
Sep
(10) |
Oct
(9) |
Nov
|
Dec
(2) |
2011 |
Jan
(4) |
Feb
(5) |
Mar
(30) |
Apr
(1) |
May
(2) |
Jun
(5) |
Jul
(3) |
Aug
(2) |
Sep
(3) |
Oct
|
Nov
(6) |
Dec
|
2012 |
Jan
|
Feb
(10) |
Mar
|
Apr
|
May
(1) |
Jun
(3) |
Jul
(1) |
Aug
|
Sep
(2) |
Oct
|
Nov
(2) |
Dec
(4) |
2013 |
Jan
(5) |
Feb
(3) |
Mar
|
Apr
(3) |
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2014 |
Jan
(2) |
Feb
|
Mar
|
Apr
(1) |
May
(3) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(9) |
Nov
(7) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(4) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2017 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(5) |
Dec
|
2019 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
From: Brian F. <bfr...@gm...> - 2007-08-02 18:07:04
|
Hi Rob, Thanks for the explanation. Now that you mentioned it I recall reading somewhere OEM versus NEM. Guess I forgot about that. Thats what I get for using old code without deeper reading. Thanks again. Brian On 7/31/07, Robert May <rob...@us...> wrote: > > On 31/07/07, Brian Fredette <bfr...@gm...> wrote: > > I found the threads example posted in this group and began playing > around. > > I've modified the code to add a splash screen using > Win32::GUI:SplashScreen, > > a timer taken from Tutorial_Part4_timer.pl, a statusbar, and a > notifyicon. > > For some reason the timer never gets fired. I've tried removing the > > splashscreen and threads but it still won't fire. The tutorial works > ... > > why doesn't this: > > If you've already gone to the trouble of removing the SplashScreen > code and the threads code and seen that the problem still exists, why > not post that short code, rather than making us wade through lots of > unnecessary stuff? > > [snip very long code] > > I can reduce your problem to this: > > #!/perl -w > use strict; > use warnings; > > use Win32::GUI(); > > my $win = new Win32::GUI::Window( > -name => 'winMain', > -size => [700, 500], > -onResize => \&resizeWin, > ); > $win->AddTimer('T1', 1000); > > $win->Show(); > Win32::GUI::Dialog(); > > sub resizeWin { > print "Resize Event seen\n"; > } > > sub T1_Timer { > print "Timer went off!\n"; > } > > and it stems from the fact that you are mixing the 'Old Event Model' > (OEM) with the 'New Event Model' (NEM). > > The Old Event Model is the one that calls subs by a name composed of > the name of the object and the name of the event (e.g. in your example > T1_Timer()) > > The New Event Model is the one that calls a sub that you specify using > a -onXXX option to the constructor (e.g. in your example -onResize => > \&resizeWin) > > For (I think) performance reasons, when you specify a NEM event > handler using an -onXXX option in the constructor, then the OEM method > of working is switched off - hence in your example the T1_Timer() sub > is never called (btw in your example the _Maximize, _Minimize, _Resize > and _Terminate handlers are never called either) > > There are 3 ways to fix this. > > (1) Only use OEM event handlers: remove the -onResize option, and > rename resizeWin() as winMain_Resize() (you'll need to remove the > winMain_Resize you already have defined) > > (2) Use only NEM event handlers: add an -onTimer => > \&some_timer_hander line to the main window constructor, and rename > the T1_Timer() sub some_timer_handler() > > (3) Leave it all as it is, and add an -eventmodel => 'both' line to > the main window constructor. This is not the preferred solution, as > it is very easy to get confused and have 2 handlers for the same event > - for example if you did this to your code, you would have 2 handlers > for the Resize event (resizeWin() and winMain_Resize()) - as it > happens, the NEM handler would get called first, and because it > doesn't return 0, the OEM handler would get called afterwards. If > the NEM handler returned 0, the OEM handler wouldn't get called ... > see how this gets confusing ... > > Regards, > Rob. > |
From: Robert M. <ro...@th...> - 2007-08-02 13:43:18
|
On 02/08/07, Robert May <rob...@us...> wrote: > On 02/08/07, Jan Dubois <ja...@ac...> wrote: > > On Wed, 01 Aug 2007, Robert May wrote: > > > On 31/07/07, Robert May <rob...@us...> wrote: > > > > I'll post another version as soon as I've shown that it tests clean > > > > (hopefully tomorrow). > > > > I don't quite get the list of test failures. Are you getting test failures > > from just compiling the ActivePerl sources with `nmake && nmake test`? > > Yes. VC6 (although using the .h files from a more recent SDK). > Win2k. I don't build perl from source very often, but I don't think > I've ever had a completely clean test run with either ActivePerl or > the 'official' source. Turns out I had a broken type.exe on my path that caused lines like my $x = `type somefile`; to fail. Remove it, and I get a clean bill of health on the tests. That's that one solved. Regards, Rob. |
From: Robert M. <rob...@us...> - 2007-08-01 23:26:44
|
On 02/08/07, Jan Dubois <ja...@ac...> wrote: > On Wed, 01 Aug 2007, Robert May wrote: > > On 31/07/07, Robert May <rob...@us...> wrote: > > > I'll post another version as soon as I've shown that it tests clean > > > (hopefully tomorrow). > > I don't quite get the list of test failures. Are you getting test failures > from just compiling the ActivePerl sources with `nmake && nmake test`? Yes. VC6 (although using the .h files from a more recent SDK). Win2k. I don't build perl from source very often, but I don't think I've ever had a completely clean test run with either ActivePerl or the 'official' source. If you're interested I'll do a clean build from the 819 source tomorrow, and let you see the relevant bits of the test output. > That would be wrong. Running without test failures is a prerequisite > for the releases. OK - I'll investigate further too, but probably not until the weekend. > > Attached patches implement the same functionality against AS build 819 > > and, probably more importantly, perl 9.5.9. > > > > Tests run without failures (well, the same failures as I get without > > the patch - see below). > I'll take a look at your patches once I get a little more time. I may not > get around to it until the weekend though. No rush from my perspective. > Unfortunately we just missed ActivePerl 822, which was already approved > by QA this afternoon (there is no 821, except on HP-UX). I've not even caught up with 820 yet! Thanks for your input. Rob. |
From: Jan D. <ja...@ac...> - 2007-08-01 23:06:10
|
On Wed, 01 Aug 2007, Robert May wrote: > On 31/07/07, Robert May <rob...@us...> wrote: > > I'll post another version as soon as I've shown that it tests clean > > (hopefully tomorrow). I don't quite get the list of test failures. Are you getting test failures from just compiling the ActivePerl sources with `nmake && nmake test`? That would be wrong. Running without test failures is a prerequisite for the releases. > Attached patches implement the same functionality against AS build 819 > and, probably more importantly, perl 9.5.9. > > Tests run without failures (well, the same failures as I get without > the patch - see below). > > Jan - Would you like to comment on whether you think this is suitable? > If so I'll take it to P5P, if not I'll only propose the simple > change to the QS_ flags. I'd like to see something like this go in, > as it'll make future development for Win32::GUI a whole load more > robust. I'll take a look at your patches once I get a little more time. I may not get around to it until the weekend though. I definitely think we want to get these changes into Perl 5.10. Unfortunately we just missed ActivePerl 822, which was already approved by QA this afternoon (there is no 821, except on HP-UX). Cheers, -Jan |
From: Robert M. <ro...@th...> - 2007-08-01 22:19:04
|
On 31/07/07, Robert May <rob...@us...> wrote: > I'll post another version as soon as I've shown that it tests clean > (hopefully tomorrow). Attached patches implement the same functionality against AS build 819 and, probably more importantly, perl 9.5.9. Tests run without failures (well, the same failures as I get without the patch - see below). Jan - Would you like to comment on whether you think this is suitable? If so I'll take it to P5P, if not I'll only propose the simple change to the QS_ flags. I'd like to see something like this go in, as it'll make future development for Win32::GUI a whole load more robust. > > Still TODO/to think about: > > - I'd like to see us using registered messages rather than WM_USER_* > > macros. This would avoid us ever clashing with someone else's message > > numbers (this is only a potential problem for thread messages, not > > when we have a message window) Because we sometimes use thread messages, I think there should be better bounds checking within the handlers in win32_process_message(). For example we treat *any* message with value WM_USER_MESSAGE as ours, and blindly use the wParam value as an offset into the w32_pseudo_child_message_hwnds[] array. If someone else happened to pick this same message number for a thread message, and had a large number in wParam (a window handle for example), we'd end up trying to write beyond the end of the array. This might be the driver for me to implement the registered window messages, which would solve the problem. Regards, Rob. All test runs on win2000, showing results without and with the attached patches. (1) AS Build 819 Win2k: Failed Test Stat Wstat Total Fail Failed List of Failed ------------------------------------------------------------------------------- ../ext/IO/t/io_dup.t 6 4 66.67% 2-5 comp/multiline.t 6 2 33.33% 5-6 io/dup.t 26 6 23.08% 2-7 51 tests and 315 subtests skipped. Failed 3/997 test scripts, 99.70% okay. 12/118111 subtests failed, 99.99% okay. (2) AS Build 819 Win2k with patched win32.c Failed Test Stat Wstat Total Fail Failed List of Failed ------------------------------------------------------------------------------- ../ext/IO/t/io_dup.t 6 4 66.67% 2-5 comp/multiline.t 6 2 33.33% 5-6 io/dup.t 26 6 23.08% 2-7 51 tests and 315 subtests skipped. Failed 3/997 test scripts, 99.70% okay. 12/118111 subtests failed, 99.99% okay. (3) 5.9.5 Win2k: Failed Test Stat Wstat Total Fail List of Failed ------------------------------------------------------------------------------- ../ext/IO/t/io_dup.t 6 4 2-5 ../lib/Archive/Extract/t/01_Archive-Extra 255 65280 39 2 37 39 comp/multiline.t 6 2 5-6 io/dup.t 29 6 2-7 (1 subtest UNEXPECTEDLY SUCCEEDED), 55 tests and 728 subtests skipped. Failed 4/1457 test scripts. 14/183750 subtests failed. Files=1457, Tests=183750, 1022 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU) Failed 4/1457 test programs. 14/183750 subtests failed. (4) 5.9.5 Win2k: Failed Test Stat Wstat Total Fail List of Failed ------------------------------------------------------------------------------- ../ext/IO/t/io_dup.t 6 4 2-5 ../lib/Archive/Extract/t/01_Archive-Extra 255 65280 39 2 37 39 comp/multiline.t 6 2 5-6 io/dup.t 29 6 2-7 (1 subtest UNEXPECTEDLY SUCCEEDED), 55 tests and 728 subtests skipped. Failed 4/1457 test scripts. 14/183750 subtests failed. Files=1457, Tests=183750, 987 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU) Failed 4/1457 test programs. 14/183750 subtests failed. |
From: Robert M. <rob...@us...> - 2007-08-01 00:16:16
|
On 31/07/07, Brian Fredette <bfr...@gm...> wrote: > I found the threads example posted in this group and began playing around. > I've modified the code to add a splash screen using Win32::GUI:SplashScreen, > a timer taken from Tutorial_Part4_timer.pl, a statusbar, and a notifyicon. > For some reason the timer never gets fired. I've tried removing the > splashscreen and threads but it still won't fire. The tutorial works ... > why doesn't this: If you've already gone to the trouble of removing the SplashScreen code and the threads code and seen that the problem still exists, why not post that short code, rather than making us wade through lots of unnecessary stuff? [snip very long code] I can reduce your problem to this: #!/perl -w use strict; use warnings; use Win32::GUI(); my $win = new Win32::GUI::Window( -name => 'winMain', -size => [700, 500], -onResize => \&resizeWin, ); $win->AddTimer('T1', 1000); $win->Show(); Win32::GUI::Dialog(); sub resizeWin { print "Resize Event seen\n"; } sub T1_Timer { print "Timer went off!\n"; } and it stems from the fact that you are mixing the 'Old Event Model' (OEM) with the 'New Event Model' (NEM). The Old Event Model is the one that calls subs by a name composed of the name of the object and the name of the event (e.g. in your example T1_Timer()) The New Event Model is the one that calls a sub that you specify using a -onXXX option to the constructor (e.g. in your example -onResize => \&resizeWin) For (I think) performance reasons, when you specify a NEM event handler using an -onXXX option in the constructor, then the OEM method of working is switched off - hence in your example the T1_Timer() sub is never called (btw in your example the _Maximize, _Minimize, _Resize and _Terminate handlers are never called either) There are 3 ways to fix this. (1) Only use OEM event handlers: remove the -onResize option, and rename resizeWin() as winMain_Resize() (you'll need to remove the winMain_Resize you already have defined) (2) Use only NEM event handlers: add an -onTimer => \&some_timer_hander line to the main window constructor, and rename the T1_Timer() sub some_timer_handler() (3) Leave it all as it is, and add an -eventmodel => 'both' line to the main window constructor. This is not the preferred solution, as it is very easy to get confused and have 2 handlers for the same event - for example if you did this to your code, you would have 2 handlers for the Resize event (resizeWin() and winMain_Resize()) - as it happens, the NEM handler would get called first, and because it doesn't return 0, the OEM handler would get called afterwards. If the NEM handler returned 0, the OEM handler wouldn't get called ... see how this gets confusing ... Regards, Rob. |
From: Robert M. <rob...@us...> - 2007-07-31 21:23:26
|
On 30/07/07, Robert May <rob...@us...> wrote: > Attached is a patch to win32.c (against AS build 819). It implements > most of what I've talked about, plus a few other bits. It fails 2 of the fork() tests on bleed, and one under AS build 819. > A lot of the complexity of the context passing could be removed if we > were to agree to take the hit of doing a dTHX; in > win32_process_message. We don't go in there very often (only for > alarms, kills and forks (and thread creation?). Perhaps the overhead > is worth the reduction in complexity? On investigation it turns out that the dTHX; I was doing in win32_create_message_window() gives the context of the "parent" thread when forking. There are 2 ways to solve this - always pass the context into win32_create_message_window(), or do a dTHX; in win32_process_message. I've opted for the latter, as it simplifies the code a lot. We can always change this later. I'll post another version as soon as I've shown that it tests clean (hopefully tomorrow). > Still TODO: > - I'd like to see us using registered messages rather than WM_USER_* > macros. This would avoid us ever clashing with someone else's message > numbers (this is only a potential problem for thread messages, not > when we have a message window) Regards, Rob. |
From: Brian F. <bfr...@gm...> - 2007-07-31 02:16:51
|
All, I found the threads example posted in this group and began playing around. I've modified the code to add a splash screen using Win32::GUI:SplashScreen, a timer taken from Tutorial_Part4_timer.pl, a statusbar, and a notifyicon. For some reason the timer never gets fired. I've tried removing the splashscreen and threads but it still won't fire. The tutorial works ... why doesn't this: #!/perl -w use strict; use warnings; $|=1; use Win32::GUI; use Win32::GUI::SplashScreen; use threads; use threads::shared; use Thread::Queue; ## Create worker threads and associated variables. ## -- THIS MUST BE DONE, AND ALL THREADS STARTED ## -- BEFORE THE WINDOW IS CREATED. my $TQ1 = new Thread::Queue; my $TQ2 = new Thread::Queue; my $ts1_run : shared = 0; my $ts2_run : shared = 0; my $t1_objHandle : shared = 0; my $t2_objHandle : shared = 0; my $thread1 = threads->new(\&Thread1); my $thread2 = threads->new(\&Thread2); ## Hide Perl Window my $perlW = Win32::GUI::GetPerlWindow(); #Win32::GUI::Hide($perlW); # Create and diaplay the splash screen Win32::GUI::SplashScreen::Show( -file => "splash.bmp", # set a name that doe not exist to force internal splash screen -mintime => 3, ); # Hide the splash - blocks until the splashscreen is removed Win32::GUI::SplashScreen::Done(); ## Create Window my $win = new Win32::GUI::Window( -name => 'winMain', -title => "My Main Window", -size => [700, 500], -onResize => \&resizeWin, ); my $t1 = $win->AddTimer('T1', 1000); # never calls sub T1_Timer $win->AddButton( -name => 'btnRun1', -size => [50,20], -pos => [4,10], -text => 'Run 1', ); $win->AddProgressBar( -name => 'pbT1', -size => [120,20], -pos => [58,10], -smooth => 1, ); $win->{pbT1}->SetRange(0,99); $t1_objHandle = $win->{pbT1}->{-handle}; $win->AddButton( -name => 'btnRun2', -size => [50,20], -pos => [4,32], -text => 'Run 2', ); $win->AddProgressBar( -name => 'pbT2', -size => [120,20], -pos => [58,32], -smooth => 1, ); $win->{pbT2}->SetRange(0,99); $t2_objHandle = $win->{pbT2}->{-handle}; my $sb = $win->AddStatusBar(); my $icon = new Win32::GUI::Icon('d:/source/perl/auditutil/images/data_server.ICO'); my $ni = $win->AddNotifyIcon( -name => "NI", -icon => $icon, -tip => "Hello" ); $win->Center(); $win->Show(); Win32::GUI::Dialog(); #### Boss sub winMain_Maximize{ 0 }; sub winMain_Minimize{ 0 }; sub winMain_Resize{ 0 }; sub winMain_Terminate{ $ts1_run = -1; $ts2_run = -1; #join workers. $thread1->join(); $thread2->join(); $win->NI->Remove(); $win->Hide(); return -1; } sub btnRun1_Click{ print "clicked btnRun1 \n"; if($ts1_run){ $win->{btnRun1}->Text('Run 1'); $ts1_run = 0; }else{ $win->{btnRun1}->Text('Stop 1'); $ts1_run = 1; } return 1; } sub btnRun2_Click{ if($ts2_run){ $win->{btnRun2}->Text('Run 2'); $ts2_run = 0; }else{ $win->{btnRun2}->Text('Stop 2'); $ts2_run = 1; } return 1; } sub resizeWin { $sb->Move(0, $win->ScaleHeight - $sb->Height); $sb->Resize($win->ScaleWidth, $sb->Height); } sub T1_Timer { print "Timer went off!\n"; return 0; } #### Child 1 sub Thread1{ my $ctr = 1; while( $ts1_run != -1 ){ # die when semaphore says so. if( $ts1_run == 1 && defined($t1_objHandle) ){ #only create a new value when the semaphore is Up Win32::GUI::ProgressBar::SetPos($t1_objHandle, $ctr); $ctr++; $ctr = 0 if $ctr > 99; } select(undef, undef, undef, 0.01); } } #### Child 2 sub Thread2{ my $ctr = 1; while( $ts2_run != -1 ){ # die when semaphore says so. if( $ts2_run == 1 && defined($t1_objHandle) ){ #only create a new value when the semaphore is Up Win32::GUI::ProgressBar::SetPos($t2_objHandle, $ctr); $ctr++; $ctr = 0 if $ctr > 99; } select(undef, undef, undef, 0.01); } } Thanks in advance, Brian Fredette |
From: Tian8970 <tia...@gm...> - 2007-07-31 00:39:38
|
2007/7/31, per...@li... < per...@li...>: > > Send Perl-Win32-GUI-Users mailing list submissions to > per...@li... > > To subscribe or unsubscribe via the World Wide Web, visit > https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users > or, via email, send a message with subject or body 'help' to > per...@li... > > You can reach the person managing the list at > per...@li... > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Perl-Win32-GUI-Users digest..." > > > Today's Topics: > > 1. Re: Why is my GUI hanging? (Jan Dubois) > 2. Re: Why is my GUI hanging? (Robert May) > 3. HWND_MESSAGE on Win98 [Was: Why is my GUI hanging?] (Robert May) > 4. Re: HWND_MESSAGE on Win98 (Jan Dubois) > 5. Re: HWND_MESSAGE on Win98 (Robert May) > 6. Re: Why is my GUI hanging? (Robert May) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Sat, 28 Jul 2007 18:04:26 -0700 > From: "Jan Dubois" <ja...@ac...> > Subject: Re: [perl-win32-gui-users] Why is my GUI hanging? > To: "'Robert May'" <rob...@us...> > Cc: per...@li... > Message-ID: <051601c7d17c$68c63ac0$3a52b040$@com> > Content-Type: text/plain; charset="us-ascii" > > On Sat, 28 Jul 2007, Robert May wrote: > > On 28/07/07, Jan Dubois <ja...@ac...> wrote: > > > CreateProcess() will return and not wait for command.com/cmd.exe to > > > initialize. Upon return win32_spawnvp() will call win32_msgwait(), > > > which should continue to pump the message loop until the external > > > process ends. > > > > That's what's supposed to happen, but in AS build 819 on win98 (that's > > all I have access to this weekend), I have to change the flags to > > MsgWaitForMultipleObjects from QS_ALLEVENTS to > > QS_ALLEVENTS|QS_SENDMESSAGE to get it to pump the sent WM_DDE_INITIATE > > message. > > Alright, I looked at the code again, and the real problem is: > win32_msgwait() doesn't actually dispatch any messages; it only > processes (via win32_async_check()) WM_TIMER and WM_USER messages sent > to hwnd NULL. > > The whole reason for *not* running a message pump is to allow an > embedding application to use PostThreadMessage() too. If we ran a > message pump, we wouldn't know what to do with messages sent to hwnd > NULL that we are not expecting. > > But given the problem you discovered with DDE initiation while waiting > for system() to return, I think win32_async_check() needs to run a > message pump. Given that the whole PostThreadMessage() mechanism is too > brittle for GUI threads anyways (you cannot avoid losing messages), I > doubt anyone is using it while also embedding Perl. > > While looking at this issue I noticed that even though we are using a > message-only window on Windows 2000 and later, we are not actually > expecting anybody else to dispatch the messages to a wndproc; we always > try to snatch them out of the queue via PeekMessage(). So we still > inherit the brittleness of the PostThreadMessage() mechanism. > > I'll see if I can come up with a patch for both issues some time later > next week. > > Cheers, > -Jan > > PS: Please let me know if you happen to know a mechanism to create a > message-only window on 98/NT (a window that is not top-level and > will not receive broadcast messages). If this were possible, then we > could get rid of PostThreadMessage() completely. > > > > > > ------------------------------ > > Message: 2 > Date: Sun, 29 Jul 2007 13:19:52 +0100 > From: "Robert May" <rob...@us...> > Subject: Re: [perl-win32-gui-users] Why is my GUI hanging? > To: "Jan Dubois" <ja...@ac...> > Cc: per...@li... > Message-ID: > <54b...@ma...> > Content-Type: text/plain; charset=ISO-8859-1 > > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > On Sat, 28 Jul 2007, Robert May wrote: > > > On 28/07/07, Jan Dubois <ja...@ac...> wrote: > > > > CreateProcess() will return and not wait for command.com/cmd.exe to > > > > initialize. Upon return win32_spawnvp() will call win32_msgwait(), > > > > which should continue to pump the message loop until the external > > > > process ends. > > > > > > That's what's supposed to happen, but in AS build 819 on win98 (that's > > > all I have access to this weekend), I have to change the flags to > > > MsgWaitForMultipleObjects from QS_ALLEVENTS to > > > QS_ALLEVENTS|QS_SENDMESSAGE to get it to pump the sent WM_DDE_INITIATE > > > message. > > > > Alright, I looked at the code again, and the real problem is: > > win32_msgwait() doesn't actually dispatch any messages; it only > > processes (via win32_async_check()) WM_TIMER and WM_USER messages sent > > to hwnd NULL. > > PeekMessage() will dispatch sent messages, (apparently) regardless of > the filtering applied. Certainly on Win98 all I have to change to fix > this particular DDE problem is to add QS_SENDMESSAGE to the > MsgWaitForMultipleObjects() to get it to return if there is a sent > message in the queue - even if I've called alarm(0); to make > w32_hwnd_message not equal to INVALID_HANDLE_VALUE, so that we do the > 'thread message only' PeekMessage, the DDE problem is gone. > > > The whole reason for *not* running a message pump is to allow an > > embedding application to use PostThreadMessage() too. If we ran a > > message pump, we wouldn't know what to do with messages sent to hwnd > > NULL that we are not expecting. > > Right. But there are good reasons not to run a full message pump. > For example, from a Win32::GUI point of view I really don't want > win32_async_check to be dispatching keyboard messages for me - first, > I may want to be using a message pump with more complexity that simply > doing a TranslateMessage/DispatchMessage - I may want to dela with > dialog messages (IsDialogMessage()) and accelerators > (IsAcceleleratorMessage()). I think it would be very confusing if, > for example, sleep() started behaving like this. > > > But given the problem you discovered with DDE initiation while waiting > > for system() to return, I think win32_async_check() needs to run a > > message pump. > > I think it's already doing enough. The DDE problem is that > MsgWaitForMultipleObjects isn't returning for the *sent* > WM_DDE_INITIATE message. > > > Given that the whole PostThreadMessage() mechanism is too > > brittle for GUI threads anyways (you cannot avoid losing messages), I > > doubt anyone is using it while also embedding Perl. > > I wouldn't bet on it. What we should do is put a call to > CallMsgFilter() in any message pump loop we have that might pull > thread messages off the queue, to give someone else a chance to see > then, if they need to (See > http://blogs.msdn.com/oldnewthing/archive/2005/04/28/412574.aspx for > more info) > > > While looking at this issue I noticed that even though we are using a > > message-only window on Windows 2000 and later, we are not actually > > expecting anybody else to dispatch the messages to a wndproc; we always > > try to snatch them out of the queue via PeekMessage(). So we still > > inherit the brittleness of the PostThreadMessage() mechanism. > > This is a problem that I have on my list of things to look at. In > particular, even if we're using a message-only window, someone else's > message pump (e.g the one run by Win32::MsgBox, may pull our messages > from the queue and translate/dispatch them. As we are not handling > the messages in the window's wndproc, they never get processed. > > > I'll see if I can come up with a patch for both issues some time later > > next week. > > Currently I'm leaning towards just adding QS_SENDMESSAGE to the > MsgWaitForMultipleObjects() call - we'll need to do this anyway to > solve the DDE problem, and I think it's a small enough change to > propose for 5.10. I think anything else we do will be a much bigger > change, and will probably have to wait for after that. > > I'll spent some more time thinking about this during the week. > Should we move this discussion to P5P? > > > PS: Please let me know if you happen to know a mechanism to create a > > message-only window on 98/NT (a window that is not top-level and > > will not receive broadcast messages). If this were possible, then we > > could get rid of PostThreadMessage() completely. > > I'm not aware of a way, but I'll do some research. I'm pretty sure > that we don't wan ta real top-level window .... > > Regards, > Rob. > > > > ------------------------------ > > Message: 3 > Date: Sun, 29 Jul 2007 15:59:33 +0100 > From: "Robert May" <rob...@us...> > Subject: [perl-win32-gui-users] HWND_MESSAGE on Win98 [Was: Why is my > GUI hanging?] > To: "Jan Dubois" <ja...@ac...> > Cc: per...@li... > Message-ID: > <54b...@ma...> > Content-Type: text/plain; charset=ISO-8859-1 > > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > PS: Please let me know if you happen to know a mechanism to create a > > message-only window on 98/NT (a window that is not top-level and > > will not receive broadcast messages). If this were possible, then we > > could get rid of PostThreadMessage() completely. > > I can't speak for WinNT, as I don't have it available, but on Win98, > using HWD_MESSAGE as the parent window to CreateWindowEx() appears to > work fine (despite what MSDN says). Using it I end up with a window > that is a child of a hidden system window. The window is not top > level, not visible, and I can't make it receive a broadcast message. > > As soon as I can get back in front of a Win2K box I'll look to see if > the implementation looks the same there. > > Regards, > Rob. > > > > ------------------------------ > > Message: 4 > Date: Mon, 30 Jul 2007 00:45:40 -0700 > From: "Jan Dubois" <ja...@ac...> > Subject: Re: [perl-win32-gui-users] HWND_MESSAGE on Win98 > To: "'Robert May'" <rob...@us...> > Cc: per...@li... > Message-ID: <05cf01c7d27d$a07d4e20$e177ea60$@com> > Content-Type: text/plain; charset="us-ascii" > > On Sun, 29 Jul 2007, Robert May wrote: > > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > > PS: Please let me know if you happen to know a mechanism to create a > > > message-only window on 98/NT (a window that is not top-level and > > > will not receive broadcast messages). If this were possible, > > > then we could get rid of PostThreadMessage() completely. > > > > I can't speak for WinNT, as I don't have it available, but on Win98, > > using HWD_MESSAGE as the parent window to CreateWindowEx() appears to > > work fine (despite what MSDN says). Using it I end up with a window > > that is a child of a hidden system window. The window is not top > > level, not visible, and I can't make it receive a broadcast message. > > I've seen at least anecdotal evidence that using HWND_MESSAGE on 98 might > be somewhat dangerous: > > http://www.virtualdub.org/blog/pivot/entry.php?id=153 > > So I'm not sure if we want to ignore MSDN on this point. > > Cheers, > -Jan > > > > > ------------------------------ > > Message: 5 > Date: Mon, 30 Jul 2007 20:11:24 +0100 > From: "Robert May" <rob...@us...> > Subject: Re: [perl-win32-gui-users] HWND_MESSAGE on Win98 > To: "Jan Dubois" <ja...@ac...> > Cc: per...@li... > Message-ID: > <54b...@ma...> > Content-Type: text/plain; charset=ISO-8859-1 > > On 30/07/07, Jan Dubois <ja...@ac...> wrote: > > On Sun, 29 Jul 2007, Robert May wrote: > > > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > > > PS: Please let me know if you happen to know a mechanism to create a > > > > message-only window on 98/NT (a window that is not top-level and > > > > will not receive broadcast messages). If this were possible, > > > > then we could get rid of PostThreadMessage() completely. > > > > > > I can't speak for WinNT, as I don't have it available, but on Win98, > > > using HWD_MESSAGE as the parent window to CreateWindowEx() appears to > > > work fine (despite what MSDN says). Using it I end up with a window > > > that is a child of a hidden system window. The window is not top > > > level, not visible, and I can't make it receive a broadcast message. > > > > I've seen at least anecdotal evidence that using HWND_MESSAGE on 98 > might > > be somewhat dangerous: > > > > http://www.virtualdub.org/blog/pivot/entry.php?id=153 > > > > So I'm not sure if we want to ignore MSDN on this point. > > Thanks for that link. I had already readr it, and can confirm that > GetAncestor(hwnd, GA_ROOT) crashes applications on my Win98 box. I'm > nott 100% sure, what the reference to DialogBoxParam is, but if we > assume that he was passing the message window handle as the owner > window for a dialog, then it's well documented that this first thing > the DialogBox...() functions do is call GetAncestor(..., GA_ROOT), to > account for people passing a child window handle, which is not a valid > owner-window. As we aren't likely to ever call GetAncestor() or > DialogBox...() on the window, we might be safe. I'm less happy about > what he says about the BSOD. > > There's surprisingly little information on on the web regarding > HWND_MESSAGE. I think the safest bet is to keep using thread messages > for the earlier systems. It's a shame, as loosing that complexity > would have been good. > > Regards, > Rob. > > > > ------------------------------ > > Message: 6 > Date: Mon, 30 Jul 2007 22:18:59 +0100 > From: "Robert May" <rob...@us...> > Subject: Re: [perl-win32-gui-users] Why is my GUI hanging? > To: per...@li... > Message-ID: > <54b...@ma...> > Content-Type: text/plain; charset="iso-8859-1" > > Re-post to the win32-gui-users list, without the zip attachment, so > that it goes through. > > Rob. > > On 30/07/07, Robert May <rob...@us...> wrote: > > > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > > > The whole reason for *not* running a message pump is to allow an > > > > embedding application to use PostThreadMessage() too. If we ran a > > > > message pump, we wouldn't know what to do with messages sent to hwnd > > > > NULL that we are not expecting. > > > > On 29/07/07, Robert May <rob...@us...> wrote: > > > Right. But there are good reasons not to run a full message pump. > > > For example, from a Win32::GUI point of view I really don't want > > > win32_async_check to be dispatching keyboard messages for me - first, > > > I may want to be using a message pump with more complexity that simply > > > doing a TranslateMessage/DispatchMessage - I may want to dela with > > > dialog messages (IsDialogMessage()) and accelerators > > > (IsAcceleleratorMessage()). I think it would be very confusing if, > > > for example, sleep() started behaving like this. > > > > Thinking about this further it would be worse than confusing - it > > would potentially result in incorrect ordering of messages: > > > > Imagine I write XS with thin wrappers to GetMessage, TranslateMessage > > and DispatchMessage, such that I could write perl code somthing like > > this: > > > > while(my $msg = GetMessage()) { > > TranslateMessage($msg); > > DispatchMessage($msg); > > } > > > > Now I can end up in win32_async check between any 2 perl calls, and > > say I had just pulled a WM_KEYDOWN message. TranslateMessage pushes a > > WM_CHAR message onto the top of the queue. If I end up in > > win32_async_check between the TranslateMessage and DispatchMessage > > calls, and it pumps keyboard messages, then the WM_CHAR will be > > delivered before the WM_KEYDOWN. This would at best be confusing, and > > more likely break applications. > > > > I think the approach that win32_async_check takes currently is almost > OK. > > > > Attached is a patch to win32.c (against AS build 819). It implements > > most of what I've talked about, plus a few other bits. > > > > Highlights: > > > > - QS_SENDMESSAGE added to wim32_msgwait to solve the DDE problem. > > > > - I've left QS_ALLMESSAGES in win32_msgwait, rather than using the > > QS_POSTMESSAGE|QS_TIMER that we did in build 820 and blead, I think > > it's better. > > > > - I've wrapped the PostMessage(.... PM_NOREMOVE) in win32_async check > > in a while() loop, to ensure that all messages get marked read - I can > > see occasions when there are multiple messages in the queue, and > > win32_msgwait/win32_async_check spin a couple of time to mark them all > > read, we now only get one loop. I've re-factored the function to move > > the PeekMessage loop to the end, so that I don't have to have it and > > the signal dispatch code twice. > > added another PostMessage loop (this is now very similar to the patch > > I proposed to solve the bug that caused use to change the QS_* flags > > for build 820/bleed. > > > > - the message pump part of win32_async_check now re-posts WM_QUIT > > messages (needed to play nicely with other message loops) > > > > - I've moved the message handling from win32_async_check to it's own > > function: win32_process_messages(), which can process either thread or > > window messages. > > > > - I've created a windows class for our message window, and made it's > > window procedure call win32_process_messages(). win32_async_check() now > > does a Translate/Dispatch message if we have a message window. This > > means that if we have a message window we won't lose messages from > > someone else's message loop. > > > > - I've added a hook procedure to handle the thread messages, if we > > don't have a message window. win32_async_check calls it using > > CallMsgFilter if it ever retrieves a thread message. This now means > > that we won't lose any thread messages in other modal loops, so long > > as those loops do a CallMsgFilter() - All Win32 OS modal loops do > > this (including message boxes, menus, window-resizing/moving etc.); > > we should encourage all other GUI packages (e.g. Tk, > > Win32::GUI) to make this call at appropriate times. > > > > - The hook procedure passes thread messages that we might be > > interested in to win32_process_message, and returns true if we process > it; > > it passes it along the hook chain if we don't process it. This allows > someone > > else using thread messages, in the case where we don't have a message > > window, to call SetWindowsHookEx to install their own handler to catch > > thread messages that we pull off the message queue. > > > > I think I've covered most bases. I can't run the test suite, as it > > throws too many errors on Win98. I'll try to do it on Win2K in the > > next couple of days. > > > > I also attach a couple of scripts that exhibit some of the > > problems I was trying to eliminate. They are documented in the > > scripts themselves. > > > > Still TODO: > > - I need help getting some of the > > PERL_IMPLICIT_CONTEXT/MULTIPLICITY/whatever ifdefs right. The context > > passing is a bit complex, as we can't change the signature for the > > window procedure callback to include a context, but I've coded a way > > round this. > > - I'd like to see us using registered messages rather than WM_USER_* > > macros. This would avoid us ever clashing with someone else's message > > numbers (this is only a potential problem for thread messages, not > > when we have a message window) > > > > A lot of the complexity of the context passing could be removed if we > > were to agree to take the hit of doing a dTHX; in > > win32_process_message. We don't go in there very often (only for > > alarms, kills and forks (and thread creation?). Perhaps the overhead > > is worth the reduction in complexity? > > > > I will re-iterate: all that is actually needed to solve the original > > DDE initialisation problem that started this discussion is to add > > QS_SENDMESSAGE to the MsgWaitForMultipleObjects line in > > win32_msgwait(). All the rest of this stuff would be 'nice to have' > > so that Win32::GUI, Tk and other gui tookits can play nicely with perl > > on Win32. > > > > I hope this is useful, > > Regards, > > Rob. > > > > > > > -- > Please update your address book with my new email address: > ro...@th... > -------------- next part -------------- > A non-text attachment was scrubbed... > Name: win32.c.patch > Type: application/octet-stream > Size: 12021 bytes > Desc: not available > > ------------------------------ > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? Stop. > Now Search log events and configuration files using AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/ > > ------------------------------ > > _______________________________________________ > Perl-Win32-GUI-Users mailing list > Per...@li... > https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users > http://perl-win32-gui.sourceforge.net/ > > > End of Perl-Win32-GUI-Users Digest, Vol 14, Issue 9 > *************************************************** > -- http://mail.google.com/mail/photos/static/UykTcFMUSSZlBPRqPNyMUKmXZaO60lDRgzMreAsYBtU10leFylauhTXh6Tlxc-MA |
From: Tian8970 <tia...@gm...> - 2007-07-31 00:39:02
|
-- http://mail.google.com/mail/photos/static/UykTcFMUSSZlBPRqPNyMUKmXZaO60lDRgzMreAsYBtU10leFylauhTXh6Tlxc-MA |
From: Robert M. <rob...@us...> - 2007-07-30 21:19:05
|
Re-post to the win32-gui-users list, without the zip attachment, so that it goes through. Rob. On 30/07/07, Robert May <rob...@us...> wrote: > > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > > The whole reason for *not* running a message pump is to allow an > > > embedding application to use PostThreadMessage() too. If we ran a > > > message pump, we wouldn't know what to do with messages sent to hwnd > > > NULL that we are not expecting. > > On 29/07/07, Robert May <rob...@us...> wrote: > > Right. But there are good reasons not to run a full message pump. > > For example, from a Win32::GUI point of view I really don't want > > win32_async_check to be dispatching keyboard messages for me - first, > > I may want to be using a message pump with more complexity that simply > > doing a TranslateMessage/DispatchMessage - I may want to dela with > > dialog messages (IsDialogMessage()) and accelerators > > (IsAcceleleratorMessage()). I think it would be very confusing if, > > for example, sleep() started behaving like this. > > Thinking about this further it would be worse than confusing - it > would potentially result in incorrect ordering of messages: > > Imagine I write XS with thin wrappers to GetMessage, TranslateMessage > and DispatchMessage, such that I could write perl code somthing like > this: > > while(my $msg = GetMessage()) { > TranslateMessage($msg); > DispatchMessage($msg); > } > > Now I can end up in win32_async check between any 2 perl calls, and > say I had just pulled a WM_KEYDOWN message. TranslateMessage pushes a > WM_CHAR message onto the top of the queue. If I end up in > win32_async_check between the TranslateMessage and DispatchMessage > calls, and it pumps keyboard messages, then the WM_CHAR will be > delivered before the WM_KEYDOWN. This would at best be confusing, and > more likely break applications. > > I think the approach that win32_async_check takes currently is almost OK. > > Attached is a patch to win32.c (against AS build 819). It implements > most of what I've talked about, plus a few other bits. > > Highlights: > > - QS_SENDMESSAGE added to wim32_msgwait to solve the DDE problem. > > - I've left QS_ALLMESSAGES in win32_msgwait, rather than using the > QS_POSTMESSAGE|QS_TIMER that we did in build 820 and blead, I think > it's better. > > - I've wrapped the PostMessage(.... PM_NOREMOVE) in win32_async check > in a while() loop, to ensure that all messages get marked read - I can > see occasions when there are multiple messages in the queue, and > win32_msgwait/win32_async_check spin a couple of time to mark them all > read, we now only get one loop. I've re-factored the function to move > the PeekMessage loop to the end, so that I don't have to have it and > the signal dispatch code twice. > added another PostMessage loop (this is now very similar to the patch > I proposed to solve the bug that caused use to change the QS_* flags > for build 820/bleed. > > - the message pump part of win32_async_check now re-posts WM_QUIT > messages (needed to play nicely with other message loops) > > - I've moved the message handling from win32_async_check to it's own > function: win32_process_messages(), which can process either thread or > window messages. > > - I've created a windows class for our message window, and made it's > window procedure call win32_process_messages(). win32_async_check() now > does a Translate/Dispatch message if we have a message window. This > means that if we have a message window we won't lose messages from > someone else's message loop. > > - I've added a hook procedure to handle the thread messages, if we > don't have a message window. win32_async_check calls it using > CallMsgFilter if it ever retrieves a thread message. This now means > that we won't lose any thread messages in other modal loops, so long > as those loops do a CallMsgFilter() - All Win32 OS modal loops do > this (including message boxes, menus, window-resizing/moving etc.); > we should encourage all other GUI packages (e.g. Tk, > Win32::GUI) to make this call at appropriate times. > > - The hook procedure passes thread messages that we might be > interested in to win32_process_message, and returns true if we process it; > it passes it along the hook chain if we don't process it. This allows someone > else using thread messages, in the case where we don't have a message > window, to call SetWindowsHookEx to install their own handler to catch > thread messages that we pull off the message queue. > > I think I've covered most bases. I can't run the test suite, as it > throws too many errors on Win98. I'll try to do it on Win2K in the > next couple of days. > > I also attach a couple of scripts that exhibit some of the > problems I was trying to eliminate. They are documented in the > scripts themselves. > > Still TODO: > - I need help getting some of the > PERL_IMPLICIT_CONTEXT/MULTIPLICITY/whatever ifdefs right. The context > passing is a bit complex, as we can't change the signature for the > window procedure callback to include a context, but I've coded a way > round this. > - I'd like to see us using registered messages rather than WM_USER_* > macros. This would avoid us ever clashing with someone else's message > numbers (this is only a potential problem for thread messages, not > when we have a message window) > > A lot of the complexity of the context passing could be removed if we > were to agree to take the hit of doing a dTHX; in > win32_process_message. We don't go in there very often (only for > alarms, kills and forks (and thread creation?). Perhaps the overhead > is worth the reduction in complexity? > > I will re-iterate: all that is actually needed to solve the original > DDE initialisation problem that started this discussion is to add > QS_SENDMESSAGE to the MsgWaitForMultipleObjects line in > win32_msgwait(). All the rest of this stuff would be 'nice to have' > so that Win32::GUI, Tk and other gui tookits can play nicely with perl > on Win32. > > I hope this is useful, > Regards, > Rob. > > -- Please update your address book with my new email address: ro...@th... |
From: Robert M. <rob...@us...> - 2007-07-30 19:11:25
|
On 30/07/07, Jan Dubois <ja...@ac...> wrote: > On Sun, 29 Jul 2007, Robert May wrote: > > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > > PS: Please let me know if you happen to know a mechanism to create a > > > message-only window on 98/NT (a window that is not top-level and > > > will not receive broadcast messages). If this were possible, > > > then we could get rid of PostThreadMessage() completely. > > > > I can't speak for WinNT, as I don't have it available, but on Win98, > > using HWD_MESSAGE as the parent window to CreateWindowEx() appears to > > work fine (despite what MSDN says). Using it I end up with a window > > that is a child of a hidden system window. The window is not top > > level, not visible, and I can't make it receive a broadcast message. > > I've seen at least anecdotal evidence that using HWND_MESSAGE on 98 might > be somewhat dangerous: > > http://www.virtualdub.org/blog/pivot/entry.php?id=153 > > So I'm not sure if we want to ignore MSDN on this point. Thanks for that link. I had already readr it, and can confirm that GetAncestor(hwnd, GA_ROOT) crashes applications on my Win98 box. I'm nott 100% sure, what the reference to DialogBoxParam is, but if we assume that he was passing the message window handle as the owner window for a dialog, then it's well documented that this first thing the DialogBox...() functions do is call GetAncestor(..., GA_ROOT), to account for people passing a child window handle, which is not a valid owner-window. As we aren't likely to ever call GetAncestor() or DialogBox...() on the window, we might be safe. I'm less happy about what he says about the BSOD. There's surprisingly little information on on the web regarding HWND_MESSAGE. I think the safest bet is to keep using thread messages for the earlier systems. It's a shame, as loosing that complexity would have been good. Regards, Rob. |
From: Jan D. <ja...@ac...> - 2007-07-30 07:46:34
|
On Sun, 29 Jul 2007, Robert May wrote: > On 29/07/07, Jan Dubois <ja...@ac...> wrote: > > PS: Please let me know if you happen to know a mechanism to create a > > message-only window on 98/NT (a window that is not top-level and > > will not receive broadcast messages). If this were possible, > > then we could get rid of PostThreadMessage() completely. > > I can't speak for WinNT, as I don't have it available, but on Win98, > using HWD_MESSAGE as the parent window to CreateWindowEx() appears to > work fine (despite what MSDN says). Using it I end up with a window > that is a child of a hidden system window. The window is not top > level, not visible, and I can't make it receive a broadcast message. I've seen at least anecdotal evidence that using HWND_MESSAGE on 98 might be somewhat dangerous: http://www.virtualdub.org/blog/pivot/entry.php?id=153 So I'm not sure if we want to ignore MSDN on this point. Cheers, -Jan |
From: Robert M. <rob...@us...> - 2007-07-29 14:59:31
|
On 29/07/07, Jan Dubois <ja...@ac...> wrote: > PS: Please let me know if you happen to know a mechanism to create a > message-only window on 98/NT (a window that is not top-level and > will not receive broadcast messages). If this were possible, then we > could get rid of PostThreadMessage() completely. I can't speak for WinNT, as I don't have it available, but on Win98, using HWD_MESSAGE as the parent window to CreateWindowEx() appears to work fine (despite what MSDN says). Using it I end up with a window that is a child of a hidden system window. The window is not top level, not visible, and I can't make it receive a broadcast message. As soon as I can get back in front of a Win2K box I'll look to see if the implementation looks the same there. Regards, Rob. |
From: Robert M. <rob...@us...> - 2007-07-29 12:19:50
|
On 29/07/07, Jan Dubois <ja...@ac...> wrote: > On Sat, 28 Jul 2007, Robert May wrote: > > On 28/07/07, Jan Dubois <ja...@ac...> wrote: > > > CreateProcess() will return and not wait for command.com/cmd.exe to > > > initialize. Upon return win32_spawnvp() will call win32_msgwait(), > > > which should continue to pump the message loop until the external > > > process ends. > > > > That's what's supposed to happen, but in AS build 819 on win98 (that's > > all I have access to this weekend), I have to change the flags to > > MsgWaitForMultipleObjects from QS_ALLEVENTS to > > QS_ALLEVENTS|QS_SENDMESSAGE to get it to pump the sent WM_DDE_INITIATE > > message. > > Alright, I looked at the code again, and the real problem is: > win32_msgwait() doesn't actually dispatch any messages; it only > processes (via win32_async_check()) WM_TIMER and WM_USER messages sent > to hwnd NULL. PeekMessage() will dispatch sent messages, (apparently) regardless of the filtering applied. Certainly on Win98 all I have to change to fix this particular DDE problem is to add QS_SENDMESSAGE to the MsgWaitForMultipleObjects() to get it to return if there is a sent message in the queue - even if I've called alarm(0); to make w32_hwnd_message not equal to INVALID_HANDLE_VALUE, so that we do the 'thread message only' PeekMessage, the DDE problem is gone. > The whole reason for *not* running a message pump is to allow an > embedding application to use PostThreadMessage() too. If we ran a > message pump, we wouldn't know what to do with messages sent to hwnd > NULL that we are not expecting. Right. But there are good reasons not to run a full message pump. For example, from a Win32::GUI point of view I really don't want win32_async_check to be dispatching keyboard messages for me - first, I may want to be using a message pump with more complexity that simply doing a TranslateMessage/DispatchMessage - I may want to dela with dialog messages (IsDialogMessage()) and accelerators (IsAcceleleratorMessage()). I think it would be very confusing if, for example, sleep() started behaving like this. > But given the problem you discovered with DDE initiation while waiting > for system() to return, I think win32_async_check() needs to run a > message pump. I think it's already doing enough. The DDE problem is that MsgWaitForMultipleObjects isn't returning for the *sent* WM_DDE_INITIATE message. > Given that the whole PostThreadMessage() mechanism is too > brittle for GUI threads anyways (you cannot avoid losing messages), I > doubt anyone is using it while also embedding Perl. I wouldn't bet on it. What we should do is put a call to CallMsgFilter() in any message pump loop we have that might pull thread messages off the queue, to give someone else a chance to see then, if they need to (See http://blogs.msdn.com/oldnewthing/archive/2005/04/28/412574.aspx for more info) > While looking at this issue I noticed that even though we are using a > message-only window on Windows 2000 and later, we are not actually > expecting anybody else to dispatch the messages to a wndproc; we always > try to snatch them out of the queue via PeekMessage(). So we still > inherit the brittleness of the PostThreadMessage() mechanism. This is a problem that I have on my list of things to look at. In particular, even if we're using a message-only window, someone else's message pump (e.g the one run by Win32::MsgBox, may pull our messages from the queue and translate/dispatch them. As we are not handling the messages in the window's wndproc, they never get processed. > I'll see if I can come up with a patch for both issues some time later > next week. Currently I'm leaning towards just adding QS_SENDMESSAGE to the MsgWaitForMultipleObjects() call - we'll need to do this anyway to solve the DDE problem, and I think it's a small enough change to propose for 5.10. I think anything else we do will be a much bigger change, and will probably have to wait for after that. I'll spent some more time thinking about this during the week. Should we move this discussion to P5P? > PS: Please let me know if you happen to know a mechanism to create a > message-only window on 98/NT (a window that is not top-level and > will not receive broadcast messages). If this were possible, then we > could get rid of PostThreadMessage() completely. I'm not aware of a way, but I'll do some research. I'm pretty sure that we don't wan ta real top-level window .... Regards, Rob. |
From: Jan D. <ja...@ac...> - 2007-07-29 01:05:18
|
On Sat, 28 Jul 2007, Robert May wrote: > On 28/07/07, Jan Dubois <ja...@ac...> wrote: > > CreateProcess() will return and not wait for command.com/cmd.exe to > > initialize. Upon return win32_spawnvp() will call win32_msgwait(), > > which should continue to pump the message loop until the external > > process ends. > > That's what's supposed to happen, but in AS build 819 on win98 (that's > all I have access to this weekend), I have to change the flags to > MsgWaitForMultipleObjects from QS_ALLEVENTS to > QS_ALLEVENTS|QS_SENDMESSAGE to get it to pump the sent WM_DDE_INITIATE > message. Alright, I looked at the code again, and the real problem is: win32_msgwait() doesn't actually dispatch any messages; it only processes (via win32_async_check()) WM_TIMER and WM_USER messages sent to hwnd NULL. The whole reason for *not* running a message pump is to allow an embedding application to use PostThreadMessage() too. If we ran a message pump, we wouldn't know what to do with messages sent to hwnd NULL that we are not expecting. But given the problem you discovered with DDE initiation while waiting for system() to return, I think win32_async_check() needs to run a message pump. Given that the whole PostThreadMessage() mechanism is too brittle for GUI threads anyways (you cannot avoid losing messages), I doubt anyone is using it while also embedding Perl. While looking at this issue I noticed that even though we are using a message-only window on Windows 2000 and later, we are not actually expecting anybody else to dispatch the messages to a wndproc; we always try to snatch them out of the queue via PeekMessage(). So we still inherit the brittleness of the PostThreadMessage() mechanism. I'll see if I can come up with a patch for both issues some time later next week. Cheers, -Jan PS: Please let me know if you happen to know a mechanism to create a message-only window on 98/NT (a window that is not top-level and will not receive broadcast messages). If this were possible, then we could get rid of PostThreadMessage() completely. |
From: Robert M. <rob...@us...> - 2007-07-28 23:34:27
|
On Sat, 28 Jul 2007, Robert May wrote: > Here's what happens - the call to system, or using backticks, makes a > request to the OS to find the program associated with *.html files, > launch it (if it isn't already running) and ask it to open the html > file. > > As part of the process of finding out if there is already a running > program of the right type the OS may attempt (depending on the program > and it's associated registry values) to use a technique called DDE - > if it does try this mechanism, the in broadcasts a WM_DDE_INITIATE > message to every top-level window in the system, and waits for each > one to reply. In this case we have a top-level window ($main), and so > the system sends this message to our top level window, but because we > are not in a message loop we never respond, and the system has to wait > for a timeout (typically about 30 seconds). > > The code in perl behind the system call *should* be handling > WM_DDE_INITIATE messages, but is not (at least not in the version of > perl you are running) > > There are 2 ways that I can see to resolve this for now. > (1) As I already suggested do 'undef $main' before making the shell > call - this destroys our window so we no longer have a top level > window. > (2) Use ShellExecute, which spins its own internal message loop until > the DDE initialisation is complete. Something like this: > $main->ShellExecute("", "temp.html", "", "", SW_SHOW); On 28/07/07, Jan Dubois <ja...@ac...> wrote: > This does not sound plausible to me: system("start foo.html") will > end up calling CreateProcess() on command.com/cmd.exe because start > is an intrinsic shell command and will not be found on the PATH. On Win98 it's not a shell buit-in, it's a command called start.exe. I'm not sure this affects things though. > CreateProcess() will return and not wait for command.com/cmd.exe to > initialize. Upon return win32_spawnvp() will call win32_msgwait(), > which should continue to pump the message loop until the external > process ends. That's what's supposed to happen, but in AS build 819 on win98 (that's all I have access to this weekend), I have to change the flags to MsgWaitForMultipleObjects from QS_ALLEVENTS to QS_ALLEVENTS|QS_SENDMESSAGE to get it to pump the sent WM_DDE_INITIATE message. Further to this, in bleed and AS build 820 we changed the flags to MsgWaitForMultipleObjects from QS_ALLEVENTS to QS_POSTMESSAGE|QS_TIMER. This won't have improved things. Here's what I think happens: (1) the 'system' call results in a new process being started (either start.exe or cmd.exe depending on OS). The new process is not initialised by the time CreateProcess returns. (2) When CreateProcess returns win32_spawnvp calls into win32_msgwait to wait for the external command to finish. (3) the external command (whether start.exe or cmd.exe's builtin) passes what it has been asked to start - in this case something.html - to ShellExeculte() which in turn looks up the class key for .html in the registry. There it finds a ddeexec key, and so starts a DDE conversation. The first part of the DDE conversation is to broadcast a WM_DDE_INITIATE message to all top-level windows (As far as I can tell this is done with something like SendMessageTimeout(HWND_BROADCAST, ..... )) (4) If our process has a top level window, then that top level window is sent a WM_DDE_INITIATE message by the new external process, but win32_msgwait() is not pumping sent messages, and so our process does not respond, and there is a delay while the external process times out waiting for us. The worst thing about this is that if we are in a long-running "system" call, and have a top-level window, then we will cause delays to *any* other DDE communications. Try running this: #!perl -w use strict; use warnings; use Win32::GUI(); my $mw = Win32::GUI::Window->new; system "notepad.exe"; And while notepad is still open, double-click an html file on your desktop - you'll get a 30 second delay before your browser shows the page. > But even if it didn't, the "start" command is just a commandline > interface to the ShellExecuteEx() function called from cmd.exe, > so it wouldn't be any different from your solution (2) above. It is different. ShellExecute spins a message-loop in the thread from which it is called. In the case of using the start command the ShellExecuteEx() is called in the context on the newly created process, and spins a message loop in the newly started thread. In my example the call to ShellExecute() is in the perl process, and so spins it's message loop within the perl main thread, which is where we need a message loop to pump the received WM_DDE_INITIATE message. I'm at a bit of a disadvantage not having a Win2K machine to hand to check this thoroughly (I'll try to do that on Monday or Tuesday). I'm not sure that I entirely understand the implication of adding QS_SENDMESSAGE to win32_msgwait. I think it only affects cross-process and cross-thread sent messages (as all intra-process sent messages get dispatched directly to the windproc for the window). Regards, Rob. |
From: Jan D. <ja...@ac...> - 2007-07-28 20:56:15
|
On Sat, 28 Jul 2007, Robert May wrote: > Here's what happens - the call to system, or using backticks, makes a > request to the OS to find the program associated with *.html files, > launch it (if it isn't already running) and ask it to open the html > file. > > As part of the process of finding out if there is already a running > program of the right type the OS may attempt (depending on the program > and it's associated registry values) to use a technique called DDE - > if it does try this mechanism, the in broadcasts a WM_DDE_INITIATE > message to every top-level window in the system, and waits for each > one to reply. In this case we have a top-level window ($main), and so > the system sends this message to our top level window, but because we > are not in a message loop we never respond, and the system has to wait > for a timeout (typically about 30 seconds). > > The code in perl behind the system call *should* be handling > WM_DDE_INITIATE messages, but is not (at least not in the version of > perl you are running) > > There are 2 ways that I can see to resolve this for now. > (1) As I already suggested do 'undef $main' before making the shell > call - this destroys our window so we no longer have a top level > window. > (2) Use ShellExecute, which spins its own internal message loop until > the DDE initialisation is complete. Something like this: > $main->ShellExecute("", "temp.html", "", "", SW_SHOW); This does not sound plausible to me: system("start foo.html") will end up calling CreateProcess() on command.com/cmd.exe because start is an intrinsic shell command and will not be found on the PATH. CreateProcess() will return and not wait for command.com/cmd.exe to initialize. Upon return win32_spawnvp() will call win32_msgwait(), which should continue to pump the message loop until the external process ends. But even if it didn't, the "start" command is just a commandline interface to the ShellExecuteEx() function called from cmd.exe, so it wouldn't be any different from your solution (2) above. Of course all bets are off if you have a start.exe/start.com on the PATH. > [Jan, I don't know if you read all the messages to this list, but know > you are subscribed - I'll follow-up to P5P with a report (and patch?)] I only browse the subject lines. Please CC me explicitly if you want to make sure I read a particular message. Cheers, -Jan |
From: Robert M. <rob...@us...> - 2007-07-28 19:58:27
|
On 28/07/07, Robert May <rob...@us...> wrote: > On 28/07/07, Robert May <rob...@us...> wrote: > > In order to help me track this down, I'd like to get some information > > from as wide a set of perl versions and operating systems as possible, > > but I only have Win98 available to me right now. I'd appreciate it > > if as many people as possible could run the attached script, and reply > > to this message with the output. > > > > Looking forward to your feedback. Thanks to everyone for the very quick response. I was expecting Activestate builds 819 and 820 to hang for 30 secs or more on Win2K and WinXP. Seems I was wrong. Back to the drawing board. I may ask for help running some tests again soon. Thanks, Rob. |
From: Apu i. <apu...@ya...> - 2007-07-28 19:42:53
|
here you go Rob. Two different scenario. First when I have firefox open(1 sec), second when I have it closed (8 sec) (It does not find the file. i checked and it gets unlinked before firefox can display it.) D:\Documents and Settings\Administrator.APU-DESKTOP\Desktop>perl delay_bug.pl Perl Version: 5.008008 Build number: 819 OS name : Win2000Service Pack 4 Elapsed time: 1 D:\Documents and Settings\Administrator.APU-DESKTOP\Desktop>perl delay_bug.pl Perl Version: 5.008008 Build number: 819 OS name : Win2000Service Pack 4 Elapsed time: 8 -Apu --- Robert May <rob...@us...> wrote: > On 28/07/07, Robert May > <rob...@us...> wrote: > > In order to help me track this down, I'd like to > get some information > > from as wide a set of perl versions and operating > systems as possible, > > but I only have Win98 available to me right now. > I'd appreciate it > > if as many people as possible could run the > attached script, and reply > > to this message with the output. > > > > Looking forward to your feedback. > > This time with the script! > > Regards, > Rob. > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Splunk Inc. > Still grepping through log files to find problems? > Stop. > Now Search log events and configuration files using > AJAX and a browser. > Download your FREE copy of Splunk now >> http://get.splunk.com/> _______________________________________________ > Perl-Win32-GUI-Users mailing list > Per...@li... > https://lists.sourceforge.net/lists/listinfo/perl-win32-gui-users > http://perl-win32-gui.sourceforge.net/ ------------------------------ Apu Islam ( E Pluribus Unum) |
From: Robert M. <rob...@us...> - 2007-07-28 14:53:18
|
On 28/07/07, Robert May <rob...@us...> wrote: > In order to help me track this down, I'd like to get some information > from as wide a set of perl versions and operating systems as possible, > but I only have Win98 available to me right now. I'd appreciate it > if as many people as possible could run the attached script, and reply > to this message with the output. > > Looking forward to your feedback. This time with the script! Regards, Rob. |
From: Robert M. <rob...@us...> - 2007-07-28 14:49:23
|
All, We've had a recent thread discussing a delay in launching an external program after creating a Win32::GUI window. After some investigation I think this is a problem in perl, and not something we can do anything about in Win32::GUI. In order to help me track this down, I'd like to get some information from as wide a set of perl versions and operating systems as possible, but I only have Win98 available to me right now. I'd appreciate it if as many people as possible could run the attached script, and reply to this message with the output. On this machine I see: Perl Version: 5.008008 Build number: 819 OS name : Win98(2nd ed) A Elapsed time: 1 Looking forward to your feedback. Regards, Rob. |
From: Robert M. <rob...@us...> - 2007-07-28 14:11:21
|
On 26/07/07, Robert May <rob...@us...> wrote: > On 26/07/07, Marc N=FCrnberger <mar...@ar...> wrote: > > Hmmmm... I found a strange behavior after adding some "debugging" print= s. > > The delay occurs when the last command is executed. That `links.html` > > one. Everything works fine up to that point. But that's only the case > > when I use the GUI version. When using the console version that command > > runs without delay. Does somebody know why that occurs? > > I have no idea what might be causing that. I can't immediately see > how Win32::GUI could be at fault, but I am never surprised. OK, I think I can explain it now - and it looks like a problem with perl, and not Win32::GUI - I'll need do do a little bit more investigation, and if I'm right I'll work on a fix for perl. > I tried using > system "start temp.html"; > instead, and I see the delay you're taking about. I can get rid of > the delay by doing > undef $main; > before making the system call Here's what happens - the call to system, or using backticks, makes a request to the OS to find the program associated with *.html files, launch it (if it isn't already running) and ask it to open the html file. As part of the process of finding out if there is already a running program of the right type the OS may attempt (depending on the program and it's associated registry values) to use a technique called DDE - if it does try this mechanism, the in broadcasts a WM_DDE_INITIATE message to every top-level window in the system, and waits for each one to reply. In this case we have a top-level window ($main), and so the system sends this message to our top level window, but because we are not in a message loop we never respond, and the system has to wait for a timeout (typically about 30 seconds). The code in perl behind the system call *should* be handling WM_DDE_INITIATE messages, but is not (at least not in the version of perl you are running) There are 2 ways that I can see to resolve this for now. (1) As I already suggested do 'undef $main' before making the shell call - this destroys our window so we no longer have a top level window. (2) Use ShellExecute, which spins its own internal message loop until the DDE initialisation is complete. Something like this: $main->ShellExecute("", "temp.html", "", "", SW_SHOW); I'll continue my investigation. Regards, Rob. [Jan, I don't know if you read all the messages to this list, but know you are subscribed - I'll follow-up to P5P with a report (and patch?)] |
From: Robert M. <rob...@us...> - 2007-07-27 19:45:16
|
On 27/07/07, Veli-Pekka T=E4til=E4 <vt...@ma...> wrote: > First of all, good to hear you are working on a TK-like layout manager. > I'm looking forward to its release. Don't hold you breath :-) Just because it's on my list doesn't mean that I'll get around to it. Of course, anyone else is free to write something and either release it themselves, or submit it for inclusion with Win32::GUI. > Although another great way to do > GUis would be to design them with the Visual Studio tools and then load > the resources in Win32::GUI. Is that supported, i.e. can I load plain > Win32 dialogs or menus and have Perl do the event handling? I suppose > not. It would be possible to make this work, but I believe that our target audience is primarily people who do not have access to the MS toolchain - so it's not something I'm likely to look at. > Is the Win32::GUI::MakeMenu() function documented as used by the Notepad > example in 1.03? I don't see it mentioned anywhere. I don't think so. Documentation patches are always welcome! > What's the difference between track bar and slider? i used the slider > and it works great. However, my screen reader and MSDN calls the control > a track bar. Most people I know talk casualy about sliderse or faders if > it is a mixer. MS call the control the TrackBar control in their documentation. Win32::GUI::Slider appears to be an alias for Win32::GUI::Trackbar - so I don't think there's a difference other than their name. > Also I had two initial problems with the slider control. I failed to > specify a size and was slightly disappointed that sliders cannot bundle > a label with the control like check boxes can. Chek boxes don't even > need their size specified. Would be nice if sliders had a default size, > too, though maybe this is a mishap in the underlying Win32 APi. What default size would you suggest for a slider? Like many of the controls there isn't really a natural default size, so Win32::GUI uses [0,0] if you don't provide one. Slider controls suooper a concept called 'buddy' windows - you can attach another window to the left/top or right/bottom (depending if the slider is horizonal or vertical). See the SetBuddy method. It works like this: #!perl -w use strict; use warnings; use Win32::GUI 1.05 qw(CW_USEDEFAULT); my $mw =3D Win32::GUI::Window->new( =09-title =3D> "Slider Demo", =09-size =3D> [400,300], ); my $slider =3D $mw->AddSlider( =09-pos =3D> [30,10], =09-size =3D> [100,30], =09-selrange =3D> 0, ); $slider->SetBuddy(1, $mw->AddLabel(-text =3D> 'Min')); $slider->SetBuddy(0, $mw->AddLabel(-text =3D> 'Max')); $mw->Show(); Win32::GUI::Dialog(); $mw->Hide(); __END__ > On a more general note, how do I specify the tab order in a dialog? Tab order is the same at the "z-order" of the child windows. Whenever a child window is created it is but at the end of the z-order list, and so by default the tab-order is the order of window creation. You can the z-order by using SetWindowPos() like this: $window_to_reorder->SetWindowPos($window_to_insert_after, 0 ,0 ,0 ,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIATE); > Last but not least, how do I indicate that a > group of radio buttons forms a radio control? Research the WS_GROUP window style, and use the -group option to set it. > Oh and before I forget: > I have an unusual keybord interface where I'd like a push button to be > pushed down while a key is hehld down and released on key up. How would > I go about this, are there key up / down events for buttons and how do I > programmatically push a button in stead of clicking it which means push > and release? Can I ignore keyboard messages that are a result of > Windows's key repeat when a key is held down? Generally unusual user-interface behaviour is a very bad idea. If you're sure that you want to proceed with this then from your description you're heading in the right direction. I don't immediately remember if Win32::GUI::Button's allow easy access to WM_KEYDOWN/WM_KEYUP messages, but you can always Hook() them. You want the $button->SetState(1) to programatically make the button look like it is pushed. Reagrds, Rob. |
From: Robert M. <rob...@us...> - 2007-07-27 19:22:58
|
On 27/07/07, a98...@gm... <a98...@gm...> wrote: > is it possible to show an icon within a menu? Not directly using Win32::GUI, but using Win32::API too ... I posted some code to the list a few months ago - I was going to give you a pointer to the list archive, but it appears that SF's search is broken again, so I attach it below. Regards, Rob. #!perl -w use strict; use warnings; use Win32::API(); Win32::API->Import('user32', 'SetMenuItemInfo', 'LILP', 'L') or die; Win32::API->Import('user32', 'SetMenuInfo', 'LP', 'L') or die; use Win32::GUI qw(CW_USEDEFAULT SM_CXMENUCHECK SM_CYMENUCHECK TRANSPARENT); use Win32::GUI::DIBitmap(); sub MIIM_BITMAP() {0x00000080} sub MIM_STYLE() {0x00000010} sub MNS_CHECKORBMP() {0x04000000} sub MNS_NOCHECK() {0x80000000} my $menu = Win32::GUI::Menu->new( 'Popup' => 'Popup', '>Item &1' => { -name => 'Item1', -onClick => sub { print "Item1\n"; 0; }, }, '>Item &2' => { -name => 'Item2', -onClick => sub { print "Item2\n"; 0; }, }, '>Item &3' => { -name => 'Item3', -onClick => sub { print "Item3\n"; 0; }, }, '>-' => 'Seperator', '>Item &4' => { -name => 'Item4', -onClick => sub { print "Item4\n"; 0; }, }, ); # Remove the reserved space for check marks - comment out this # line to see the effect of leaving the reserved space set_menu_info($menu->{Popup}->{-handle}); my @bitmaps; # we need to keep a reference to the bitmaps to stop them getting destroyed my $pos = 0; for my $color ( [255,0,0], [0,255,0], [0,0,255] ) { # ( Blue, Green, Red ) my $bmp = create_bitmap($color); set_menuitem_bitmap($menu->{Popup}->{-handle}, $pos++, $bmp->{-handle}); push @bitmaps, $bmp; } my $mw = Win32::GUI::Window->new( -left => CW_USEDEFAULT, -size => [400,300], -onMouseRightUp => \&context_menu, -onPaint => \&instructions, ); $mw->Show(); Win32::GUI::Dialog(); $mw->Hide(); exit(0); # Handler for onMouseRightUp event sub context_menu { my ($self) = @_; $self->TrackPopupMenu($menu->{Popup}); return 0; } # Set the bitmap for the menu item. We set by position, as in Win32::GUI I # can see no way to get the menu item identifier. # IN: handle to menu # position of item in menu (zero based) # handle to bitmap # OUT: returns true on success, die()s on failure sub set_menuitem_bitmap { my ($hmenu, $pos, $hbmp) = @_; # Create a MENUITEMINFO structure my $mii = pack( 'IIIIILLLLLIL', 12 * 4, # cbsize = sizeof(MENUITEMINFO) MIIM_BITMAP, # fMask = MIIM_BITMAP 0, # fType - unused 0, # fState - unused 0, # wID - unused 0, # hSubMenu - unused 0, # hbmpChecked - unused 0, # hbmpUnchecked - unused 0, # dwItemData - unused 0, # dwTypeData - unused 0, # cch - unused $hbmp, # hbmpItem ); my $r = SetMenuItemInfo($hmenu, $pos, 1, $mii); if ( $r == 0 ) { die qq(SetMenuItemInfo() failed: $^E); } return 1; } # Set the menu style so that we don't reserve space for checkmarks, # otherwise we have an extra gap to the left of the bitmap # IN: handle to menu # OUT: returns true on success, die()s on failure sub set_menu_info { my ($hmenu) = @_; # Create a MENUINFO structure my $mi = pack( 'LLLILLL', 7 * 4, # cbsize = sizeof(MENUITEMINFO) MIM_STYLE, # fMask = MIM_STYLE MNS_NOCHECK, # dwStyle (or MNS_CHECKORBMP if we want some items to # have checks and some to have bitmaps) 0, # cyMax - unused 0, # hbrBack - unused 0, # dwContextHelpID - unused 0, # dwMenuData - unused ); my $r = SetMenuInfo($hmenu, $mi); if ( $r == 0 ) { die qq(SetMenuInfo() failed: $^E); } return 1; } # Create a solid color bitmap of the correct size # IN: COLOR - array ref [ Blue, Green, Red ] # OUT: Win32::GUI::Bitmap sub create_bitmap { my ($color) = @_; my $cx = Win32::GUI::GetSystemMetrics(SM_CXMENUCHECK); my $cy = Win32::GUI::GetSystemMetrics(SM_CYMENUCHECK); my $dib = Win32::GUI::DIBitmap->new($cx, $cy); for my $y ( 0 .. $cy-1 ) { for my $x ( 0 .. $cx-1 ) { # Using array ref, as DIBitmap appears to have a bug with # passing a COLORREF value (0xBBGGRR). Note that when DIBitmap # uses an array ref the colors are in a different order to most # Win32::GUI usage of array refs for colors: BGR rather than RGB. $dib->SetPixel($x, $y, $color); } } my $bmp = $dib->ConvertToBitmap(); return $bmp; } # Handler for onPaint event sub instructions { my ($self, $dc) = @_; my $saved = $dc->Save(); $dc->Validate(); my ($l, $t, $r, $b) = $self->GetClientRect(); $dc->BkMode(TRANSPARENT); $dc->DrawText("Right-Click to see menu", $l, $t, $r, $b); $dc->Restore($saved); return 0; } __END__ |