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
[EMAIL PROTECTED]
#! 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__