From: Tom A. <to...@yt...> - 2001-02-28 21:16:56
|
With regards to fork() and Win32::GUI.... I have been playing with this as well, and while I have not arrived at a "best practices" I have arrived at a baseline that works. Basically, I fork the gui thread and then send window messages to it, or, call the appropriate function on the window object I want to manipulate in a "classless" way. For example, if you had created a progress bar control, you would normally call it using $progressControl->somefunction(); that is $progressControl->SetPos($amount); As it turns out, and I don't know if Aldo intended for it to work this way, if you have a handle to the control, you can also call the routine in the "classless" way by doing GUI::ProgressBar::SetPos($progressControlHandle,$amount)); The latter is the way I talk to the controls from the thread that is not running Win32::GUI::Dialog. Right now, I am locating the window handle for the dialog itself using GUI:FindWindow() in the non-gui thread. I'm not happy with this approach, and am looking at other solutions as well. Amine Moulay Ramdane's Win32::MemMap package (http://www.generation.net/~aminer/Perl/) looks like the right solution for this, at least for me, but I had a problem with it when I tried to use it and ran out of time to mess with it. I know he recently posted an updated version, I need to pull that down and see if it still has the same problem. My initial need was to not have to use GUI::FindWindow() to locate the dialog and controls. My thought was to serialize a hash in the gui thread and pass it back to the non gui thread via shared memory - which Win32::MemMap provides, and unserialize on the non gui side. You can probably do something similar with pipes, but for some reason, I thought that the shared memory approach looked better. I suspect that I've rambled on enough for one day. I've included in this message a script for a progress bar that runs in a thread by itself taking positioning commands from another thread. Oh, by the way, in response to another message on the list today, I think Win32::MemMap has a timer implementation in it. Wandering back to the real world..... --- Tom Tom Allebrandi to...@yt... #! perl -w ############################################################################ #### ############################################################################ #### ## ## Subpackage ProgressBar ## ## package Ta2::UiHelpers::ProgressBar; require Exporter; @ISA = qw(Exporter); @EXPORT = qw( Create Destroy Set ); use Win32::GUI; use constant CW_USEDEFAULT => 0x80000000; # # Reserves ProgressBar in the main namespace for us (uhmmm...) # *ProgressBar:: = \%Ta2::UiHelpers::ProgressBar::; ############################################################################ #### # # Manifest constants # use constant TITLE_BAR_HEIGHT => 19; use constant WINDOW_BORDER => 3; use constant MARGIN => (7 - WINDOW_BORDER); ############################################################################ #### # # Create() # sub Create { # # Parameters # my ($title,$width,$height,$minValue,$maxValue) = @_; # # "Local" variables # my $handle = 0; my $i; my $pid; # # Fire off a thread to manage the window # $pid = fork(); if (!defined($pid)) { # # Failed to fork # warn("Failed to fork management thread for ProgressBar\n"); } elsif ($pid == 0) { # # We are continuing in the child. Do the progress bar # doProgressBar($title,$width,$height,$minValue,$maxValue); exit(0); } else { # # We are continuing in the parent. Wait for the window to appear but # wait no more than 30 seconds # $i = 0; while (($handle == 0) && ($i < 30)) { # # Look for the window # if (($handle = GUI::FindWindow("",$title)) == 0) { # # Not found. Pause and try again # sleep(1); $i++; } } if ($handle == 0) { warn("Never saw the ProgressBar appear\n"); } } return($handle); } ############################################################################ #### # # Destroy() # sub Destroy { # # Parameters # my ($handle) = @_; # # Tell the window procedure to quit # # 0x8001 = WM_EXITLOOP = WM_APP+1 return(GUI::PostMessage($handle,0x8001,-1,0)); } ############################################################################ #### # # Set() # sub Set { # # Parameters # my ($handle,$amount) = @_; # # The progress bar is the first control on the dialog # $handle = GUI::GetDlgItem($handle,0); # # Set the new progress amount # # 1026 == PBM_SETPOS return(GUI::ProgressBar::SetPos($handle,$amount)); } ############################################################################ #### # # doProgressBar() # sub doProgressBar { # # Parameters # my ($title,$width,$height,$minValue,$maxValue) = @_; # # "Local" variables # my $progressControl; my $window; # # Create a dialog box to hold the progress bar # $window = new Win32::GUI::DialogBox( -text => $title, -left => CW_USEDEFAULT, -top => CW_USEDEFAULT, -width => $width, -height => $height, -name => 'Ta2::UiHelpers::ProgressBarDialog', -remstyle => WS_SYSMENU, -remexstyle => WS_EX_CONTEXTHELP); if (!defined($window)) { warn("Failed to create ProgressBar dialog\n"); goto ABORT; } # # Compute a good size for the progress bar control # $width -= (2 * MARGIN) + (2 * WINDOW_BORDER); $height -= TITLE_BAR_HEIGHT + (2 * MARGIN) + (2 * WINDOW_BORDER); # # Put the progress bar on the window # $progressControl = $window->AddProgressBar( -left => MARGIN, -top => MARGIN, -width => $width, -height => $height, -smooth => 1); if (!defined($progressControl)) { warn("Failed to create ProgressBar control\n"); goto ABORT; } # # Set the limits and the initial position # $progressControl->SetRange($minValue,$maxValue); $progressControl->SetPos($minValue); # # Put the display on the screen # $window->Show(); # # Activate the dialog # Win32::GUI::Dialog(); # # Take the display off of the screen # $window->Hide(); ABORT: if (defined($window)) { $window->DestroyWindow(); } } ############################################################################ #### # # Support routines # sub ProgressBarDialog_Terminate { return(-1); } ############################################################################ #### ############################################################################ #### ## ## Main program ## ## # # "Local" variables # my $i; my $pb; # # Create a progress bar # $pb = Create("A Progress Bar",200,100,0,30); # # Update it once a second for 30 seconds # for ($i=0;$i<30;$i++) { Set($pb,$i); sleep(1); } # # Take away the progress bar # Destroy($pb); exit(0); __END__ |