Home
New
Site Map
VB Examples
Visual Basic Example Intro
ODBC
Program Generator
COM
Client/Server and Web
TurboIMAGE
Calls from Win32
Guest Book
Email |
Using an ActiveX
Server-Side
Component with a Host-Based Application
The goal in this example is to take an arbitrary HP terminal-based application,
add a Visual Basic Graphical User Interface (GUI) to it and make it accessible
through a Web browser without changing even one line of application source
code. How is this possible? We can do it using an ActiveX dll server
component that manipulates the WRQ Reflection terminal emulator.
Figure 2.1 - Network View of Result
|

|
Figure 2.1 provides a network view of the results of our
objective. When we are done, the same application that is now accessible
using a terminal emulator will be accessible both through the Web or a PC using
a Visual Basic GUI client. It is important to note that we need to add a
middle tier server into our network to make this solution possible. In
this case we choose to use an NT server. However, any Windows 9X, NT or
Windows 2000 platform could be used.
Figure 2.2 - Software View of Result
|

|
Figure 2.2 shows how the solution we have in mind works from a
software component point of view. It is important to note that
absolutely nothing changes on the HP e3000. For the client/server
solution, we only need to add one copy of Reflection to the NT
server. For the Web solution we also need IIS 4.0 or higher on the NT
server. That's it!
On the PC that will serve as the GUI client, we need the free VB
runtime components. On the PC that will serve as the Web browser, we only
need a Web browser. In a real-world implementation of this solution we'd
only need one copy of Reflection to implement this solution and one login
connection the the HP e3000! In fact, if we work it right, we can have as
many users as we want make use of it. (This is a simple example and it has
some limitations that would have to be overcome before it became truly
multi-user.)
HP 3000 Demo
Application
A small VPlus application is used to implement our sample
solution. Its one screen is show in Figure 2.3.
Figure 2.3 - Demo VPlus Application
|

|
Implementing The
Solution
Implementing the solution we have in mind will take several
steps:
-
First, we let Reflection create most of a program to run the
Reflection session by capturing a Visual Basic program while running the
application.
-
Next, add the generated code to a new Visual Basic program
that will logon the the HP 3000 do our work and logoff.
-
We then change the Visual Basic program to an ActiveX (COM)
server dll component.
-
We then create a GUI client to test the COM component.
-
We then write an Active Server Page (ASP) module in Visual
Basic Script to use the or COM component on the Web.
-
Finally, we create an HTM page to invoke the ASP module.
Capture a
Reflection Visual Basic Module
The easiest way to integrate Reflection commands into a Visual Basic program
is to first record your actions in Reflection and save the file as a Visual
Basic code module. Next, add the module to your Visual Basic project and make
the modifications needed to integrate the Reflection commands into your Visual
Basic program. The following procedure provides a step-by-step description of
the process:
Record a Script in Reflection.
-
Start with a "fresh" copy of Reflection. Do not start with a
settings file (you may choose to load a settings file after you start
recording, though, as described in step 3. The recorded material will
contain the OLE commands that start Reflection (and load the settings file,
if needed). If Reflection is already running, you can reset to default
values and start fresh by closing any open connections, then choosing the
Defaults command from the Setup menu.
-
Choose the Start Recording command from the Reflection Script menu.
-
Perform the actions you want to record. This can include configuring
your connection or loading a settings file.
-
When you're done recording, choose the Stop Recording command from
the Script menu.
-
In the Stop Recording dialog box, enter a name in the File Name text box
and choose Visual Basic (*.bas) from the Save As Type list box.
-
Choose Save to save your file as a Visual Basic code module.
Add the Script to Your Visual Basic Project.
-
Start a new Standard.exe project file.
-
Choose Add File from Visual Basic's File menu, select the code module you
created in Reflection, and choose OK.
This adds the Visual Basic code module you recorded in Reflection to your
Visual Basic project.
-
Choose Add File from Visual Basic's File menu, add RWINAPI.TXT
from the Reflection directory as a module, and choose OK.
This adds the Reflection constant definitions to your Visual Basic project.
Click here for more information about this file.
-
Select the name of your Reflection code module from the Visual Basic
Project window, then choose View Code.
This opens the Visual Basic code module you recorded in Reflection. The
procedure that Reflection recorded is listed as "Main" in the
Procedure (or "Proc") list box. Since Visual Basic does not
require a Main procedure, you should change the name of this procedure to
something more descriptive. For example, if you recorded a logon script, you
might change the Main procedure to "ReflectionSession."
Figure 2.2 - Captured Reflection Visual
Basic Program
' Generated by the Reflection Script Recorder on 10-04-2000 17:48:22.14.
' Generated by Reflection for HP 6.00.
Option Explicit
Sub Main()
Dim Reflection As Object
Dim password1 As String
Const DIALOG_TITLE = "timeent"
Const NEVER_TIME_OUT = 0
Dim LF As String ' Chr$(rcLF) = Chr$(10) = Control-J
Dim CR As String ' Chr$(rcCR) = Chr$(13) = Control-M
Dim ESC As String ' Chr$(rcESC) = Chr$(27) = Control-[
LF = Chr$(rcLF)
CR = Chr$(rcCR)
ESC = Chr$(rcESC)
' Create a new instance of Reflection.
Set Reflection = CreateObject("Reflection1.Application")
' Use the statement below instead to attach to an existing instance of Reflection.
' Set Reflection = GetObject(, "Reflection1.Application")
' Normally the Reflection application will be visible while this script is running,
' and will remain open when this script terminates.
' Delete the following line if you want Reflection to be invisible and automatically closed.
Reflection.Visible = True
' Password was removed from this script for security.
password1 = ""
' Prompt for (what is assumed to be) a password.
password1 = Reflection.PasswordBox("ENTER ACCOUNT (XFORMIX) PASSWORD:", DIALOG_TITLE)
If password1 = "" Then Exit Sub
' Do not let Reflection process data communications between API calls.
Reflection.ProcessDatacomm = False
If Reflection.Connected = False Then
Reflection.ConnectionType = "BEST-NETWORK"
Reflection.ConnectionSettings = "Host class"
Reflection.ConnectionSettings = "DefaultNetwork VT-MGR"
End If
If Reflection.Connected = False Then
Reflection.Connect
End If
Reflection.StatusBar = "Waiting for Prompt: MPE/iX:"
Reflection.WaitForString "MPE/iX:", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit "hello mgr.xformix,rctest" & CR
Reflection.StatusBar = "Waiting for Prompt: ENTER ACCOUNT (XFORMIX) PASSWORD:"
Reflection.WaitForString LF & "ENTER ACCOUNT (XFORMIX) PASSWORD:", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit password1, rcDecodePassword
Reflection.Transmit CR
Reflection.StatusBar = "Waiting for Prompt: RCTEST.XFORMIX:"
Reflection.WaitForString LF & "RCTEST.XFORMIX: ", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit "timeentp" & CR
Reflection.StatusBar = "Waiting for Prompt: Sub Code :"
Reflection.WaitForString ESC & "b", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit "RJC"
' Press HpEnter (Simulate pressing the Enter key).
Reflection.TransmitTerminalKey rcHpEnterKey
Reflection.StatusBar = "Waiting for Prompt: Sub Code : R"
Reflection.WaitForString ESC & "b", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
' Press F8, labeled as EXIT
Reflection.TransmitTerminalKey rcHpF8Key
Reflection.StatusBar = "Waiting for Prompt: RCTEST.XFORMIX:"
Reflection.WaitForString LF & "RCTEST.XFORMIX: ", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit "EXIT" & CR
Reflection.WaitForString LF & "<Your 'VT-MGR' connection has terminated>" & CR & LF & LF, NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.CapsLock = False
' Resume normal data communications processing.
Reflection.ProcessDatacomm = True
End Sub
' Recording stopped at 17:50:20.07.
|
Notice that two lines at the top of the procedure have been included to
dimension a variable as an OLE Automation object, and then to create an instance
of the object for the specific Reflection product you're using. Other lines in
the procedure that call Reflection methods and properties are prefixed with the
name "Reflection" so they can reference the appropriate object.
Create a Visual
Basic Project
for the Generated Code
Figure 2.4 - Create a Visual Basic Project
 |
Figure 2.5 - Add the Reflection Created
Module
|

|
Figure 2.6 - Add the Reflection API module
|

|
Figure 2.7 - Module List from New Program
|

|
Figure 2.8 - Reference the Reflection Object
in the Project
|

|
Edit one line of code from the generated application.
'Set Reflection = GetObject(, "Reflection1.Application")
Set Reflection = CreateObject("Reflection1.Application")
Figure 2.9 - Run the Generated Application
from Visual Basic
|

|
At this point we have a Visual Basic program that runs a
Reflection session. We could add a graphical user interface to it and make
it a more attractive application. However, by changing it to an ActiveX
(COM) component we gain many more benefits. Some of those are the ability
to share an instance of Reflection between multiple users, the ability to share
a logon session on the HP e3000 and the ability to access the component over the
Web.
Before making our program into a COM component, we will divide
it's statements into logical groupings. The reasons for this
partitioning will become more obvious when we create our ActiveX implementation.
Partition the Visual
Basic Program
into Logical Subroutines
The generated Visual Basic program logically performs at least 3 different
functions; Logon, ProcessTimeRequest and Logoff. We next partition the
program statements into these three logical groupings and add a startup subroutine
to invoke them.
Figure 2.10 - Partitioned Program
' Generated by the Reflection Script Recorder on 10-04-2000 17:48:22.14.
' Generated by Reflection for HP 6.00.
Option Explicit
Dim Reflection As Object
Dim password1 As String
Dim searchAcct As String 'Text we're going to look for, find
Dim searchText As String 'Text we're going to look for, find
Const DIALOG_TITLE = "timeent"
Const NEVER_TIME_OUT = 0
Dim LF As String ' Chr$(rcLF) = Chr$(10) = Control-J
Dim CR As String ' Chr$(rcCR) = Chr$(13) = Control-M
Dim ESC As String ' Chr$(rcESC) = Chr$(27) = Control-[
Sub Logon()
LF = Chr$(rcLF)
CR = Chr$(rcCR)
ESC = Chr$(rcESC)
' Create a new instance of Reflection.
Set Reflection = CreateObject("Reflection1.Application")
' Use the statement below instead to attach to an existing instance of Reflection.
' Set Reflection = GetObject(, "Reflection1.Application")
' Normally the Reflection application will be visible while this script is running,
' and will remain open when this script terminates.
' Delete the following line if you want Reflection to be invisible and automatically closed.
Reflection.Visible = True
' Password was removed from this script for security.
password1 = ""
' Prompt for (what is assumed to be) a password.
password1 = Reflection.PasswordBox("ENTER ACCOUNT (XFORMIX) PASSWORD:", DIALOG_TITLE)
If password1 = "" Then Exit Sub
' Do not let Reflection process data communications between API calls.
Reflection.ProcessDatacomm = False
If Reflection.Connected = False Then
Reflection.ConnectionType = "BEST-NETWORK"
Reflection.ConnectionSettings = "Host class"
Reflection.ConnectionSettings = "DefaultNetwork VT-MGR"
End If
If Reflection.Connected = False Then
Reflection.Connect
End If
Reflection.StatusBar = "Waiting for Prompt: MPE/iX:"
Reflection.WaitForString "MPE/iX:", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit "hello mgr.xformix,rctest" & CR
Reflection.StatusBar = "Waiting for Prompt: ENTER ACCOUNT (XFORMIX) PASSWORD:"
Reflection.WaitForString LF & "ENTER ACCOUNT (XFORMIX) PASSWORD:", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit password1, rcDecodePassword
Reflection.Transmit CR
Reflection.StatusBar = "Waiting for Prompt: RCTEST.XFORMIX:"
Reflection.WaitForString LF & "RCTEST.XFORMIX: ", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit "timeentp" & CR
Reflection.StatusBar = "Waiting for Prompt: Sub Code :"
Reflection.WaitForString ESC & "b", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
' Add to make into a real program
Exit Sub
ErrorHandler:
' Check for properties er ror
If Err = 10000 Then
Reflection.MsgBox "This demonstration script was unable to modify one or more Reflection Properties", 48, "Logon Demo"
Exit Sub
End If
End Sub
' Recording stopped at 17:50:20.07.
Sub ProcessTimeRequest(searchAcct As String, returnCode As Integer, Result As String)
Reflection.Transmit "RJC"
' Press HpEnter (Simulate pressing the Enter key).
Reflection.TransmitTerminalKey rcHpEnterKey
Reflection.StatusBar = "Waiting for Prompt: Sub Code : R"
Reflection.WaitForString ESC & "b", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
' Press F8, labeled as EXIT
End Sub
Sub Logoff()
Call ProcessTimeRequest("dummy query", 0, searchText) ' Added
' Press F8, labeled as EXIT
Reflection.TransmitTerminalKey rcHpF8Key
Reflection.StatusBar = "Waiting for Prompt: RCTEST.XFORMIX:"
Reflection.WaitForString LF & "RCTEST.XFORMIX: ", NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.WaitForHostTrigger
Reflection.StatusBar = ""
Reflection.Transmit "EXIT" & CR
Reflection.WaitForString LF & "<Your 'VT-MGR' connection has terminated>" & CR & LF & LF, NEVER_TIME_OUT, rcAllowKeystrokes
Reflection.CapsLock = False
' Resume normal data communications processing.
Reflection.ProcessDatacomm = True
' Add to make into a real program and to terminate Reflection properly
Reflection.Quit
Set Reflection = Nothing
Exit Sub
ErrorHandler:
' Check for properties error
If Err = 10000 Then
Reflection.MsgBox "This demonstration script was unable to modify one or more Reflection Properties", 48, "Logon Demo"
Exit Sub
End If
End Sub
|
Creating a COM implementation of the program consists mainly of
adding a Class module with the right properties and methods that invokes the
module we already have. It is really this new Class that will provide the
required COM interface to the outside world.
Create an ActiveX
COM DLL Server
Figure 2.11 - Create a Class
|

|
Figure 2.12 - Code Generate By The Class
Builder
'local variable(s) to hold property value(s)
Private mvarQueryAccount As Variant 'local copy
Private mvarQReturnCode As Variant 'local copy
Private mvarQResult As Variant 'local copy
Public Sub QueryQServer()
End Sub
Public Sub StopQServer()
End Sub
Public Sub StartQServer()
End Sub
Public Property Let QResult(ByVal vData As Variant)
'used when assigning a value to the property, on the left side of an assignment.
'Syntax: X.QResult = 5
mvarQResult = vData
End Property
Public Property Set QResult(ByVal vData As Variant)
'used when assigning an Object to the property, on the left side of a Set statement.
'Syntax: Set x.QResult = Form1
Set mvarQResult = vData
End Property
Public Property Get QResult() As Variant
'used when retrieving value of a property, on the right side of an assignment.
'Syntax: Debug.Print X.QResult
If IsObject(mvarQResult) Then
Set QResult = mvarQResult
Else
QResult = mvarQResult
End If
End Property
Public Property Let QReturnCode(ByVal vData As Variant)
'used when assigning a value to the property, on the left side of an assignment.
'Syntax: X.QReturnCode = 5
mvarQReturnCode = vData
End Property
Public Property Set QReturnCode(ByVal vData As Variant)
'used when assigning an Object to the property, on the left side of a Set statement.
'Syntax: Set x.QReturnCode = Form1
Set mvarQReturnCode = vData
End Property
Public Property Get QReturnCode() As Variant
'used when retrieving value of a property, on the right side of an assignment.
'Syntax: Debug.Print X.QReturnCode
If IsObject(mvarQReturnCode) Then
Set QReturnCode = mvarQReturnCode
Else
QReturnCode = mvarQReturnCode
End If
End Property
Public Property Let QueryAccount(ByVal vData As Variant)
'used when assigning a value to the property, on the left side of an assignment.
'Syntax: X.QueryAccount = 5
mvarQueryAccount = vData
End Property
Public Property Set QueryAccount(ByVal vData As Variant)
'used when assigning an Object to the property, on the left side of a Set statement.
'Syntax: Set x.QueryAccount = Form1
Set mvarQueryAccount = vData
End Property
Public Property Get QueryAccount() As Variant
'used when retrieving value of a property, on the right side of an assignment.
'Syntax: Debug.Print X.QueryAccount
If IsObject(mvarQueryAccount) Then
Set QueryAccount = mvarQueryAccount
Else
QueryAccount = mvarQueryAccount
End If
End Property
|
Create a GUI
Client To Use The ActiveX Server
Figure 2.13 - GUI Client Screen
|

|
Figure 2.14 - Gui Client Code
Option Explicit
Private ResultBuffer As String
Private QueryBuffer As String
Private returnCode As Integer
Dim CR As String 'Carriage return
Dim LF As String 'Linefeed
Dim TimeServer As New TimeEntProj.TimeQuery
Private Sub cmdQuery_Click()
TimeServer.QReturnCode = 0
TimeServer.QueryAccount = UCase(txtAccount)
If TimeServer.QueryAccount <> "" Then
TimeServer.QueryQServer
txtReturnCode = TimeServer.QReturnCode
If TimeServer.QReturnCode = 2 Then
txtAccount = TimeServer.QueryAccount
txtResult = TimeServer.QResult
Else
txtMessage = "Invalid Account -- Please Renter"
End If
Else
MsgBox "Please Enter Account Number"
End If
End Sub
Private Sub Form_Load()
txtReturnCode = 0
TimeServer.StartQServer
CR = Chr$(13)
LF = Chr$(10)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set TimeServer = Nothing
TimeServer.StopQServer
End Sub
Private Sub cmdStop_Click()
Unload Me
End Sub
|
Create an Active
Server Page (ASP) Client To Use The ActiveX Server
Figure 2.15 - Active Server Page The Uses
COM Object
| <%@ LANGUAGE="VBSCRIPT" %> <%
Response.Buffer = true Dim bOK, strErrorDesc, strResultBuffer
Set TimeServer = Server.CreateObject("TimeEntProj.TimeQuery")
TimeServer.StartQServer TimeServer.QueryAccount =
Request.Form("txtAccountNum") Response.Write "Account
Number Entered: " & TimeServer.QueryAccount TimeServer.QResult =
" " TimeServer.QReturnCode = 0
bOk = TimeServer.QueryQServer
If bOk = 0 Then strResultBuffer = TimeServer.QResult
If bOk <> 0 Then strErrorDesc =" Error"
TimeServer.StopQServer Set TimeServer = Nothing
%>
<html>
<head> <title>Results</title> </head>
<body bgcolor="#FFFFFF">
<p>Here is the result of the Query: </p>
<p><a href="<%=Request.Form("txtResultCode")%>"><%=Request.Form("txtResultCode")%></a></p>
<% If bOk = 0 Then %> <p><textarea rows="5"
name="S1" cols="51"><%=strResultBuffer%></textarea></p>
<p>It worked!</p> <% Else Response.Write strErrorDesc End
If%>
</body> </html>
|
Figure 2.16 - HTML Form
<html>
<head>
<title>Testing Time Entry component</title>
</head>
<body bgcolor="#ffffff">
<form target="bottom" method="post" action=".\TimeQEnt.asp" name="frmTAX">
<p> Please Enter Your Account Number Below:</p>
<div align="left"><table border="0" cellpadding="0" cellspacing="5">
<tr>
<td align="right"> Account Number</td>
<td><input name="txtAccountNum" size="31" value="" >
</td>
</tr>
<tr>
<td align="right" colspan="2"><div align="center"><center><p><input type="submit"
value="Submit" name="B1"></p></center></div></td>
</tr>
</table>
</div>
</form>
</body>
</html>
|
Figure 2.17 - HTML Entry Screen
Uses ASP Page
 |
Installation and
Configuration
This example distribution comes in as a single
zip file. It contains installation components for both the HP e3000 and
the Windows computer.
Prerequisites
-
Both the HP e3000 and the PC must be reachable by each other
across a network.
-
The HP e3000 requires MPE/iX 5.5 or newer
-
The Windows 9x or NT computer requires Visual Basic 6 sp3 or
newer. It also requires IIS 4.0 or newer.
Install Programs on HP e3000
Install Programs on NT Server
Run setup.exe on the Windows computer.
Getting something
to work...
Compile and Execute the VB Sample Application
Finally, compile and execute the Visual Basic
sample application.
Download the source
|