From: Felix G. <fe...@fr...> - 2001-08-20 19:26:02
|
<HTML> <HEAD> <title>Win32::GUI FAQ</title> </HEAD> <BODY> <H1>The Win32::GUI FAQ</H1> <PRE>Aldo Calpini, da...@pe... Erick Bourgeois, er...@je...=20 Felix Gaehler, fe...@fr... v0.3, August 20, 2001 </PRE> <P><EM>This is the "Frequently Asked Questions" for Perl Win32::GUI = module. The=20 questions and answers have been collected from the Win32::GUI-Users = mailing=20 list. </EM> <HR> <H1>General Questions</H1> <H2>What is Win32::GUI?</H2> <P>"Win32::GUI is a Win32-platform native graphical user interface = toolkit for=20 Perl. Basically, it's an XS implementation of most of the functions = found in=20 user32.dll and gdi32.dll, with an object oriented Perl interface and an=20 event-based dialog model that mimic the functionality of visual basic. = It was a=20 big fun for me to put it up, hope it will be a fun for you too :-)"</P> <H2>Where can I get Win32::GUI?</H2> <P>The creator and chief maintainer of the Win32::GUI module is Aldo = Calpini.=20 The module and pertinent information can be found at <A=20 href=3D"http://dada.perl.it/">http://dada.perl.it/</A>. <BR>"The module = is=20 actually in beta testing so be warned that syntax and behavior can = change with=20 future builds; and of course, that there are many incomplete parts, = sparse=20 documentation (you can browse here the work in progress), and generally = a lot of=20 things to do."=20 <P>Win32::GUI for ActiveState Perl 5.6 can be downloaded from the = ActiveState=20 Archive using PPM:=20 <PRE> ppm install Win32::GUI </PRE> <P>Documentation is available at=20 <PRE> <A = href=3D"http://dada.perl.it/gui_docs/gui.html">http://dada.perl.it/gui_do= cs/gui.html</A> <A = href=3D"http://www.jeb.ca/howto/The_Win32-GUI_HOWTO.html">http://www.jeb.= ca/howto/The_Win32-GUI_HOWTO.html</A> </PRE> <H2>What about licensing?</H2> <P>If I develop a product in Perl with usage of the Win32::GUI module, = and I spread=20 (well lets assume for FREE) to the public.. Is it still under GNU = license or=20 do we have to pay the Win32::GUI team something ?=20 <P>"No, you don't have to pay anything. I'm not a lawyer and I don't = want to pay=20 a lawyer :-) Win32::GUI is released under the Artistic License, e.g. you = can=20 redistribute it under the same terms of Perl itself."=20 <HR> <H1>Frequent Problems</H1> <H2>Why does my window seem to freeze when my program is in a loop?</H2> <P>I can help here. Put a call to DoEvents() inside the loop. This will = ensure=20 that all queued messages are processed before going on with the loop: <PRE> use strict; use Win32::GUI; my $main =3D Win32::GUI::Window->new( -name =3D> "Main", -title =3D> "Win32-GUI: Doevents-Demo", -left =3D> 100, -top =3D> 100, -width =3D> 600, -height =3D> 400, ); sub Main_Terminate() { print "Main window terminated\n"; return -1; } my $textfield =3D $main->AddTextfield( -name =3D> "Textfield", -text =3D> "have fun and more", -left =3D> 75, -top =3D> 150, -width =3D> 200, -height =3D> 40, -readonly =3D> 1, ); $main->Show(); $textfield->Text("Processing infile..."); open INFILE, "<infile.txt" or die "open infile error: = $!"; my $linenr =3D 0; foreach my $line (<INFILE>) { $linenr++; $textfield->Text("Processing line $linenr"); <B>Win32::GUI::DoEvents() >=3D 0 or die "Window was closed = during processing";</B> sleep 1; #body of the loop... } $textfield->Text("completed"); Win32::GUI::DoEvents(); sleep 1; #program continues... </PRE> <P>This will, of course, make your loop run slightly slower (almost = irrelevant=20 if there is no activity on the window). But there is the advantage = (other than=20 having the Textfield saying "Processing...") of being able to stop the = loop in=20 the middle by killing the window, or with a 'dedicated' stopbutton, for = example.=20 <H2>Can I use a window handle in more than one process?</H2> <P>If you run some lengthy processing like web page retrieval with LWP, = database=20 search, file processing etc., and you cannot call $Window->DoEvents() = within=20 that processing, your window will seem to freeze during your processing. = The=20 solution to that is, to do the processing in a separate Windows thread = or=20 process. ActivePerl 5.6 simulates the "fork" command using Windows = threads.=20 <P>"Well, from Windows point of view, it is a thread. From Perl's point = of view,=20 it is a process. The Perl interpreter is busily keeping the data = separate=20 between the two threads (I'm not sure I understand the complete = technique of the=20 magic that does that, but I'm sure it can be made to work because the = Perl=20 language doesn't expose "real" addresses (much))."=20 <P>"On the other hand, the (UNIX) model for "fork" is that the multiple=20 processes (threads on Perl for Windows) start off with identical=20 data/variables/file handles. And the Windows model for "windows" is that = the=20 windows are owned by a process (not a thread), and can be accessed by = any thread=20 that has the window handle. (And in fact, because Windows was developed = on DOS,=20 the windows are even a bit visible to other processes, but that doesn't = concern=20 us here.)"=20 <P>"By creating the Win32::GUI objects before forking, both the parent = and child=20 threads get copies (?) of the object variables. Because of the nature of = Windows, the embedded Window handles inside both copies of the object = variables=20 are equally usable. Because of the (present) nature of Win32::GUI, = whereby most=20 of the parameter data is pumped into Win32 API parameters, and most of = the=20 return values are obtained by calling Win32 APIs to obtain it, I have = shown=20 experimentally that it is possible to use the Win32::GUI object = references from=20 both a parent and a child thread. Now it is important to remember that = Windows=20 only delivers window messages to the first thread of a program, so in = the Perl=20 "fork" environment, this gets translated to <B>only the parent process = of a=20 group of Perl-forked processes can successfully run = Win32::GUI::Dialog</B> (Yep,=20 I tried it the other way first, figuring that the parent could more = easily=20 monitor the child process for death, since fork returns the child pid, = and=20 waitpid works that way--but it just hung, and the windows never = appeared).=20 However, <B>the child can use the object references created by = Win32::GUI</B>=20 [before the fork] to access the "IsEnabled", "IsVisible" attributes of = the=20 window widgets, and they are dynamically updated (not cached in the = object). The=20 child can access the current selection from combo boxes. The child can = enable=20 and disable widgets, and the display gets updated appropriately. This is = quite=20 adequate for my application, which now can do its "long" operations in = the child=20 "process", and keep the GUI window "active" (except that certain parts = get=20 disabled during "long" operations)."=20 <H2>How can I use Win32::GUI functions in EVAL?</H2> <P>Yes, Win32::GUI supports things like these (it's really Perl that = supports it=20 :-), but you need to escape your window-handler variable $W:=20 <PRE> eval qq ( sub main::$subtxt { print "button clicked\n"; <B>\$W</B>->SimpleLabel->Text("Got a = click"); } ); $@ or die "Error in eval: $@"; $$$verify </PRE>...and always check for $@ after an eval!=20 <HR> <H1>Text Fields</H1> <H2>How can I get a vertical scrollbar in a textfield?</H2> Add these options when you create the textfield: <PRE> =20 -multiline =3D> 1 -autovscroll =3D> 1 </PRE>This should do the trick.=20 <H2>How can I get the selected portion of a textfield?</H2> <P>There is a Selection method that returns the start and end of the = selection.=20 Then you just make a substr on the Textfield content: <PRE> ($from, = $to) =3D $Textfield->Selection(); $var =3D substr($Textfield->Text, $from, $to-$from); </PRE> <H2>How can I get the _Change event from a RichEdit control?</H2> <P>"I'd like to share a solution to a problem that has been driving me = nuts for=20 a while. I changed a Textfield control to a RichEdit and it would not = give me=20 the _Change event. I dug in the GUI.xs and could find nothing wrong. I = finally=20 tracked it down to the eventmask being zero, which means that the = notification=20 messages don't come to the GUI message loop in the first place. The = workaround=20 is to do=20 <PRE> $MainWindow->myRichEditField->SendMessage (0x445, 0, 1); </PRE> <P>That sends EM_SETEVENTMASK (0x445) to the control with the ENM_CHANGE = bit=20 set. Hope that spares somebody else a headache."=20 <H2>How can I format text in a RichEdit control?</H2> <P>There is a SetCharFormat method to the RichEdit control. <PRE> $Rich->Select ($from_here, $to_there); $Rich->SetCharFormat (-color =3D> $flashy_pink) </PRE> To set the font at the beginning you can use: <PRE> my $Font =3D new Win32::GUI::Font( -name =3D> "Courier New",=20 -height =3D> 16, -bold =3D> 0, ); ### or the font/style of your choice... ### and then in your AddRichEdit use -font =3D> $Font </PRE> <HR> <H1>ListView</H1> <H2>How can I prevent the user from choosing more than one item in a=20 Listview?</H2>You can use the -singlesel option on the ListView to = achieve what=20 you want.=20 <H2>How can I display a popup menu within a ListView?</H2> <P>Here is an example how it can be done:=20 <PRE># define popup menu for listview my $PopupMenu =3D new Win32::GUI::Menu( "Item Properties" =3D> "ItemProp", ">&Properties" =3D> "ItemProperties", ); =20 # get right-click in listview sub DataView_RightClick { my($X, $Y) =3D Win32::GUI::GetCursorPos(); =20 $MainWindow->TrackPopupMenu($PopupMenu->{ItemProp},$X, $Y); } =20 # clicked on particular menu item in popup menu sub ItemProperties_Click { ## code you want to process; } </PRE> <HR> <H1>MessageBox</H1> <H2>What are the icon, button and modality values for MessageBox?</H2> <P>"I think these will work, I haven't tried them all.=20 <PRE>Settings =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D 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 =20 Return Values =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 1 - OK 2 - Cancel 3 - Abort 4 - Retry 5 - Ignore 6 - Yes 7 - No" </PRE> <HR> <H1>Cursors</H1> <H2>How can I change the cursor to an hourglass and back?</H2> <P>Basically, what you want is <PRE> Win32::GUI::SetCursor () </PRE> the tricky thing is to get the standard resource of the hourglass. Feel = free to use my perl module http://www.fairymails.com/perl/WinStRes.pm for = exactly this: (Notice: Win32::API must be installed) <PRE> Win32::GUI::SetCursor (WinCursor (WAIT)); # hourglass ... Win32::GUI::SetCursor (WinCursor ()); # ... and back </PRE> What this module does is <PRE> $LoadImage =3D new Win32::API ('user32', 'LoadImage', [N,N,I,I,I,I],N) or die 'can\'t find LoadImage function'; ... %cursors =3D ( 'NORMAL' =3D> 32512, 'IBEAM' =3D> 32513, 'WAIT' =3D> 32514, ... sub WinCursor { local $_ =3D $cursors{$_[0]} or $cursors{'NORMAL'}; return $LoadImage->Call (0, $_, 2, 0, 0, 0x8040); } </PRE> Example: <p>First download the module http://www.fairymails.com/perl/WinStRes.pm = and store it under the name 'WinStRes.pm' in the directory where you have your perl = program, or in the perl modules directory. Second, make sure Win32::API is installed, or install it using ppm. The perl program below now shows the hourglass cursor for two seconds = each time the button "search now" is clicked. <PRE> use strict; use Win32::GUI; #How to get the "wait cursor" resource. #Alternative 1, using the Win32::API module: use Win32::API; my $loadImage =3D new Win32::API ('user32', 'LoadImage', = ['N','N','I','I','I','I'],'N') or die 'cannot find LoadImage function'; my $waitCursor =3D $loadImage->Call(0, 32514, 2, 0, 0, 0x8040); #Alternative 2, using the WinStRes module (uses Win32::API) #use WinStRes; #download from = http://www.fairymails.com/perl/WinStRes.pm #my $waitCursor =3D WinCursor("WAIT"); my $main =3D Win32::GUI::Window->new( -name =3D> "Main", -title =3D> "Win32-GUI: Hourglass Cursor Demo", -left =3D> 100, -top =3D> 100, -width =3D> 600, -height =3D> 400, ); my $search =3D $main->AddButton( -name =3D> 'Search', -text =3D> 'search now',=20 -left =3D> 25, -top =3D> 25, ); sub Search_Click { print "Searching...";=20 <B>my $oldCursor =3D Win32::GUI::SetCursor($waitCursor); #show = hourglass ...</B> sleep 2; #do your search here print "done\n"; <B>Win32::GUI::SetCursor($oldCursor); #show previous arrow cursor = again</B> return 1; } sub Main_Terminate { print "Main Window terminated\n"; return -1; } $main->Show(); Win32::GUI::Dialog(); </PRE> <HR> <H1>Extensions to Win32::GUI</H1> <H2>Is there a spreadsheet (grid) look-a-like solution or = component?</H2> <P>"No, but I'm thinking about implementing one (just thinking for now = :-). "=20 <H2>Is there a inline webbrowser somewhere ? or a HTML or XML = parser?</H2> <P>"No, and I don't think I will try to implement one :-) You should = instead look at=20 Win32::OLE, to see if you can embed an InternetExplorer instance in a = window.=20 That said, it seems that RichEdit 3.0 (available in Windows 2000) has a = lot of=20 nice features, that I'll try to implement if time permits."=20 <p>So, I used the Win32:OLE example from Learning Perl on Win32:=20 <PRE> use Win32::OLE; my $browser =3D CreateObject OLE = "InternetExplorer.Application.1" || return 0; $browser->{'Visible'} =3D 1; $browser->Navigate("http://www.perlmonks.org/"); </PRE> This works fine, except I'm now forcing the user to use IE instead of = Netscape.=20 And it's possible (not likely I realize) that they don't even have IE. = So what happens then?=20 <p>To show an URL in the default browser of your PC, the Win32::Shell = helps. Win32::Shell can be downloaded from the Activestate archive using ppm. = It is not in CPAN at present (June 2001). <PRE> use Win32::Shell; $url =3D "http://www.perlmonks.org"; Win32::Shell::Execute("open", $url, undef, undef, = "SW_SHOWNORMAL"); </PRE> This starts the default browser opened to the correct URL, with no = delay, and no console window.=20 <H2>Is there support for JPG or common image formats like .PNG or = .GIF?</H2> Win32::GUI::DIBitmap add new reading/writing bitmap formats to = Win32::GUI and some images manipulations (Conversion, Screen capture, ...).<br> This package uses FreeImage 2.4.1, an open source image library = supporting all common bitmap formats (visit : <a = href=3D"http://www.6ixsoft.com/">http://www.6ixsoft.com/</a>). <p>Supports many formats, such as: <pre> Format Reading Writing Description. BMP Y Y Windows or OS/2 Bitmap ICO Y N Windows Icon JPEG Y Y JPEG - JFIF Compliant JNG Y N JPEG Network Graphics KOALA Y N C64 Koala Graphics IFF Y N IFF Interleaved Bitmap MNG Y N Multiple Network Graphics PBM Y Y Portable Bitmap (ASCII) PBMRAW Y Y Portable Bitmap (RAW) PCD Y N Kodak PhotoCD PCX Y N Zsoft Paintbrush PGM Y Y Portable Greymap (ASCII) PGMRAW Y Y Portable Greymap (RAW) PNG Y Y Portable Network Graphics PPM Y Y Portable Pixelmap (ASCII) PPMRAW Y Y Portable Pixelmap (RAW) RAS Y N Sun Raster Image TARGA Y N Truevision Targa TIFF Y Y Tagged Image File Format WBMP Y Y Wireless Bitmap PSD Y N Adobe Photoshop </pre> <h3>Current version : 0.03</h3> <p><a = href=3D"http://perso.club-internet.fr/rocherl/DIBitmap.html">DIBitmap</a>= : Win32::GUI::DIBitmap Docs<br> <a = href=3D"http://perso.club-internet.fr/rocherl/Win32-GUI-DIBitmap-SRC.zip"= >Win32-GUI-DIBitmap-SRC.zip (28 ko)</a> : Source Code and samples (You must download FreeImage = source code for build it, see Readme.txt)<br> <a = href=3D"http://perso.club-internet.fr/rocherl/Win32-GUI-DIBitmap-PPM-5005= .zip">Win32-GUI-DIBitmap-PPM-5005.zip (266 ko)</a> : PPM distribution for Active Perl 5.003 (see = Readme) <br> <a = href=3D"http://perso.club-internet.fr/rocherl/Win32-GUI-DIBitmap-PPM-56.z= ip">Win32-GUI-DIBitmap-PPM-56.zip (271 ko)</a> : PPM distribution for Active Perl 5.6 (see Readme) <p> For more information see <a = href=3D"http://perso.club-internet.fr/rocherl/Win32GUI.html">http://perso= .club-internet.fr/rocherl/Win32GUI.html</a> (email from Laurent Rocher Aug 20, 2001)</p> <H2>How can I deal with moving and resizing stuff when a window is = resized?</H2> <P>"Dealing with moving and resizing stuff when a window is resized is = really=20 annoying, not to mention boring. So I created a class to make that = easier. That=20 was a lot more fun for some reason :) Anyway, the result is = Win32::GUI::Resizer.=20 <PRE> <A = href=3D"http://www.bahnhof.se/~johanl/perl/Win32GUI/">http://www.bahnhof.= se/~johanl/perl/Win32GUI/</A> </PRE>Please try it out if you like and let me know what you think. = " (email from Johan Lindstr=F6m, Sourcerer, Boss Casinos Ltd, Antigua,=20 jp...@bo...)=20 <H2>Is there a Win32-GUI-Builder available (i.e. a visual aid in = designing the=20 GUI)?</H2> <P>yes, well.. at least a basic one. Download=20 <PRE> <A = href=3D"ftp://ftp.wh.whoi.edu/pub/gb109.zip">ftp://ftp.wh.whoi.edu/pub/gb= 109.zip</A></PRE> For more information, check the Win32::GUI mailing-list, the emails from = David Hiltz.=20 <p>Another one is the <b>GUI Loft</b> by Johan Lindstr=F6m. This is a = powerful and easy-to-use WYSIWYG editor for designing Win32::GUI windows, dialog boxes and toolwindows. It is = also a set of classes used=20 to create the window for you at runtime. <p> Download source and/or binaries here: <a = href=3D"http://www.bahnhof.se/~johanl/perl/Loft/"> http://www.bahnhof.se/~johanl/perl/Loft/</a> <p> The Perl Artistic License applies. <p> There is an extensive User Manual in the Help menu, please read it. But = try=20 the program first, you are programmers and power-users after all, right? = :) <p> Currently supported controls are: Window, DialogBox, ToolbarWindow, Button, Label, TextField, RadioButton, = CheckBox, GroupBox, Listbox, RichEdit, ListView, ComboBox, TreeView,=20 TabStrip, Timer, ImageList <p> Cool features include: <p>- Pretty extensive WYSIWYG support + 100% accurate preview <p>- Pretty complete support for Win32::GUI control options--and then = some <p>- It's actually easy to use (IMHO :) <p>- Docs and demo code <p>- No-code runtime TabStrip management <HR> </BODY></HTML> |