The Win32::GUI FAQ

Aldo Calpini, dada@perl.it
Erick Bourgeois, erick@jeb.ca 
Felix Gaehler, feli@freesurf.ch

v0.1, April 14, 2001

This is the "Frequently Asked Questions" for Perl Win32::GUI module. The questions and answers have been collected from the Win32::GUI-Users mailing list.


Important Notice: This is a first draft version of the FAQ. The document is not yet complete and the answers have not yet been verified.


General Questions

What is Win32::GUI?

"Win32::GUI is a Win32-platform native graphical user interface toolkit for Perl. Basically, it's an XS implementation of most of the functions found in user32.dll and gdi32.dll, with an object oriented Perl interface and an event-based dialog model that mimic the functionality of visual basic. It was a big fun for me to put it up, hope it will be a fun for you too :-)"

Where can I get Win32::GUI?

The creator and chief maintainer of the Win32::GUI module is Aldo Calpini. The module and pertinent information can be found at http://dada.perl.it/.
"The module is actually in beta testing so be warned that syntax and behavior can change with future builds; and of course, that there are many incomplete parts, sparse documentation (you can browse here the work in progress), and generally a lot of things to do."

Win32::GUI for ActiveState Perl 5.6 can be downloaded from the ActiveState Archive using ppm:

  ppm install Win32::GUI

Documentation is available at

  http://dada.perl.it/gui_docs/gui.html

  http://www.jeb.ca/howto/The_Win32-GUI_HOWTO.html

What about licensing?

If I develop a product in Perl with usage of the Win32::GUI module, and I spread (well lets asume for FREE) to the public.. is it still under GNU license or do we have to pay the win32::gui team something ?

"No, you don't have to pay anything. I'm not a lawyer and I don't want to pay a lawyer :-) Win32::GUI is released under the Artistic License, eg. you can redistribute it under the same terms of Perl itself."


Frequent Problems

Why does my window seem to freeze when my program is in a loop?

I can help here. Put a call to DoEvents() inside the loop. this will ensure that all queued messages are processed before going on with the loop:

    Textfield->change(-text "Processing...");    $$$verify
    foreach $line () {
        $Window->DoEvents();
        # body of the loop...
    }
    Textfield->change(-text "completed");

This will, of course, make your loop run slightly slower (almost irrelevant if there is no activity on the window). But there is the advantage (other than having the Textfield saying "Processing...") of being able to stop the loop in the middle by killing the window, or with a 'dedicated' stopbutton, for example.

Can I use a window handle in more than one process?

If you run some lengthy processing like web page retrieval with LWP, database search, file processing etc, and you cannot call $Window->DoEvents() within that processing, your window will seem to freeze during your processing. The solution to that is, to do the processing in a separate Windows thread or process. ActivePerl 5.6 simulates the "fork" command using Windows threads.

"Well, from Windows point of view, it is a thread. From Perl's point of view, it is a process. The Perl interpreter is busily keeping the data separate between the two threads (I'm not sure I understand the complete technique of the magic that does that, but I'm sure it can be made to work because the Perl language doesn't expose "real" addresses (much))."

"On the other hand, the (Unix) model for "fork" is that the multiple processes (threads on Perl for Windows) start off with identical data/variables/file handles. And the Windows model for "windows" is that the windows are owned by a process (not a thread), and can be accessed by any thread that has the window handle. (And in fact, because Windows was developed on DOS, the windows are even a bit visible to other processes, but that doesn't concern us here.)"

"By creating the Win32::GUI objects before forking, both the parent and child threads get copies (?) of the object variables. Because of the nature of Windows, the embedded Window handles inside both copies of the object variables are equally usable. Because of the (present) nature of Win32::GUI, whereby most of the parameter data is pumped into Win32 API parameters, and most of the return values are obtained by calling Win32 APIs to obtain it, I have shown experimentally that it is possible to use the Win32::GUI object references from both a parent and a child thread. Now it is important to remember that Windows only delivers window messages to the first thread of a program, so in the Perl "fork" environment, this gets translated to only the parent process of a group of Perl-forked processes can successfully run Win32::GUI::Dialog (Yep, I tried it the other way first, figuring that the parent could more easily monitor the child process for death, since fork returns the child pid, and waitpid works that way--but it just hung, and the windows never appeared). However, the child can use the object references created by Win32::GUI [before the fork] to access the "IsEnabled", "IsVisible" attributes of the window widgets, and they are dynamically updated (not cached in the object). The child can access the current selection from combo boxes. The child can enable and disable widgets, and the display gets updated appropriately. This is quite adequate for my application, which now can do its "long" operations in the child "process", and keep the GUI window "active" (except that certain parts get disabled during "long" operations)."

How can I use Win32::GUI functions in EVAL?

Yes, Win32::GUI supports things like these (it's really Perl that supports it :-), but you need to escape your window-handler variable $W:

    eval qq (
        sub main::$subtxt {
            print "button clicked\n";
            \$W->SimpleLabel->Text("Got a click");
        }
    );
    $@ or die "Error in eval: $@";   $$$verify
...and always check for $@ after an eval!

Text Fields

How can I change the background color of a text field?

To change the background color of a Richedit field, use

  Richedit->SendMessage(EM_SETBKGNDCOLOR, 0, hex('00FF00')); 

This sets the background color to green. Note that the hex() format for the color is expressed as BBGGRR (BB=blue, GG=green, RR=red).

Textfield does not support EM_SETBKGNDCOLOR. have you tried this:

  # change to red
  Textfield->Change( -background => [ 255, 0, 0 ] ); 
  # repaint the control
  Textfield->InvalidateRect(1);  

Note: Colors can now be given in the HTML notation too (eg. "#E3E2CC").

How can I get a vertical scrollbar in a textfield?

Add this option when you create the Textfield:
  -autovscroll => 1
This should do the trick.

How can I get the selected portion of a textfield?

There is a Selection method that returns the start and end of the selection. then you just make a substr on the Textfield content:

  ($from, $to) = $Textfield->Selection();
  $var = substr($Textfield->Text, $from, $to-$from);

How can I get the _Change event from a RichEdit control?

"I'd like to share a solution to a problem that has been driving me nuts for a while. I changed a Textfield control to a RichEdit and it would not give me the _Change event. I dug in the GUI.xs and could find nothing wrong. I finally tracked it down to the eventmask being zero, which means that the notification messages don't come to the GUI message loop in the first place. The workaround is to do

  $MainWindow->myRichEditField->SendMessage (0x445, 0, 1);

That sends EM_SETEVENTMASK (0x445) to the control with the ENM_CHANGE bit set. Hope that spares somebody else a headache."


ListView

How can I prevent the user from choosing more than one item in a Listview?

You can use the -singlesel option on the ListView to achieve what you want.

How can I display a popup menu within a ListView?

Here is an example how it can be done:

# define popup menu for listview
my $PopupMenu = new Win32::GUI::Menu(
    "Item Properties" => "ItemProp",
    ">&Properties" => "ItemProperties",
);
 
# get right-click in listview
sub DataView_RightClick {
   my($X, $Y) = Win32::GUI::GetCursorPos();
 
   $MainWindow->TrackPopupMenu($PopupMenu->{ItemProp},$X, $Y);
}
 
# clicked on particular menu item in popup menu
sub ItemProperties_Click {
   ## code you want to process;
}

MessageBox

What are the icon, button and modality values for MessageBox?

"I think these will work, I haven't tried them all.

Settings
=================================
0 - display only the OK button
1 - display OK and Cancel buttons
2 - display Abort, Retry, and Ignore buttons
3 - display Yes, No, and Cancel buttons
4 - display Yes and No buttons
5 - display Retry and Cancel buttons

16 - display Critical Message icon
32 - display Warning Query icon
48 - display Warning Message icon
64 - display Information Message icon

0 - set first button as default
256 - set second button as default
512 - set third button as default
768 - set fourth button as default

 
Return Values
=============
1 - OK
2 - Cancel
3 - Abort
4 - Retry
5 - Ignore
6 - Yes
7 - No"

Cursors

How can I change the cursor to hourglass and back?

$$$tbd (find out first...)


Extensions to Win32::GUI

Is there a spreadsheet (grid) look-a-like solution or component?

"No, but I'm thinking about implementing one (just thinking for now :-). "

Is there a inline webbrowser somewhere ? or a HTML or XML parser?

"No, and I don't think I will try to implement one :-) You should instead look at Win32::OLE, to see if you can embed an InternetExplorer instance in a window. That said, it seems that RichEdit 3.0 (available in Windows 2000) has a lot of nice features, that I'll try to implement if time permits."

Is there support for JPG or common image formats like .PNG or .GIF?

"Support is for .BMP files only. There is something in the Win32 API about JPGs, but I have not yet investigated it thoroughly."

$$$How to convert JPG and GIF to BMP in Perl (tbd)

Is there a Win32-GUI-Builder available (i.e. a visual aid in designing the GUI)?

yes, well.. at least a basic one. Download

  ftp://ftp.wh.whoi.edu/pub/gb109.zip
For more information, see in the Win32::GUI mailing-list, the mails from David Hiltz.

How can I deal with moving and resizing stuff when a window is resized?

"Dealing with moving and resizing stuff when a window is resized is really annoying, not to mention boring. So I created a class to make that easier. That was a lot more fun for some reason :) Anyway, the result is Win32::GUI::Resizer.

  http://www.bahnhof.se/~johanl/perl/Win32GUI/
Please try it out if you like and let me know what you think. "

$$$Source: mail from Johan Lindström, Sourcerer, Boss Casinos Ltd, Antigua, jpl@bosscasinos.com