This covers the steps for building a control. It describes generating a template, and then modifying the code to suit your project.
Notice the lines with the GUIDs, shown below. Never modify these lines.
The actual GUID values vary because PerlCtrl generates a unique value
each time it is run with the -t option:
# Do not edit the next three lines.
TypeLibGUID => '{478B3DC2-2E30-11D2-B46F-0800365DA902}',
ControlGUID => '{478B3DC3-2E30-11D2-B46F-0800365DA902}',
DispInterfaceIID=> '{478B3DC4-2E30-11D2-B46F-0800365DA902}',
To build a control, first run the PerlCtrl utility with the -t
command-line switch. This generates a Perl Control template that looks
similar to the HelloCtrl.pl sample file, which is located by default
in C:\Program Files\ActiveState Perl Dev Kit 7.x\Samples\HelloCtrl.
When you run PerlCtrl -t, it is helpful to redirect the output to a
filename, as in:
PerlCtrl -t > template.pl
The contents of template.pl are shown below. Notice that most of the
values are defaults and that there is no Perl code in the
MyPackage::MyName package. The output of PerlCtrl -t is merely a
guide for writing your own controls.
=pod
=begin PerlCtrl
%TypeLib = (
PackageName => 'MyPackage::MyName',
DocString => 'My very own control',
HelpFileName => 'MyControl.chm',
HelpContext => 1,
TypeLibGUID => '{76E36E16-BE3F-434D-8177-A118EC60BED6}', # do NOT edit this line
ControlGUID => '{356AC076-AA86-43C3-8982-E2B8BC0A2868}', # do NOT edit this line either
DispInterfaceIID=> '{16C94834-A727-4D6F-9AD3-32052BA3B567}', # or this one
ControlName => 'MyObject',
ControlVer => 1, # increment if new object with same ProgID
# create new GUIDs as well
ProgID => 'MyApp.MyObject',
LCID => 0,
DefaultMethod => 'MyMethodName1',
Methods => {
MyMethodName1 => {
DocString => "The MyMethodName1 method",
HelpContext => 101,
DispID => 0,
RetType => VT_I4,
TotalParams => 5,
NumOptionalParams => 2,
ParamList =>[ ParamName1 => VT_I4,
ParamName2 => VT_BSTR,
ParamName3 => VT_BOOL,
ParamName4 => VT_I4,
ParamName5 => VT_UI1 ],
},
MyMethodName2 => {
DocString => "The MyMethodName2 method",
HelpContext => 102,
DispID => 1,
RetType => VT_I4,
TotalParams => 2,
NumOptionalParams => 0,
ParamList =>[ ParamName1 => VT_I4,
ParamName2 => VT_BSTR ],
},
}, # end of 'Methods'
Properties => {
MyIntegerProp => {
DocString => "The MyIntegerProp property",
HelpContext => 201,
DispID => 2,
Type => VT_I4,
ReadOnly => 0,
},
MyStringProp => {
DocString => "The MyStringProp property",
HelpContext => 202,
DispID => 3,
Type => VT_BSTR,
ReadOnly => 0,
},
Color => {
DocString => "The Color property",
HelpContext => 203,
DispID => 4,
Type => VT_BSTR,
ReadOnly => 0,
},
MyReadOnlyIntegerProp => {
DocString => "The MyReadOnlyIntegerProp property",
HelpContext => 204,
DispID => 5,
Type => VT_I4,
ReadOnly => 1,
},
}, # end of 'Properties'
); # end of %TypeLib
=end PerlCtrl
=cut
You must add some code to the Perl control and choose what package you
want it to reside in. You must add this code before the =pod directive.
Then, update the PackageName element in the %TypeLib hash to specify
the package to which you added your code. Add the following code at the
beginning of template.pl:
package MyControl;
# Here's a simple property, implemented as a package variable:
#
our $name = "Vera";
# And another property, implemented with an accessor method:
#
my $lastname = "Jones";
sub last {
return $lastname unless @_;
$lastname = shift;
}
# Here's a method to issue a greeting.
#
sub Greet {
return "Hello, $name $lastname";
}
# Although we'll expose the name as a property, let's provide
# a method to set it, as well.
#
sub setName {
my $old_name = $name; # save the old name
$name = shift; # get the name the user specified
return $old_name; # return the old name
}
Next, change the PackageName element of %TypeLib to specify the
package in which you put the code:
PackageName => 'MyControl',
Now, give the control a name, a ProgId, and a version. Change the
ControlName to MyVeryOwnControl, leave ControlVer at 1, and change
ProgID to My.Control. ProgID is very important: it is the name used
to launch the Perl control. The updated section of %TypeLib should now
look like this:
ControlName => 'MyVeryOwnControl',
ControlVer => 1, # increment if new object with same ProgID
# create new GUIDs as well
ProgID => 'My.Control',
Next, configure the information about the methods to expose. There is a
Greet() method and a setName() method. Greet() is the
DefaultMethod, so you must set the method element to contain
information about these methods and their return values. You must set
the RetType, TotalParams (total number of parameters),
NumOptionalParams (total number of optional parameters), and ParamList
(a list of parameter names and types) for each method.
DocString and HelpContext are optional. They are used to associate a
topic in a compiled help file with the method.
See Linking to Compiled HTML Help
for more information.
DefaultMethod => 'Greet',
Methods => {
'Greet' => {
DocString => "The Greet() method",
HelpContext => 10,
RetType => VT_BSTR,
TotalParams => 0,
NumOptionalParams => 0,
ParamList =>[ ]
},
'setName' => {
DocString => "The setName() method",
HelpContext => 11,
RetType => VT_BSTR,
TotalParams => 1,
NumOptionalParams => 0,
ParamList =>[ 'name' => VT_BSTR ]
},
}, # end of 'Methods'
You must set the Properties element of %TypeLib. The entry from
%TypeLib is shown below. Specify the Type and ReadOnly value for
each property. Use the DocString and HelpContext elements to
associate properties with a page in a compiled help file:
Properties => {
'name' => {
DocString => "The name property",
HelpContext => 20,
Type => VT_BSTR,
ReadOnly => 0,
},
'last' => {
DocString => "The last property",
HelpContext => 21,
Type => VT_BSTR,
ReadOnly => 0,
},
}, # end of 'Properties'
Check the source code for MyControl.pl below. After making the changes to
the source that was generated by PerlCtrl -t, the source code should look
like this (except with different GUIDs):
package MyControl;
# Here's a simple property, implemented as a package variable:
#
our $name = "Vera";
# And another property, implemented with an accessor method:
#
my $lastname = "Jones";
sub last {
return $lastname unless @_;
$lastname = shift;
}
# Here's a method to issue a greeting.
#
sub Greet {
return "Hello, $name $lastname";
}
# Although we'll expose the name as a property, let's provide
# a method to set it, as well.
#
sub setName {
my $old_name = $name; # save the old name
$name = shift; # get the name the user specified
return $old_name; # return the old name
}
=pod
=begin PerlCtrl
%TypeLib = (
PackageName => 'MyControl',
DocString => 'My very own control',
HelpFileName => 'MyControl.chm',
HelpContext => 1,
TypeLibGUID => '{E4E91C9C-312D-11D2-B477-0800365DA902}', # do NOT edit this line
ControlGUID => '{E4E91C9D-312D-11D2-B477-0800365DA902}', # do NOT edit this line either
DispInterfaceIID=> '{E4E91C9E-312D-11D2-B477-0800365DA902}', # or this one
ControlName => 'MyVeryOwnControl',
ControlVer => 1, # increment if new object with same ProgID
# create new GUIDs as well
ProgID => 'My.Control',
DefaultMethod => 'Greet',
Methods => {
'Greet' => {
DocString => "The Greet() method",
HelpContext => 10,
RetType => VT_BSTR,
TotalParams => 0,
NumOptionalParams => 0,
ParamList =>[ ]
},
'setName' => {
DocString => "The setName() method",
HelpContext => 11,
RetType => VT_BSTR,
TotalParams => 1,
NumOptionalParams => 0,
ParamList =>[ 'name' => VT_BSTR ]
},
}, # end of 'Methods'
Properties => {
'name' => {
DocString => "The name property",
HelpContext => 20,
Type => VT_BSTR,
ReadOnly => 0,
},
'last' => {
DocString => "The last property",
HelpContext => 21,
Type => VT_BSTR,
ReadOnly => 0,
},
}, # end of 'Properties'
); # end of %TypeLib
=end PerlCtrl
=cut
To generate your control, run the following command (under Windows NT/2000):
PerlCtrl template.pl
The following output is displayed:
Created 'template.dll'
If you receive an error, carefully check the changes made to template.pl,
and fix any errors or typos. Then, run PerlCtrl template.pl again. If you
still get errors, compare your version of template.pl to the
MyControl.pl program provided in the MyControl subdirectory of the
Perl Dev Kit samples (by default
C:\Program Files\ActiveState Perl Dev Kit 7.x\Samples\PerlCtrl\MyControl).
Once you have generated the DLL, register it with the following command:
regsvr32 template.dll
A dialog box with the following text is displayed:
DllRegisterServer in template.DLL succeeded.
Click OK to dismiss the dialog.
Test MyControl using the VBScript program MyControl.vbs. It puts the
MyControl.dll sample through its paces. Before running MyControl.vbs,
generate a .dll from MyControl.pl using the following commands:
perlctrl MyControl.pl
regsvr32 mycontrol.dll
Additionally, you must compile the associated help file, and copy it to the same directory as the .dll using the commands shown below. The source files for the compiled help are located in the html directory beneath the MyControl directory (by default C:\Program Files\ActiveState Perl Dev Kit 7.x\Samples\PerlCtrl\MyControl).
hhc MyControl.hhp
xcopy MyControl.chm ..
The VBScript program that uses mycontrol.dll is shown below:
' Launch My.Control
'
Dim objMyControl
Set objMyControl = CreateObject("My.Control")
'
' Let's look at the name property.
MsgBox objMyControl.name, vbOKOnly, "Current value of MyControl.name."
'
' Let's issue a greeting to Vera.
MsgBox objMyControl.Greet
'
' Let's change the name to Chuck using a method.
objMyControl.setName("Chuck")
'
' Since Greet() is the default method, we don't need to specify
' it as the method name if we want to issue a greeting.
MsgBox objMyControl
'
' Change the name to Dave using the property and issue a greeting.
objMyControl.name = "Dave"
MsgBox objMyControl
You can test the associations between the control and the help file using either the ActivePerl Win32::OLE - Type Library Browser or the Microsoft VBA Editor. See the related sections of the User Guide for instructions.