1) How can I have a perl routine running as the master program with the 
Window just popping up as a dialog box and once I have modified the 
appropriate parameters, it just disappears and the command is given back to 
the background perl script ?
You can have any number of windows defined and controls added. A window only
shows after you issue the $Winvar->Show() method. After that, it just sits
on your monitor. If you want it to interact with the user, you either need
to go Win32::GUI::Dialog() once or Win32::GUI::DoEvents() periodically.

If you want to take a window off the screen and reuse it later, your
Window_Terminate event handler (subroutine) must not return -1. Returning 1
or -1 from _Terminate (should be any non-zero value, but in fact I found 2
to misbehave) destroys all your controls, even though they might still be
visible on the screen. Go $Winvar->Hide() and return 0 - preventing the
default action of destroying the window when control passes back from the
_Terminate event handler. To Hide() from elsewhere, return 1 - or don't
return at all. Later, you can simply Show() and Dialog() again. But see
below on how to end the message loop if you return 0 from _Terminate.

2) How can I pass control objects as parameters to the perl subroutines, if 
i wish to come up with a generic GUI of myy own being called as a 
subroutine from within the main perl program ?
You can create windows and their controls at any time. No problem creating
controls dynamically, even after the window has been on the screen, i.e.,
from within an event handler. In that case, have your _Terminate handler
return -1 and destroy the window. Next time you need another window, create
one. That does leak some memory, but nothing serious. If your program is
designed to run forever, you must get more inventive - reuse the window and
all the controls you ever needed, only hiding those you don't currently want
seen; for each new control check a hash to see which one to reuse and only
create another when there is none that fits and so on. But again, this
should not be necessary for a program with a reasonable running time.

3) Can I have two main windows open at a time ?
Yes. One Dialog() call (or a loop with one DoEvents() call) passes control
to the message loop - that is, all messages from all windows created within
this perl session and task get processed and the appropriate event handler
subs called. You just need to keep track of your termination: if you return
-1 from ANY event handler, the message loop terminates and control passes
back to your perl script after the Win32::GUI::Dialog() call. If you still
have another window, you need to call Dialog() again. If you don't have
another window and do Dialog(), your script hangs due to lack of events that
could terminate the message loop.

It is important to bear in mind how control is passed around, especially
with more than one window active or with your intention of showing and
hiding windows. Win32::GUI::Dialog() passes control to the message loop
(inside the Win32::GUI xs C++ code). From there, the event subs get called.
If one of them returns -1, the message loop returns and script execution
resumes after the Dialog() line. This clearly implies, if one of your event
handlers does a lot of lengthy stuff, your window appears to be frozen,
because control does not pass back to the xs and no other event subs get
called. There is an easy solution to this: call Win32::GUI::DoEvents() from
within the bit of script that runs so long. Even if it is from within the
event handler or a subroutine called from the event handler. The only trap
is, beware of re-entering the same bit of script. Here's an example:

# create window here
$button1_active = 0;
$return_value = 1;
Win32::GUI::Dialog();
print "done.\n";
exit;

Button1_Click
{
        return 1 if $button1_active;
# in case the user clicked on Button1 again
        $button1_active = 1;
        for (0..1000)
        {
                print "$_ ";
                Win32::GUI::DoEvents();
# this gives the user a chance to click Abort
                last unless $button1_active;
# quit loop if (s)he did
        }
        $button1_active = 0;
        return $return_value;
}
Abort_Click
{
        $button1_active = 0;
        return 1;
}
Window_Terminate
{
        Abort_Click();
# don't forget that or the loop continues after the window is closed and
destroyed
        $return_value = -1;     # this also returns -1 from the event sub!!
}

business as usual if the script was not running, because the implicit return
-1 destroys the window and stops the message loop, which was started by
Win32::GUI::Dialog().

If the script was running, control passes back out of the inner message
loop, which was started by Win32::GUI::DoEvents() inside the Button1_Click
handler. The perl loop there finds the flag $button1_active zero and
terminates. If this sub now would return 1 instead of the $return_value -1,
the outer message loop, invoked by Win32::GUI::Dialog(), would not terminate
- with the window already destroyed, because _Terminate did not return 0,
the script would effectively hang, receiving no more messages.

One more note: if you $Winvar->Hide() your window inside an event handler
and then start your "background" script (this would in fact be a foreground
script, because you only have one task here), your window would still be
visible. Call Win32::GUI::DoEvents() one more time after Hide() to have the
internal INVALIDATE and PAINT messages take the window off the screen. And
don't forget to Show() the window when your script finishes or you won't
receive any more messages except timer ticks - not even Window_Activate,
because you can't activate a hidden window.

Feel free to come back with more basic questions, but I won't usually sit
around with nothing else to do ;-)


Reply via email to