| Store | Cart

ActiveState Docs

PDK 6.0 Documentation

Loading...

Building a PerlCtrl

Control Building Overview

This covers the steps for building a control. It describes generating a template, and then modifying the code to suit your project.

Things Not to Disturb

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}',

Step 1: Generating the Template

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 6.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

Step 2: Adding the Code

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',

Step 3: Identifying the Control

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',

Step 4: Configuring Method Information

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'

Step 5: Configuring Property Information

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'

Step 6: Examining the Control Code

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

Step 7: Generating and Registering the DLL

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 6.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.

Step 8: Testing the Control

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 6.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

Testing the Association

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.