NAME

Win32::GUI::Loft Programmer's Reference -- how to incorporate The GUI Loft windows into your Perl programs (not utterly complete :)


INTRODUCTION

What is it?

Win32::GUI::Loft is the Runtime part of The GUI Loft.

The most important class is Win32::GUI::Loft::Design, which is used to build the designed windows at runtime. A few important methods are discussed below.


SYNOPSIS

Building a window you designed in The GUI Loft

        use strict;
        use Win32::GUI;
        use Win32 ();
        use Win32::GUI::Loft::Design;
        my $fileWindow = "fetch.gld";           #You created this using The GUI Loft
        my $objDesign = Win32::GUI::Loft::Design->newLoad($fileWindow) or
                        die("Could not open window file ($fileWindow)");
        my $win = $objDesign->buildWindow() or die("Could not build window ($fileWindow)");
        $win->Show();
        Win32::GUI::Dialog();

Loading the file yourself

This line

        my $objDesign = Win32::GUI::Loft::Design->newLoad($fileWindow) or
                        die("Could not open window file ($fileWindow)");

loads the Window from file. You can load the file yourself and build the window like this:

        my $fhIn;
        open($fhIn, "<$fileWindow") or die("Could not open file ($fileWindow)\n");
        binmode($fhIn);         #Note! It's a storable image
        local $/;
        my $code = <$fhIn>;
        close($fhIn) or die();
        my $objDesign = Win32::GUI::Loft::Design->newScalar($code) or
                        die("Could not build window file ($fileWindow)\n");

The newScalar() method may be used if you e.g. get the window definition (the contents of the $code variable in this example) from something other than a file; e.g. a database or a file handle. Remember to use binmode() if you read the file yourself.

Event handlers

        #The Name property of the loaded window is "winFetch"
        sub ::winFetch_Terminate {
                return(-1);
                }

Window controls

        #The -name of the button is "btnFetch"
        sub ::btnFetch_Click {
                #The Name property of the loaded window is "winFetch"
                defined(my $win = $Win32::GUI::Loft::window{winFetch}) or return(1);
                #There is another control (a Textfield) in the Design called "tfURL"
                my $url = $win->tfURL->Text();
                return(1);
                }


INSTALLATION

Required modules

Please make sure the following modules are present before installing the Runtime (see below):

        Win32
        Win32::API
        Win32::GUI

The easiest way to install the modules should be to run this from a command line:

C:\> ppm install MODULENAME

Note: So far as I understand, PPM packages are used only by the ActiveState Perl distribution, not e.g. the IndigoPerl distro. If you have any luck getting Win32::GUI (the window toolkit) to work with IndigoPerl, please let me know.

Win32::GUI::Loft is pure Perl, so a manual installation (or one using nmake which is the usual/preferred way) from the source should definitely be possible.

The Win32::GUI::Loft Runtime

The Runtime is a set of modules used in your programs to create the windows. You'll need to install the required modules and the Runtime before you try the Demo programs.

First install the required modules, then install the PPM packages found in the ``PPM'' directory. Run install.bat.

Note: You will need to run install.bat each time you download a new release! install.bat will remove, then reinstall the new modules.

The GUI Loft Application

There is a binary and a source distribution.

The binary is totally freestanding. Just run the program, and it should work.

The source relies on the Runtime, so install the PPMs first. The source is also dependent on the modules found in the Modules dir. Install them, then run the Perl file ``lib/tgl.pl''. If you still don't succeed, you'll see which modules are missing.


DEMOS

The Demo programs are located in the Demo directory. After you have installed the Runtime PPMs, just run the Perl scripts to see them in action.

The code is commented to point out interesting and important things, so a code walkabout could be educational.

Password

A simple demo of the Win32::GUI::Loft::Design class.

To demonstrate the timer, I chose to implement one very good user interface detail in some versions of the e-mail program Eudora; when Caps-lock is active, Eudora will warn the user that the password probably will get screwed up. The demo warns regardless of the Caps-lock state.

Things to learn from:

FetchURL

Enter a URL and Fetch will do a GET and display the HTTP headers and the raw HTML.

This is a great example of a quick GUI wrapper around a simple Perl program. A colleague asked if I knew how to see the HTTP response of a GET request.

-``Sure, that's a few lines of Perl''

Whining. -``Isn't there a Windows program to do that already?''

Well, fifteen minutes later, there was. And I spent most of that time trying to find the HTTP::Response method returning the HTTP headers (headers_as_string).

Things to learn from:

FileDisplay

Simple program to display files in a RichEdit control.

Things to learn from:

The GUI Loft

For real world examples, look in the Loft\resource directory. Here you can find the windows and dialogs used in The GUI Loft.

If you decide to experiment or change anyhing, it might be a sligthly clever idea to make a backup copy first. But you already knew that... ;)


BUILDING LOFT WINDOWS

The Demo programs

Until this section gets a little more complete, the best way to learn is to check out the code in the Demo programs.

It's not overly complicated, and the demos are nicely commented.

Building the Window

The -name of the Window

The Name property, and how to change it

Adding Menus

Adding a menu to your window is really simple.

Create the menu the usual way, create the Design object, then set the mnuMenu property before you actually build the window. An example from the FileDisplay demo program:

        my $fileWindow = "filedisplay.gld";
        my $objDesign = Win32::GUI::Loft::Design->newLoad($fileWindow);
        $objDesign->mnuMenu( Win32::GUI::MakeMenu(
                        "&File"                                         => "mnuFile",
                        " > E&xit"                                      => "mnuFileExit",
                        ) );
        my $win = $objDesign->buildWindow();

[Note: This example doesn't contain error checking. The demo program does.]

Other Loft::Design Methods


WIN32::GUI + LOFT WINDOWS

This section contains advice on how to do Win32::GUI coding with the windows you designed in The GUI Loft.

The %window hash

The %design hash

Clustered controls

There is a method rhClusterWingc() on your Design objects you can use to access the clusters and their controls.

$deisgn->rhClusterWingc() is a hash ref with (key = Cluster name, value = array ref (with Win32::GUI controls)).

        #Let's say your created window is called winTest
        defined(my $win = $Win32::GUI::Loft::window{winTest}) or return(1);
        my $design = $Win32::GUI::Loft::design{winTest};
        #Here are the clusters
        print join(", ", keys %{$design->rhClusterWingc()}) . "\n\n";
        #Display all clustered controls
        print Dumper($design->rhClusterWingc());


CUSTOMIZING THE BUILD PROCESS

If this is the first time you read the Programmer's Reference, I suggest you skim this section.

Inspecting and changing options

Each control can be altered at build time using a subclassed Win32::GUI::Loft::ControlInspector object. You can - addstyle, -remstyle, etc. and basically change the entire list of options passed to the AddXXX() method creating the control.

The Demo program FetchURL is an example of this, changing the background color of the window (to an ugly color... sorry), and adding a style to the window, making it a ToolWindow.

Study the method ``buildOptions'' in the FetchInspector.pm file for hints on how to do this.

Note that you might have to remove existing options before adding your own.

Some extracts from the Demo program:

        ### Creating the Win32::GUI::Window object,
        ### we use a ControlInspector object
        my $objInspector = FetchInspector->new() or die("Could not create Inspector}n");
        my $win = $objDesign->buildWindow(undef, $objInspector)
                        or die("Could not build window ($fileWindow)");
        ...
        ### Subclass the Win32::GUI::Loft::ControlInspector class
        package FetchInspector;
        use base qw( Win32::GUI::Loft::ControlInspector );
        ### Override tbe buildoptions method
        sub buildOptions { my $self = shift; my $pkg = ref($self);
                my ($objControl, $raOption) = @_;
                #Modify the main window
                if($objControl->prop("Name") eq "winFetch") {
                        #Create a class with a certain bg color
                        my $clsFetch = Win32::GUI::Class->new(
                                -name => "classFetchMisc",
                                -color => 2,
                                        ) or die("Could not create Class\n");
                        push(@$raOption, "-class" => $clsFetch);
                        #Add an extended style (to make it a toolwindow)
                        #
                        #(Note that you can do this from within The GUI Loft Editor,
                        #this is just to illustrate how to do this kind of thing)
                        push(@$raOption, "-addexstyle" => 0x00000080);          #WS_EX_TOOLWINDOW
                        }
                return(@$raOption);
                }

Custom controls

Custom controls is how you use Win32::GUI controls that aren't yet supported by The GUI Loft.

This is demonstrated by the demo program Add-Custom-Control. It's similar to how the options stuff (above) work in that you use an inspector object.

Custom properties

You can customize The GUI Loft by adding files to the ./resource/perl/ directory, which can contain custom perl code. All *.pm files in this directory will be ``require''d by The GUI Loft when starting up.

The most obvious use of this feature is to add new properties to controls in The GUI Loft that I haven't implemented yet, like the 0.0.668 features (e.g. Tip).

The provided example file ./resource/perl/test.pm adds the Tip property to the Button and Checkbox control. You can remove this file if you don't like it.

This is how to do it:

        $self->propertyAdd(Win32::GUI::Loft::ControlProperty->new(
                        "Tip", "", [], undef, ""));

Note: Adding something to the Win32::GUI::Loft::Control class will affect all controls.

Note: You can only add ``simple'' properties this way. ``Tip'' is added to the control with the option ``-tip => 'text'''. More complicated properties require actual coding.

The next section contains the complete documentation for the ControlProperty constructor. Use at your own risk.

Win32::GUI::Loft::ControlProperty

new($name, [ $value = undef, $raValue = [], $nameOption, $nameProperty = $name ])

Create new ControlProperty object.

        $name -- The name of the property. This will be
        displayed in the properties window. Die if $name isn't
        passed.
        $value -- The default value of this property. Default:
        undef
        $raValue -- Array ref with possible values for this
        property, e.g. [0, 1].
                An empty array means that any values are allowed.
                An array of scalars means that these values are
                allowed. The value will be set using a call
                to the nameProperty or using the nameOption.
                Example: [ "0", "1" ]
                An array with hash refs means: (key = the property
                value, value = the parameter value that will be
                passed to nameProperty or nameOption).
                Example: [ { "current" => 0 }, { "left edge" => 1, } ]
        $nameOption -- The option name for this property when
        creating the control. Default: the lowercase $name with
        a dash prepended. Example: "Align" -> "-align".
        $nameProperty -- The property name for this property,
        i.e. the method used to set/get the value. Default:
        $name.


DISTRIBUTION

When you create applications using Win32::GUI::Loft, you need to supply the modules somehow along with the Perl program.

The Runtime

Include the PPM files (including the required modules) in your distribution script, or point to The GUI Loft web site.

Using PerlApp et al

The GUI Loft binary is a PerlApp application, and so any program you write using Win32::GUI::Loft should work equally well in that regard.

This is actually a really handy little program, since it totally eliminates the deployment problem.

I haven't tried using Perl2Exe and other similar programs, but there are reports that at least Perl2Exe works well.

http://www.activestate.com/Products/Perl_Dev_Kit/

http://www.indigostar.com/perl2exe.htm


ON GUI CODING

What? No Perl Code?

Originally, I planned to have The GUI Loft generate Perl code to build the window in addition to have a runtime module create it. I have since abandoned that idea.

Why? There are certainly advantages with producing code:

However, there are a few disadvantages with exported code that need mentioning:

Use Window State

GUI vs. Application

Separate the specifics of your current GUI implementation from your application as much as possible.

Debug Events With Carp

Knowing Win32::GUI

The GUI Loft will shield you from code. That's good and bad.

It's good because you don't need to know everything about a subject to be able to use it, the same way you e.g. don't need to understand the finer points of the POP3 protocol to use Mail::POP3Client. That's reuse of code and knowledge. That's what will bring productivity gains.

But it's also bad, because The GUI Loft can only take you so far before you run into things that aren't implemented, or that fall outside the scope of the program. Then you have to do the difficult things yourself anyway (only with a solid base and a nice framework). But you still have to do the work.

So, study Win32::GUI code and learn how things are done. Use the help files under the Help menu. If you are going to use Win32::GUI then you'll have to know how it works. There is no way around that. And when the capabilities of Win32::GUI ends, you'll have to look at the Win32 API and Aldo's Win32::API module. Get used to it.

The Internals of Win32::GUI

If you're serious about Win32::GUI, I recommend a brief tour of GUI.xs and GUI.pm.

You'll get a better view of what's in there, and a few hints of what you need to look for in the Win32 docs. Armed with that, it's possible to do quite a lot of things that aren't fully supported by Win32::GUI (or just plain undocumented :)


RESOURCES AND DOWNLOADS

The docs - [ship them with a nice ToC]

The sample apps

Win32 SDK - donwload and online link

WINUSER.H ? Copyright on that one? :(

Other bookmarks

The mailing list + archive

Erick Bourgeois ``cookbook'' site


COPYRIGHT

Win32::GUI::Loft is Copyright (c) Johan Lindström, johanl@bahnhof.se

The Perl Artistic license applies.