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;
}