Hi,

I've been putting together an example of several of the techniques I use when building a GUI. One of the things I do is to use lots of child windows to encapsulate many controls and functionality into one logical package. This works really well for me, but is still on the 'messy' side, so I've tried to encapsulate all functionality (event handling and method calls) into a single perl object that could be used throughout the application.

The example below is rather simple, but should explain the concept. In a hypothetical application, the user needs to be able to select the Employee ID in lots of places in the application. As well as being able to type in the ID directly, the user might also want to search for the ID. Rather than create lots of individual controls, an object does all the work for you...

Except for when you exit, and a crash occurs (perl 5.6 GUI 1.02 Attempt to free unreferenced scalar at C:/Perl/site/lib/Win32/GUI.pm line 3266). I do create a circular link, with a closure being used to 'remember the object (In my own application, the closure is of the window, not an object that contains it, and this doesn't crash). I'm not sure if this is a bug within win32-gui or my code?

Or is there a better way to create a perl object that can handle both method calls and events?

Thoughts?

Cheers,

jez.

---------------------
use strict;
use Win32::GUI;

#We init the EmployeeSelector class
EmployeeSelector::Init();

# Create the main window
my $mainwindow = new Win32::GUI::Window(
   -name   => "Window",
   -title  => "Objects and Windows",
   -pos    => [100,100],
   -size   => [400,400],
);
$mainwindow->Show();

#We now create several employee selector 'controls'.
my $search1=EmployeeSelector->new($mainwindow,20,20);
my $search2=EmployeeSelector->new($mainwindow,20,50);
my $search3=EmployeeSelector->new($mainwindow,20,80);
my $search4=EmployeeSelector->new($mainwindow,20,110);
my $search5=EmployeeSelector->new($mainwindow,20,140);
#Show all our controls
$search1->Show();
$search2->Show();
$search3->Show();
$search4->Show();
$search5->Show();
$search2->Move(200,200);

#Enter the message processing loop
Win32::GUI::Dialog();

package EmployeeSelector;
 #Class spefic globals
 my $searchwindow; #The search window
 my $active;       #The active object

sub Init {
 #This is a class function, and is used to initilise all objects
 $searchwindow = new Win32::GUI::DialogBox(
   -name   => "EmployeeSelector",
   -title  => "Search for Employee",
   -size   => [300,270],
 );
 $searchwindow->AddListView(
   -name => 'ListView',
   -pos    => [8,8],
   -size   => [280,189],
   -fullrowselect=> 1,
 );
 $searchwindow->AddButton (
   -name   => 'OK',
   -text   => 'OK',
   -pos    => [164,208],
   -size   => [60,21],
   #When we click ok, we populate the calling controls EmpID
   -onClick => sub {my $item=$searchwindow->ListView->SelectedItems();
                    my %hItem=$searchwindow->ListView->ItemInfo($item,0);
                    $active->SetEmpID($hItem{-text});
                    return -1;
                    },
 );
 $searchwindow->AddButton (
   -name   => 'Cancel',
   -text   => 'Cancel',
   -pos    => [228,208],
   -size   => [60,21],
   -onClick => sub {return -1},
 );
 #populate the list view
 $searchwindow->ListView->InsertColumn(-width => 55,-text  => 'Emp ID');
$searchwindow->ListView->InsertColumn(-width => 205,-text => 'Employee Name');
 $searchwindow->ListView->InsertItem(-text => [1234, 'Bob Smith']);
 $searchwindow->ListView->InsertItem(-text => [4321, 'Peter Jones']);
 $searchwindow->ListView->InsertItem(-text => [7890, 'John Brown']);
}

#The constructor
sub new {
 my $proto = shift;
 my $class = ref($proto) || $proto;
 my $self  = {};
 bless ($self, $class);
 my ($parent,$xcor,$ycor)[EMAIL PROTECTED];
 #Create window
 my $childwin = new Win32::GUI::Window (
     -parent      => $parent,
     -name        => "ChildWin",
     -pos         => [$xcor,$ycor],
     -size        => [150, 24],
     -popstyle    => Win32::GUI::WS_CAPTION | Win32::GUI::WS_SIZEBOX,
     -pushstyle   => Win32::GUI::WS_CHILD | Win32::GUI::WS_CLIPCHILDREN,
     );
 #add the window to the object
 $self->{win}=$childwin;
 #Create other controls
$childwin->AddLabel(
   -name   => 'Label',
   -text   => 'ID#',
   -height => 20,
   -width  => 20,
   -top    => 6,
   -left   => 0,
 );
 $childwin->AddTextfield (
   -name   => 'EmpID',
   -height => 20,
   -width  => 35,
   -top    => 2,
   -left   => 20,
   -tip    => 'Employee ID',
 );
 $childwin->AddButton (
   -name   => 'Search',
   -text   => 'Search',
   -height => 20,
   -width  => 60,
   -top    => 2,
   -left   => 60,
   -tip    => 'Search for a Employee  ID',
   #$self will become a closure
   -onClick => sub {Search($self)},
);
 return $self;
}

sub Search {
 #Open the search window - can be called as a method or as an event handler
 my $self=shift;
 #Set the active object to be this object
 $active=$self;
 $searchwindow->Center;
 $searchwindow->DoModal(1);
}

sub SetEmpID {
#Set the EmpID of the text box - can be called as a method or as an event handler
 my $self=shift;
 $self->{win}->EmpID->Text(shift);
}

sub Show {
 #Show the window
 my $self=shift;
 $self->{win}->Show();
}

sub Hide {
 #Hide the window
 my $self=shift;
 $self->{win}->Hide();
}

sub Move {
 #Move the window
 my $self=shift;
 $self->{win}->Move(@_);
}

sub DESTROY {
 #We have a circular link(?)
 my $self=shift;
 print 'in Destroy'.$self;
 $self->{win}=undef;
}



Reply via email to