v5.0 / 13 of 23 / 01 sep 99 / gvg
* Three significant improvements were provided with VEE 5.X:
This chapter discusses these matters in detail
* ActiveX Automation is a relatively new scheme by which different Windows
programs can communicate with each other. It is conceptually similar to the
old Windows DDE scheme, but is much better implemented, being more robust,
faster, and better documented.
The worst problem with DDE was that the user generally had to play a guessing
game to figure out how to get it to work. There was usually no information
available to determine if an application was DDE compliant, and if it was
compliant, there was almost always little or no information on which commands
to use. The scheme was so poorly defined that guessing was impossible.
AxA is far more structured and better documented. When applications are
installed under Windows, they are "registered" as ActiveX Automation
applications, identifying them to all other Windows applications that can use
AxA. A user wishing to program VEE as an AxA "client" application that makes
use of another AxA "server" application can bring up a list of available
server applications, and enable one of these applications for use in VEE.
Then VEE has access to a list of the functions provided by the server
application. The VEE programmer can create formulas containing these
commands to access the other application, and also link to a help file
presumably provided by the vendor of the server application to get help on
the use of the commands.
AxA is an "object oriented" programming scheme that is defined by (and is
in fact a subset of a Microsoft spec known as "COM", for "Component Object
Model". From the viewpoint of VEE under AxA, the AxA server application
looks like a "COM object", and the interaction between client and server is
defined by sets of "properties", "methods", and "events".
Suppose, for example, VEE is being used to control a spreadsheet application
as an AxA server. The "properties" of the spreadsheet will be various
values assigned to it: for example, the name of the current spreadsheet
file. VEE will be able to use a property to both read that file name and
change that name.
The "methods" of the spreadsheet will be used to control actual actions of
the spreadsheet. For example, VEE will be able to save or load a spreadsheet
file by using the appropriate spreadsheet method.
The "events" of the spreadsheet allow the spreadsheet to inform VEE that
something unplanned as happened, an error in spreadsheet operation, for
example. However, the VEE program must specifically contain UserFunctions to
handle specific events.
The lists of properties, methods, and events provided by an application
define a command set that is specfically designed for that application.
While there may be similarities in syntax between application, VEE has no
inherent knowledge of what properties, methods, and events a specific AxA
application supports.
Note that the VEE 5.0 ActiveX Automation features allow it to act as a
client. As for server capabilities, in principle those were available in VEE
4.0 through the VEE ActiveX control. Unfortunately, the VEE ActiveX control
was largely unworkable. A better solution for server operation is planned
for the future.
* The tools provided by VEE for support of AxA are relatively simple in
concept.
To make use of AxA in VEE, the first thing to do is "reference" the
application and create an "instance" of an "object" for it. I went to the
"Device" menu and selected "ActiveX Automation References". This gave me a
dialog box that listed the available applications:
I then selected the "ActiveX Automation" category and the VEE "CreateObject"
function:
The "Result" of this function is a "handle" that will be used by VEE
functions that set properties or execute methods for that spreadsheet. As
with "CreateObject()", these are obtained with the Function & Object Browser:
An elementary property would be to make the spreadsheet visible. This can be
done with:
* ActiveX Controls are essentially third-party "widgets" that can be
integrated into any package that supports the protocol. Such widgets might
include specialized graphics objects (such as 3D charts or waterfall
diagrams), multimedia tools for video or audio presentation, statistical
analysis packages, interface libraries for data-acquisition cards, and so on.
Thousands are available as shareware or commercially.
ActiveX Controls are conceptually very similar to the Visual BASIC Extension
(VBX) controls that were available for Windows 3.X, but are 32-bit
implementations, not 16-bit implementations. Unlike VBX controls, they can
be used with many applications (as long as they are ActiveX compliant), not
just Visual BASIC.
As with ActiveX Automation, a VEE user can select among ActiveX Controls, and
having selected one can use formulas to access the control. While the
controls are part of the VEE program, they are not wired into the program as
such, since they don't obey VEE control flow rules, but they can be easily
controlled through formula boxes.
Note that if a user creates a VEE program using ActiveX Controls, the
libraries for the controls have to be shipped along with the program, under
the licensing arrangements defined by the vendor of the controls.
* For an example of how to use ActiveX Controls with VEE, I went out on the
Web to the CNET (www.cnet.com) to find some useful ActiveX Controls that I
could use for a demo.
I found an interesting shareware ActiveX control named Sysinfo, by a Jin Hui
of China. This provided some useful information ("properties") about a PC
like processor type, memory size and so on, and some useful actions
("methods") such as programmably rebooting the PC.
I unpacked the archive containing the Sysinfo control and got the ActiveX
Control for it, which was named "sysinfo.ocx", where ".ocx" was the extension
designating an ActiveX control. I then ran VEE 5.0 so I could play with this
control.
* The first thing to do in VEE was to "reference" the ActiveX control, or in
essence, make VEE aware of it. I went to the "Device" menu and selected
"ActiveX Control References". This gave me a dialogue box that listed the
available ActiveX Controls:
In any case, I was after the Sysinfo control. I found a Microsoft Sysinfo
control in the list, but this was different from and less useful than Jin
Hui's Sysinfo control, and so I had to click on "Browse" to reference that
item (as it had no installation program, obviously it was not going to be
identified in the Windows Registry). A file browser popped up, and I used it
to cruise through the file system to find and select "sysinfo.ocx".
The list now included "System Information Control". I set the flag to make
sure it was referenced, and then clicked on OK to close the dialog box.
* Next, I had to create an "instance" of the control in my program to play
with. I went to "Device" -> "ActiveX Controls" and selected "Sysinfo". I
got a VEE object labeled:
I could change this name to whatever I wanted, and if I created duplicate
instances of the control they would be given different names such as
"Sysinfo2", "Sysinfo3", and so on, that I could change as well. The names
were simply "handles" to the particular instance of the control.
* Once I had an instance of the control in the program I could then start
to make use of it by adding formula boxes containing the appropriate
properties and methods.
I clicked on the "fx" button on the VEE Toolbar and got the "Function &
Object Browser" dialog (which was named "Select Function" in its VEE 4.0
incarnation). I selected "ActiveX Objects" from "Type", then selected
"Sysinfo" from "Library", and got a list of the Sysinfo properties and
methods:
Anyway, selecting the "ComputerName" property (which gives the network name
of the computer) and clicking on "Create Formula" gave me the formula box:
That's not always the case, and many ActiveX Controls have "events"
associated with them, where a mouse click (or whatever) interrupts the
program. VEE has a mechanism for handling such events.
I was able to find a different control, the Microsoft Calendar control, that
had events and would be useful for a demo. I referenced the Microsoft
Calendar control, then got an instance of it, named:
In any case, this object -- not the Function & Object browser -- allowed
me to set up an event handler. I went to the object menu and selected the
menu entry "CreateEventHandler", and got the dialog box:
As a first step, I implemented the handler to simply pop up a panel to show
off the new date provided by the user, using the Calendar's properties as
obtained through the Function & Object Browser:
* It was easy to modify this program to allow the Event Handler to communicate
back to the main program. I eliminated the Panel View in the handler
UserFunction and changed it to put its text into a Global Variable named
"globalstat":
* VEE 5.0 has a simple means of interfacing to the World-Wide Web. You can
enable a simple HP VEE HTTP server that will allow inspection (though not
control) of a VEE program over the Web.
The VEE HTTP server supports a number of commands that are defined as Web
addresses (URLs). These commands take a "snapshot" of some element of the
VEE display (such as the Runtime window or a function panel) and send a
bitmap of it back to the Web surfer. Since as far as the Web is concerned,
these commands look like addresses, they are transparent to the Web and no
special knowledge of the VEE HTTP server is required.
* All you have to do to enable the VEE HTTP server is go to the VEE Default
Preferences configuration dialog box, and click on "Enable Server":
This page is built with standard Hypertext Markup Language (HTML) tags, with
the various commands used to access VEE implemented as extensions to the
Web server's URL:
[13.1] ACTIVEX AUTOMATION
[13.2] VEE & ACTIVEX CONTROLS
[13.3] VEE & THE WORLD-WIDE WEB
[13.1] ACTIVEX AUTOMATION
+----------------------------------------------------------+
| ActiveX Automation References |
+----------------------------------------------------------+
| Registered Automation Servers: |
| +----------------------------------------+ |
| |[ ] API Declaration Loader | [ OK ] |
| |[ ] Marquee Control Library | [ Cancel ] |
| |[ ] Microsoft ActiveX Plugin | |
| |[*] Microsoft Excel 8.0 Object Library | [ Browse... ] |
| |[ ] Microsoft Graph 8.0 Object Library | |
| |[ ] Microsoft Internet Controls | |
| |[ ] Microsoft Map | |
| |[ ] Microsoft Repository | [ Help ] |
| +----------------------------------------+ |
| |
| +- Microsoft Excel 8.0 Object Library -----------------+ |
| | Location: C:\Program Files\MS Office\Excel 8.0 | |
| +------------------------------------------------------+ |
+----------------------------------------------------------+
Having referenced the Excel 8.0 object library, I was then able to create an
instance of an object to deal with Excel. I went to the Function & Object
Browser (through the "fx" button on the iconic toolbar), and selected
"Built-in Functions" (not "ActiveX Objects").
+---------------------------------------------------------------------+
| Function & Object Browser [x]|
+---------------------------------------------------------------------+
| Type: Category: Member: |
| +-------------------------+ +--------------------+ +--------------+ |
| | Operators | | <All> | |*CreateObject | |
| |*Built-in Functions | |*ActiveX Automation | | GetObject | |
| | Local User Functions | | Array | | | |
| | Imported User Functions | | Bessel | | | |
| | Compiled Functions | | Bitwise | | | |
| | ActiveX Objects | | Calculus | | | |
| | | | Complex Parts | | | |
| | | | Data Filtering | | | |
| | | | Generate | | | |
| | | | Matrix | | | |
| +-------------------------+ +--------------------+ +--------------+ |
| |
| +-----------------------------------------------------------------+ |
| | CreateObject(objectName) | |
| | Creates a new instance of the object specified by 'objectname' | |
| | and returns a reference to it. | |
| +-----------------------------------------------------------------+ |
| |
+---------------------------------------------------------------------+
| [ Create Formula ] [ Cancel ] [ Help ] |
+---------------------------------------------------------------------+
This gave me the function:
+------------------------------------------------+
| CreateObject(objectName) |
+------------+--------------------------+--------+
| ObjectName | CreateObject(objectName) | Result |
+------------+--------------------------+--------+
Given the "CreateObject()" function, if we want to get an Excel spreadsheet,
we would then modify this as follows:
+---------------------------------------------------+
| CreateObject(objectName) |
+------------------------------------------+--------+
| CreateObject("Excel.Sheet").worksheet(1) | Result |
+------------------------------------------+--------+
While CreateObject is an inherent VEE function, the exact syntax of the
invocation used depends on the target application, in this case Excel.
+--------------------------------------------------------------------+
| Function & Object Browser [x]|
+--------------------------------------------------------------------+
| Type: Library: Member: |
| +-------------------------+ +--------------+ +-------------------+ |
| | Operators | |*Excel | | Application | |
| | Built-in Functions | | | | Creator | |
| | Local User Functions | | | | FullName | |
| | Imported User Functions | | | | Installed | |
| | Compiled Functions | +--------------+ | Name | |
| |*ActiveX Objects | Class: | Parent | |
| | | +--------------+ | Path | |
| | | | Addin | | | |
| | | | Addins | | | |
| | | | Adjustments | | | |
| +-------------------------+ +--------------+ +-------------------+ |
| |
| +----------------------------------------------------------------+ |
| | PROPERTY Application As Application | |
| | read-only | |
| +----------------------------------------------------------------+ |
| |
+--------------------------------------------------------------------+
| [ Create Formula ] [ Cancel ] [ Help ] |
+--------------------------------------------------------------------+
Note that the Help button at the bottom of the browser actually links to a
help file for the ActiveX Automation library associated with the selected
library. This help file will explain the "object hierarchy" associated with
the library, and provide instructions on usings its methods, properties, and
events.
+---------------------------------------------------+
| CreateObject(objectName) |
+------------------------------------------+--------+
| CreateObject("Excel.Sheet").worksheet(1) | Result +--+
+------------------------------------------+--------+ |
|
+---------------------------------------------------+
|
| +-----------------------------------------------+
| | Formula |
| +-----------+-----------------------------------+
+->| Worksheet | worksheet.application.visible = 1 |
+-----------+-----------------------------------+
[13.2] VEE & ACTIVEX CONTROLS
+----------------------------------------------------------+
| ActiveX Control References |
+----------------------------------------------------------+
| Registered Controls: |
| +----------------------------------------+ |
| |[ ] Acrobat Control For ActiveX | [ OK ] |
| |[ ] Callable VEE OLE Control Module | [ Cancel ] |
| |[ ] Microsoft ActiveX Plugin | |
| |[ ] Microsoft Calendar Control | [ Browse... ] |
| |[ ] Microsoft Comm Control | |
| |[ ] Microsoft Common Dialog Control | |
| |[ ] Microsoft HTML Intrinsic Controls | |
| |[ ] Microsoft Internet Transfer Control | [ Help ] |
| +----------------------------------------+ |
| |
| +- Acrobat Control For ActiveX ------------------------+ |
| | Location: C:\Acrobat\ActiveX\PDF.OCX | |
| +------------------------------------------------------+ |
+----------------------------------------------------------+
There was a long set of ActiveX controls available. Apparently the list was
derived from Windows Registry entries established when the applications that
incorporated the controls (like Visual BASIC) were installed. A sample
inspection of these controls showed some of them to be very specialized and
cryptic, and of no interest to a VEE user.
Sysinfo: Sysinfo1
Since this particular control didn't have a visual interface worth thinking
about, I turned it into its iconized form and left it that way. Essentially
the control simply declared the type, "Sysinfo", and the name of this
"instance" of the control in the program, "Sysinfo1", that I would need to
make use of it.
+--------------------------------------------------------------------+
| Function & Object Browser [x]|
+--------------------------------------------------------------------+
| Type: Library: Member: |
| +-------------------------+ +--------------+ +-------------------+ |
| | Operators | |*SysInfo | | ACOnLine | |
| | Built-in Functions | | | | BatteryLifeTime | |
| | Local User Functions | | | | BatteryPercent | |
| | Imported User Functions | | | | BatteryStatus | |
| | Compiled Functions | +--------------+ | BuildNumber | |
| |*ActiveX Objects | Class: | CDROM | |
| | | +--------------+ |*ComputerName | |
| | | |*SysInfo | | Disk | |
| | | | enumUnit | | DiskCacheSize | |
| | | | | | DiskDrive | |
| +-------------------------+ +--------------+ +-------------------+ |
| |
| +----------------------------------------------------------------+ |
| | ComputerName As Text | |
| +----------------------------------------------------------------+ |
| |
+--------------------------------------------------------------------+
| [ Create Formula ] [ Cancel ] [ Help ] |
+--------------------------------------------------------------------+
The list of properties and methods is at the right of the panel. Selecting
one gives a little documentation on the property at the bottom of the
display. Clicking on the "Help" button in principle gives access to the
complete help file, though this one was rudimentary.
+-----------------------------------------+
| SysInfo.ComputerName |
+---------+----------------------+--------+
| SysInfo | SysInfo.ComputerName | Result |
+---------+----------------------+--------+
I deleted the input pin and type the name of the object instance into the
formula field:
+--------------------------------+
| SysInfo.ComputerName |
+-----------------------+--------+
| SysInfo1.ComputerName | Result |
+-----------------------+--------+
Either way, running it gave my computer name, "HPLVLGVG". I then wrote a
program that used the following properties:
SysInfo1.ComputerName (HPLVLGVG)
SysInfo1.ProcessorType (Pentium)
SysInfo1.UserName (gvg)
SysInfo1.PhysicalMemory (32899072)
-- and then added a method, controlled by a Message Box, to reboot the
computer:
SysInfo1.ShutdownSystem()
* The SysInfo control had properties and methods associated with it, but it
had no need to interrupt the program using it. A program user couldn't punch
buttons or tweak widgets on it, since there weren't any.
Calendar.Calendar1
This provided a widget that looked like a little calendar. Note in passing
that this object has properties of its own that are independent of VEE, and
they can be accessed and controlled through the "Control Properties" entry in
the object menu.
+--------------------------------------------------------------------+
| Create Event Handler UserFunction [x]|
+--------------------------------------------------------------------+
| Type: Library: Member: |
| +-------------------------+ +--------------+ +-------------------+ |
| | ActiveX Objects | | MSACAL | | AfterUpdate | |
| | | | | | BeforeUpdate | |
| | | | | | Click | |
| | | | | | DblClick | |
| | | +--------------+ | KeyDown | |
| | | Class: | KeyPress | |
| | | +--------------+ | KeyUp | |
| | | | Calendar | | NewMonth | |
| | | | | | NewYear | |
| | | | | | | |
| +-------------------------+ +--------------+ +-------------------+ |
| |
| +----------------------------------------------------------------+ |
| | EVENT Void AfterUpdate() | |
| +----------------------------------------------------------------+ |
| |
+--------------------------------------------------------------------+
| "Calendar1_AfterUpdate" UserFunction will be created |
| |
| [ Create Handler ] [ Cancel ] [ Help ] |
+--------------------------------------------------------------------+
I selected "AfterUpdate" and indeed got an event handler:
+------------------------------------------------+
| Calendar1_AfterUpdate |
+------------------------------------------------+
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
+------------------------------------------------+
This handler is a UserFunction, but one with some odd restrictions. You
can't put input or output pins on it, and in most cases it won't be wired
into a program directly. The only way it can communicate with the rest of
the program is through global variables. It is essentially a self-contained
subprogram that is called when the event (in this case, any update to the
Calendar object) occurs.
+------------------------------------------------+
| Calendar1_AfterUpdate |
+------------------------------------------------+
| |
| +-------------------+ |
| | Formula | |
| +-------------------+ note use of multiline |
| | "New Date: " + | Formula box |
| | Calendar1.Day + | |
| | "/" + +------------+ |
| | Calendar1.Month + | | |
| | "/" + | +---------+---------+ |
| | Calendar1.Year | | AlphaNumeric | |
| +-------------------+ +-------------------+ |
| | | |
| +---------+---------+ |
| | |
| +--+--+ |
| | OK | |
| +-----+ |
| |
+------------------------------------------------+
I then set up a Panel View as follows:
+--------------------------+
| +--------------------+ |
| | AlphaNumeric | |
| +--------------------+ |
| | New Date: 3/5/1998 | |
| +--------------------+ |
| +-----+ |
| | OK | |
| +-----+ |
| |
+--------------------------+
I set this UserFunction to "Show Panel On Execute". I created a Main Program
consisting of an Until Break and ran that, then played with the Calendar
object. When I updated the day of the month, I got the pop-up.
+---------------------------------------------+
| Calendar1_AfterUpdate |
+---------------------------------------------+
| |
| +-------------------+ |
| | Formula | |
| +-------------------+ +--------------+ |
| | "New Date: " + | | Set Variable | |
| | Calendar1.Day + | +--------------+ |
| | "/" + +-->| globalstat | |
| | Calendar1.Month + | +--------------+ |
| | "/" + | |
| | Calendar1.Year | |
| +-------------------+ |
| |
+---------------------------------------------+
I then extended the main program as follows:
+--------+ +--------------+
| Text | | Set Variable |
+--------+ +--------------+
| NIL +-->| globalstat | "NIL" is default setting of global variable
+--------+ +------+-------+
|
+---+---+
| Until +-----------------+
| Break | |
+-------+ +------------+-------------+
| If/Then/Else |
+-------------------+------+
test for change in | globalstat!="NIL" | Then +--+
global variable | | Else | |
+-------------------+------+ |
|
+--------------------------------------+
|
+------+-------+ +---------------------+
| Get Variable | | AlphaNumeric |
+--------------+ +---------------------+
| globalstat +-->| New Date: 11/4/1900 |
+--------------+ +----------+----------+
|
+--------+---------+
| Formula |
+------------------+
reset global variable | globalstat="NIL" |
+------------------+
This scheme could be extended to handle other events.
[13.3] VEE & THE WORLD-WIDE WEB
+---------------------------------------------------------------+
| Default Preferences |
+---------------------------------------------------------------+
| +---------+--------+-------+--------+----------+------------+ |
| | General | Colors | Fonts | Number | Printing | Web Server | |
| +---------+--------+-------+--------+----------+ | |
| | +-[x] Enable Server ------------------------------------+ | |
| | | | | |
| | | Root Directory: [ C:\VEE\ ] | | |
| | | HTTP Port Number: [ 80 ] | | |
| | | Server Timeout: [ 60 ] | | |
| | | Log File [ C:\Temp\http.log ] | | |
| | +-------------------------------------------------------+ | |
| +-----------------------------------------------------------+ |
| |
+---------------------------------------------------------------+
| [ OK ][ Save ][ Reset ][ Cancel ][ Help ] |
+---------------------------------------------------------------+
Once this was done, I could then use the name of my PC -- "http://hplvlgvg"
-- as an address for my Web browser to access the VEE Web server that was
then installed. This default Web page looked like this:
+-------------------------------------------------------------------+
| |
| Remotely Monitoring A VEE Program |
| |
| Welcome to the HP VEE Web Monitor Home Page. You can remotely |
| monitor a VEE program by selecting a target view (such as VEE |
| Workspace or Execution Window) and then clicking on *View*. |
| _________________________________________________________________ |
| |
| Basic Monitoring |
| |
| To monitor a VEE program, select the desired item and press the |
| View button. |
| |
| +---------------------------------------------------------------+ |
| | Basic VEE Monitoring | |
| +---------------------------------------------------------------+ |
| | (*) VEE Workspace snapshot | |
| | ( ) VEE Workspace with [ ] second updates | |
| | ( ) Execution Window snapshot | |
| | ( ) Execution Window with [ ] second updates | |
| +---------------------------------------------------------------+ |
| [ View ] |
| |
| _________________________________________________________________ |
| |
| Advanced Monitoring |
| |
| To monitor a VEE program, select the desired item and press the |
| View button. |
| |
| +---------------------------------------------------------------+ |
| | Advanced VEE Monitoring | |
| +---------------------------------------------------------------+ |
| | ( ) Last Error Message | |
| | ( ) Main Panel | |
| | ( ) Main Detail | |
| | | |
| | ( ) Panel View of UserFunction [ ] | |
| | ( ) Detail View of UserFunction [ ] | |
| +---------------------------------------------------------------+ |
| [ View ] |
| |
+-------------------------------------------------------------------+
This default Web page shows off the capabilities of the VEE Web server, which
allows you to take bitmap snapshots of different VEE views, such as the VEE
Workspace, the Execution Window, error messages, main panel, the panel view
of a specified UserFunction, and so on.
see entire VEE window: http://<server>/ViewVEE
see main VEE panel: http://<server>/ViewMainPanel
see main program: http://<server>/ViewMainDetail
see Execution Window http://<server>/ViewExecWindow
see UserFunction panel: http://<server>/ViewPanel?<userfunction_name>
see UserFunction program: http://<server>/ViewDetail?<userfunction_name>
see last error message: http://<server>/ViewError
For example, to view the Execution Window of VEE on my pc, I could type the
following URL into my browser:
http://hplvlgvg/ViewExecWindow
If I wanted to get the Panel View of a UserFunction named "DataGen", I would
enter:
http://hplvlgvg/ViewPanel?DataGen
A user could build his or her own web page using these commands and standard
HTML codes.