4.1 Overview
ST-Developer includes three examples of a driver program that controls ST-Viewer and receives its events. The examples are written in Microsoft Visual C++, Visual Basic and Visual Basic for Applications (VBA). The first two programs are distributed as Microsoft Visual Studio projects and include full source code. The VBA example is distributed as a Microsoft Excel template file. They are installed in the automation directory under the ST-Developer root installation directory.
4.2 The Visual C++ example
The window of the ST-Viewer Automation Driver is shown in Figure 4.1. The top portion of the window (the Commands area) contains controls that use the methods of the ISTview interface.
File name- Specify the name of the file you want to load into the viewer.
[...]- Display the Open File dialog box to locate the file you want to load into the viewer.
Load- Invoke the LoadFile method.
Entity ID- Specify the entity ID for the object you want to display, hide, or select/unselect.
Instance- Specify the instance number for the object specified in the Entity ID box.
All- Apply the display/select commands to all instances of the specified object.
Display- Display the object(s) with the specified entity ID and instance(s). (Invoke the MakeVisible or MakeAllVisible methods.)
Hide- Hide the specified object(s). (Invoke the
MakeVisible
or
MakeAllVisible methods.)
Select- Select the specified object(s). (Invoke the MakeSelected or MakeAllSelected methods.)
Unselect- Cancel the selection of the specified object(s). (Invoke the
MakeSelected or MakeAllSelected methods.)
Left- Specify the horizontal position of the window.
Top- Specify the vertical position of the window.
Width- Specify the width of the window.
Height- Specify the height of the window.
Left pane- Specify the width of the left (identification) pane in the model window.
Shortcuts- Select a window shortcut command. The available commands are: None , Minimize , Maximize , Restore . When None is selected, the window position and size values are used. The other commands ignore these values.
Main- Invoke the SetMainWindowPosition method.
Model- Invoke the SetWindowPosition method.
X-Angle- Specify the number of degrees to rotate the left thumbwheel.
Y-Angle- Specify the number of degrees to rotate the bottom thumbwheel.
Dolly- Specify the number of degrees to rotate the right thumbwheel.
Zoom- Specify the fZoom argument value in the Zoom method.
Apply- Invoke the RotateThumbWheel and Zoom methods.
Reset- Set all default values.
The controls in the Events area display the last events received from the viewer via the ISTviewEvents interface. These controls do not accept user input. Under Display/Select you will see the results of the OnObjectDisplay and OnObjectSelect events.
How the driver works
The driver is a dialog-based MFC application. It uses the ISTview interface to send commands to ST-Viewer, and implements the ISTviewEvents interface to receive events from ST-Viewer.
After the project was created with MFC AppWizard, ST-Viewer type library was used to add a class wrapper for the ISTview interface. ClassWizard does this using the AddClass button and then choosing From a type library on the menu. This class wrapper is usually named after the corresponding COM interface, in this application it is the ISTview C++ class. Then a member of this class was added to the main window class ( CVizdriverDlg ) -- CVizdriverDlg::m_iSTview . In addition, the following code was added to the CVizdriverApp::InitInstance implementation:
if (!AfxOleInit()) {
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
This code initializes Automation DLLs.
The communication between the driver and ST-Viewer is established in the CVizdriverDlg::OnInitDialog method. The viewer is started and the new IDispatch object is created by the call:
m_iSTview.CreateDispatch("STview.Document")
This new IDispatch object is an Automation object in ST-Viewer and it impements the ISTview interface.
The next step is to establish return communication from the viewer to the driver via the ISTviewEvents interface. First, the interface is described in vizdriver.odl file the same way it is described in the stview.tlb type library:
[ uuid(18533554-04A8-11D3-B137-00902717498E), version(1.0) ]
library STview
{
// Primary dispatch interface
[ uuid(18533554-04A8-11D3-B137-00902717498D) ]
interface ISTviewEvents : IUnknown
{
[id(1)] HRESULT OnObjectDisplay(long nID,
long nInstance, short bDisplay);
[id(2)] HRESULT OnObjectSelect(long nID,
long nInstance, short bSelect);
};
}
When this ODL file is compiled, the MIDL compiler generates two C++ source files: guid.c and events.h ; the former defines C++ constants with GUIDs taken from the ODL file, the latter declares the ISTviewEvents C++ class.
Communication becomes possible by a mechanism known as connection points . The CVizdriverDlg class is a connection point container and implements the IConnectionPointContainer interface. The support for this interface is provided by including an interface map and adding the appropriate interface part to it:
in vizdriverDlg.h :
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(Events, ISTviewEvents)
STDMETHOD (OnObjectDisplay)(long nID, long nInst, short bDisp);
STDMETHOD (OnObjectSelect) (long nID, long nInst, short bSelect);
END_INTERFACE_PART(Events)
in vizdriverDlg.cpp :
BEGIN_INTERFACE_MAP(CVizdriverDlg, CDialog)
INTERFACE_PART(CVizdriverDlg, IID_ISTviewEvents, Events)
END_INTERFACE_MAP()
This code creates a nested class, CVizdriverDlg::XEvents that implements the ISTviewEvents interface declared in events.h . A member variable XEvents m_xEvents is added to CVizdriverDlg class. The XEvents class has two methods, OnObjectDisplay and OnObjectSelect . These methods are called when ST-Viewer fires the corresponding events.
Finally, write the implementation of OnObjectDisplay and OnObjectSelect methods (in addition to the three standard methods of IUnknown : AddRef , Release and QueryInterface ). These methods are located at lines 454-501 in vizdriverDlg.cpp .
The connection points are initialized in the CVizdriverDlg::OnInitDialog method:
[1] m_pEvents = m_iSTview.m_lpDispatch;
ISTviewEvents* pEvents;
[2] HRESULT hr = m_xEvents.QueryInterface(IID_ISTviewEvents,
(void**)&pEvents);
ASSERT(SUCCEEDED(hr));
m_xEvents.Release();
[3] if (!AfxConnectionAdvise(m_pEvents, IID_ISTviewEvents, pEvents,
FALSE, &m_dwConnectID))
MessageBox("AfxConnectionAdvise failed", "Error", MB_OK);
First, we get a pointer to the IDispatch interface in the viewer's Automation object [1]. This interface pointer identifies the source of the events. We get another interface pointer by calling QueryInterface on m_xEvents with the GUID of the ISTviewEvents [2]. This interface pointer identifies the sink or destination for the events.
Finally, the connection is esablished between the source ( m_pEvents , a pointer to the ST-Viewer's IDispatch ), and the sink ( pEvents , a pointer to the driver's implementation of the ISTviewEvents interface) [3].
Once the bidirectional communication is set up, the driver operation is simple. Each command handler (e.g. CVizdriverDlg::OnCommandsDisplayselectSelect() calls the methods of ISTview class, which in turn invokes the interface methods in ST-Viewer. On the other end, when the viewer fires an event (that is it calls a method of ISTviewEvents interface), the corresponding method of CVizdriverDlg::XEvents is invoked.
When the driver's dialog box is closed, the OnCancel method calls CVizdriver::Disconnect , which calls AfxConnectionUnadvise to break the connection between the source and the sink of the ISTviewEvents interface.
4.3 The Visual Basic example
The window and controls of Visual Basic automation driver are identical to that of the Visual C++ driver.
How the driver works
The Visual Basic project for the driver consist of a single dialog form. The ST-Viewer object variable is declared at the beginning of the file as:
Dim WithEvents STV As STview.Document
The WithEvents keyword specifies that the STV object variable can respond to events by an ActiveX object (ST-Viewer automation object in this case).
For this to work, the project must reference the ST-Viewer type library ( stview.tlb ) Use the Project | References command in the Visual Basic editor to reference this library.
This variable is insantiated in the Form_Load procedure:
Set STV = New STview.Document
This insures that ST-Viewer starts and creates a new automation object as soon as the driver's dialog gets displayed.
The rest of the code is very simple. Each control event procedure calls the corresponding method of the STV object, for instance:
Private Sub cmdDisplaySelectSelect_Click()
If chkDisplaySelectAll.Value = 1 Then
STV.MakeAllSelected (txtDisplaySelectEntityID.Text), 1
Else
STV.MakeSelected (txtDisplaySelectEntityID.Text),
(txtDisplaySelectInstance.Text), 1
End If
End Sub
In addition to control event procedures, there are two event procedures for the STV object, STV_OnObjectDisplay and STV_OnObjectSelect . These procedures are called when the viewer fires the corresponding events (calls ISTviewEvents methods).
4.4 The Microsoft Excel (VBA) example
The Microsoft Excel example is a template ( .xlt ) file. This template file contains a single worksheet, Selected Objects . The first two columns are reserved for the selected objects IDs and types. The ST-Viewer Automation toolbar visible on the following illustration is included in the template file.
The file also contains a set of macros written in Visual Basic for Applications (VBA). These macros are organized into four modules within the template file.
How the Macros Work
The ThisWorkbook module defines the ST-Viewer object variable, which is declared at the beginning of the source code as:
Dim WithEvents STV As STview.Document
The WithEvents keyword specifies that the STV object variable can respond to events by an ActiveX object (ST-Viewer automation object in this case).
For this to work, the project must reference the ST-Viewer type library ( stview.tlb ) Use the Project | References command in the Visual Basic editor to reference this library.
The STV variable is insantiated by the StartViewer procedure in the Viewer module:
Set ThisWorkbook.STV = New STview.Document
The StartViewer procedure is called when you click Start ST-Viewer on the ST-Viewer Automation toolbar. To load a STEP file into the viewer, click Open STEP File . This will call the LoadSTEPFile procedure in the Viewer module. This procedure in turns calls the STV.LoadFile method.
When you select an object in ST-Viewer, the STEP ID of this object and its entity type are added to the worksheet and drawn in red color as shown in Figure 4.2. If the object loses selection, the text color returns to normal.
The Main (Selected Objects) module contains the macros that handle the rest of the commands on the ST-Viewer Automation toolbar -- SelectObject , RemoveSelection , ResetSelection . These procedures call the MakeAllSelected method of the STV object.
Finally, the ThisWorkbook module contains the event procedures that respond to events in the viewer and in the workbook itself. The STV_OnObjectSelect procedure implements the ISTviewEvents::OnObjectSelect interface method and is called by ST-Viewer whenever the user changes the selection state of an object in the viewer. The other two procedures respond to activation and deactivation of the workbook by adding and removing the commands to control ST-Viewer from the Excel shortcut menu.