Bowling for COM

AMF Bowling Products Bowling Center System, version 1.0 Container Design

Microsoft Corporation

January 30, 1998

Contents

Introduction
Design Overview
Design Detail

Introduction

This document describes the container supporting the AMF BOSS System, version 1.0, Phase II client application.

System Basics

The building blocks of the AMF system are Microsoft® ActiveX® controls (generally written in the Microsoft Visual Basic® development system) and Component Object Model–based (COM-based) business objects (generally written in the Microsoft Visual C++® development system). The ActiveX controls implement the user interface for each primary functional area. The COM-based business objects implement logically related sets of business rules and are used by the controls to perform all business processing.

Architectural Requirements

The two primary requirements for the client application are:

Basic Design Principles

To support these two requirements, the AMF container and ActiveX control specifications described in this document were developed.

Important Note   Moving to a Web-based product and/or Microsoft Transaction Server were considered longer-term objectives, so our solution domain was simply COM deployed in a traditional client/server environment. We were careful, however, to avoid specifying any design parameters that are impermissible in the Microsoft Transaction Server world.

To be considered highly extensible, the container needs to know enough about any AMF ActiveX control to:

This suggests that the container must maintain ActiveX control state information and message maps, and must have a standard means of communicating with each control. The controls, conversely, need a means of getting their requests to the container, learning about their visual environment, and knowing when they can respond to container-defined and control-defined events initiated within dialog bars.

To accomplish these things, we took advantage of the fact that we were using solely COM components. The following, then, are the key design elements:

Before we describe additional technical details regarding these items, it may be helpful to demonstrate what these approaches will yield.

A Quick AMF Container Tour

Figure 1 shows a sample container and a simple control created with the design described in this document.

Figure 1. The AMF container

The container uses registry entries to load all primary controls (those that support the primary functional areas of the system). In this example, the registry contains entries for two simple controls, BasicAMFCtrl.dll (ATL), and BasicVBParentCtrl.ocx (Visual Basic). The latter is depicted in the client area of the application window shown in Figure 1.

Figure 2. Activating the first control

The load process includes creating a main dialog bar at the top of the client area of the frame, adding a button for each control, and calling the standard initialization routines for each control. Within these routines, the controls create docked dialog bars of their own, at the left edge of the container. The container then presses the first button on the main dialog bar. This activates the first control, as is shown in Figure 2.

BasicVBParentCtrl uses the Microsoft SQL Server™ Pubs database to retrieve bowler team information. Figure 3 displays the result after clicking Search and using "PC%" as the Team-ID search criteria.

Figure 3. Searching Team IDs

Clicking any of the buttons in the left dialog bar (which belong to BasicVBParentCtrl) will invoke a handler in this control. If we click the fourth button in this dialog bar, CreateCtrl 1, or click the Bowler... button in the control itself, BasicVBParentCtrl creates a modeless child control that can be used to look up bowler information that can later be applied, automatically to team search criteria. Figure 4 displays the result of clicking the CreateCtrl 1 dialog-bar button.

Figure 4. A modeless child control

This screen shot shows a new control, BasicVBChildCtrl, which is displayed within a modeless dialog box dynamically created by the container for the purpose of hosting child controls. This dialog box has OK and Cancel buttons which send messages back to the parent to give the parent control an opportunity to interrogate the child control, via its IStandardControlInterface implementation, for data values resulting from user interactions with the child control. Clicking Search and using "4%" as search criteria yields the information in Figure 5.

Figure 5. Data to pass between the child and parent controls

We can demonstrate that data is passed between child and parent controls by clicking OK. This will copy the Bowler ID contained in the first row and past it to the search-criteria field of the parent control, BasicVBParentCtrl. This is shown in Figure 6.

Figure 6. The Bowler ID has been copied to the search field.

If we clear the Team-ID search criteria, and click Search, we will retrieve all teams that have the displayed Bowler ID as captain. This is displayed in Figure 7.

Figure 7. The search results

We can switch to the second parent control by clicking its associated button, Basic2, on the main dialog bar. This brings up the display in Figure 8.

Figure 8. Basic Ctrl: #2

The user can then access its dialog bar to perform key operations. Clicking CreateCtrl 2: D brings up a child control, which, in this example, is BasicVBParentCtrl. This is depicted in Figure 9.

Figure 9. The child control of Basic Ctrl: #2

We might use this control (which is a distinct object instance of the BasicVBParentCtrl control) to create a bowler look-up control to assist with team search criteria, as before. Instead, we will switch back to the first control, by pressing its associated button on the main dialog bar, to demonstrate that state is maintained when going between primary controls.

Figure 10. The state maintained in the parent control.

This control had been inactive while the second primary control, BasicAMFCtrl, was visible. Finally, if we click the Basic2 button again, we will see the display in Figure 11.

Figure 11. The state maintained in the child control.

This shows that switching between primary controls preserves not only the state of the primary controls, but also the states of each of the child controls.

This quick tour demonstrates several key features of the container and its compatible controls:

The standards implemented by the container and its compatible controls are responsible for these features.

Container and Control Descriptions

The AMF container:

The container implements interfaces that are available to each control via connection points. These interfaces are:

Each ActiveX control must implement a standard interface that ensures the container can communicate with and effectively manage that control, irrespective of whatever else the control does. This interface is called IStandardControlInterface.

Note   The container does not need to know anything else about a control to manage it. This means that the container mechanism can be considered highly extensible.

The following sections describe all of the specifications required to create controls that will integrate at the binary level into the container.

Design Overview

Fundamental Objects

Figure 12 identifies the primary container and control components and depicts the interaction between them.

Figure 12. Primary container and control components

Object Descriptions

The AMF BOSS client is implemented as an MFC Single Document Interface (SDI) application. This application is comprised of several MFC views, each of which orchestrates the presentation of different system functionality. The AMF container is implemented using one of these views, CContainView; this class manages Microsoft Windows® messaging, dynamic dialog bar, and ActiveX control interaction. The other fundamental objects controlled directly and indirectly by this view are as follows:

ActiveX controls implemented with ATL communicate with the container through native ATL connection-points support. ActiveX controls implemented via Visual Basic call into the container via an ATL COM object (DLL) that implements the IExecuteStdCtrl interface. This interface is essentially a wrapper for the three interfaces described above. It is initialized with pointers to IManageActiveXControls and IManageDlgBars instances implemented by the container. IExecuteStdCtrl also allows a Visual Basic control to call the IStandardControlInterface methods implemented by other ActiveX controls. ATL controls can make these calls directly, through interface pointers retrieved from the container.

Initializing the Container and Primary Controls

CContainView creates both CCentralManageActiveXControls and CCentralManageDlgBars. CContainView creates the main dialog bar using CCentralManageDlgBars, which in turn makes calls to CDynDlgbar—a dynamic dialog-bar class. CContainView then reads the registry to identify all primary controls (those that will be accessible directly from the main dialog bar). CContainView loads the primary controls via calls to CCentralManageActiveXControls. CCentralManageActiveXControls creates one instance each of IManageActiveXControls and IManageDlgBars for each control. It establishes connections (via AtlAdvise) for each of these interfaces to the corresponding connection points implemented by each control. Each control may then create its own dialog bar(s) through its IManageDlgBars source interface and the corresponding connection point. Each control may also create its own child control(s) through its IManageActiveXControls source interface and the corresponding connection point. After all of the controls are created, CContainView presses the first button on the main dialog bar.

The text or icon used to label each button in the main dialog bar is retrieved from the newly created control by CCentralManageDlgBars using a call to the control's IStandardControlInterface::GetMainButtonInfo method.

Once a control is created, CCentralManageActiveXControls is used by the parent of the control to call the child control's IStandardControlInterface::OnInitialDisplay method. The child control implements this method to perform any initialization, such as creating child controls and dialog bars.

Basic Message Processing

When the user or the view clicks a button on the main dialog bar, the corresponding control is made visible, along with its child controls and associated dialog bars. The IStandardControlInterface::OnReactivate method of each newly visible control is called by CCentralManageActiveXControls. All controls not owned by the newly visible controls are deactivated. The IStandardControlInterface::OnDeactivate method of each of these now invisible controls is called by CCentralManageActiveXControls.

Note that each button on each dialog bar is uniquely identified by a control ID. This ID is stored by CCentralManageDlgBars and is mapped to an operation ID specified by the control that owns the dialog bar. The view uses the CCentralManageDlgBars map to determine which control should receive notification that the button has been pressed. Once that determination has been made, then the appropriate notification method is called on the child control's standard interface. These notification methods are:

Each control should implement the appropriate functionality within each of these methods to handle all of its associated button operations.

A control can learn its parent's control ID and obtain useful HWNDs by calling IStandardControlInterface::GetCtrlInfo. These values allow the control to manipulate its environment, particularly the visual aspects, through standard Windows messaging.

Child Control Notes

Note that a child control should not be created with the view as the parent of its window. That role should be played by a modeless dialog created dynamically. The IManageActiveXControls::CreateChildControl method will construct such dialog boxes as a part of its control creation processing, provided that the bUseNewWindow parameter is set to TRUE. The default dynamic dialog box created for each child control contains both OK and Cancel buttons. The corresponding control registers operation IDs that correspond to these buttons. When there is an attempt to destroy a child control (by a user pressing one of these two buttons), the child control is informed via a call to its IStandardControlInterface::CallTopDlgBar method with the operation ID of the button pressed as an argument. If this method returns E_FAIL, then the dialog box and its associated control are not destroyed. If this method returns S_OK, then the parent control is notified with exactly the same call to its IStandardControlInterface::CallTopDlgBar method. It the parent returns E_FAIL from this method, then the dialog box and its associated control are not destroyed. If this method returns S_OK, then the dialog box and its associated control are destroyed.

For simplicity, all controls should use the operation IDs IDOK and IDCANCEL to identify all OK and Cancel buttons used in all dynamic dialog boxes associated with child controls.

Data Exchange between Controls

A control can request data from another control in one or more of the following three ways:

A control can send data to another control by:

Registry

The registry stores the usual characteristics of each ActiveX control. There is also a new key, HKEY_LOCAL_MACHINE\SOFTWARE\AMF, that stores information specific to the container and its controls. One its subkeys, BOSSContainer, stores values that identify the bounding RECT for the container's main frame (also known as the application window). These values are read at application start-up, and new settings for these registry values are written just prior to application termination. There is also a subkey, Components, which contains separate subkeys for each primary control (those controls that are loaded at application start-up by the view). These subkeys must be named in sequence such that the first is called 0001, the second is called 0002. . . . Each of these subkeys contains registry values that identify important initial properties for each primary control.

Note   The only way of specifying that a primary control exists is through these subkeys.

Figure 13 is an example of a complete, valid container subtree, with one component's data displayed.

Figure 13. A container subtree in the registry

Design Detail

IStandardControlInterface

Each control must fully implement this interface to guarantee integration into the AMF container. This interface is described by the following IDL:

   [
      object,
      uuid(F68B14CF-742D-11D1-BD40-0080C73C6D96),
      dual,
      helpstring("IStandardControlInterface Interface"),
      pointer_default(unique)
   ]
   interface IStandardControlInterface : IDispatch
   {
      [id(1), helpstring("method OnInitialDisplay")]
      HRESULT OnInitialDisplay([in] BSTR bstrTitle,
                   [in] BSTR bstrDisplayText1,
                   [in] BSTR bstrDisplayText2,
                   [in,out] long *phrResult);
      [id(2), helpstring("method OnReactivateDisplay")]
      HRESULT OnReactivateDisplay([in,out] long *phrResult);
      [id(3), helpstring("method OnDeactivateDisplay")]
      HRESULT OnDeactivateDisplay([in,out] long *phrResult);
      [id(4), helpstring("method OnClose")]
      HRESULT OnClose([in,out] long *phrResult);
      [id(5), helpstring("method OkToClose")]
      HRESULT OkToClose([in,out] VARIANT_BOOL *pbCanClose,
                    [in,out] BSTR *pbMsg,
                    [in,out] long *phrResult);
      [id(6), helpstring("method ShowModalPrimaryDlg")]
      HRESULT ShowModalPrimaryDlg([in] BSTR bstrCaption,
                  [in,out]long* phWnd,
                  [in,out] long *phrResult);
      [id(7), helpstring("method ShowModelessPrimaryDlg")]
      HRESULT ShowModelessPrimaryDlg([in] BSTR bstrCaption,
                  [in,out]long* phWnd,
                  [in,out] long *phrResult);
      [id(8), helpstring("method GetRefToMe")]
      HRESULT GetRefToMe([in,out]VARIANT* pvMe,
                  [in,out] long *phrResult);
      [id(9), helpstring("method CallTopDlgBar")]
      HRESULT CallTopDlgBar([in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(10), helpstring("method CallLeftDlgBar")]
      HRESULT CallLeftDlgBar([in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(11), helpstring("method CallBottomDlgBar")]
      HRESULT CallBottomDlgBar([in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(12), helpstring("method CallRightDlgBar")]
      HRESULT CallRightDlgBar([in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(13), helpstring("method GetMainButtonInfo")]
      HRESULT GetMainButtonInfo([in,out]BSTR *pbstrText,
                    [in,out]long *phIconID,
                    [in,out]VARIANT_BOOL *pbTextOnly,
                       [in,out] long *phrResult);
      [id(14), helpstring("method IsVBComponent")]
      HRESULT IsVBComponent(VARIANT_BOOL *pbVBComponent,
                    [in,out] long *phrResult);
      [id(15), helpstring("method GetCtrlDefinedData")]
      HRESULT GetCtrlDefinedData([in]int nWhichData,
               [in]int nIndex,
               [in,out]int *pnOptionalDataSize,
               [in,out]VARIANT* pvData,
               [in,out] long *phrResult);
      [id(16), helpstring("method SetCtrlDefinedData")]
      HRESULT SetCtrlDefinedData([in]int nWhichData,
               [in]int nIndex,
               [in,out]int *pnOptionalDataSize,
               [in]VARIANT vData,
               [in,out] long *phrResult);
      [id(17), helpstring("method SetMainHelperData")]
      HRESULT SetMainHelperData(
               [in]long lManageActiveXControls,
               [in]long lManageDlgBars,
               [in,out] long *phrResult);
      [propget, id(18), helpstring("property ControlID")]
      HRESULT ControlID([out, retval] short *pVal);
      [propput, id(18), helpstring("property ControlID")]
      HRESULT ControlID([in] short newVal);
   };

Initialization and termination handlers

Method OnInitialDisplay
Parameters BSTR *pbstrTitle

The suggested title for the dialog box that owns the control. The control should do a GetCtrlInfo first to see if its parent ID is greater than 0 and if the dialog box exists. Under those circumstances, it is safe to set the title.

BSTR *pbstrDisplayText1

Additional text information to be displayed.

BSTR *pbstrDisplayText2

Additional text information to be displayed.

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called by the creator of a control (the container or a control) to give the control the opportunity to issue startup commands such as creating new child controls and new dialog bars.

Method OnClose
Parameters None
Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Remarks This method is called when the control is about to be destroyed. It is called by the container to give the control the opportunity to issue cleanup commands only. The control will be destroyed irrespective of what occurs within this method.

Method OkToClose
Parameters VARIANT_BOOL *pbCanClose

The control should set this variable to TRUE if the control has no further processing that would preclude its destruction.

BSTR *pbMsg

An optional message to be displayed at user's workstation when *pbCanClose is set to TRUE.

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called when the container is in the process of interrogating each control to determine whether the controls can be destroyed. If any control sets *pbCanClose to FALSE, then the container will (generally) not destroy each control and will not exit.

Display handlers

Method OnReactivateDisplay
Parameters long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called when the control is to be made visible again. It is called by the container to give the control the opportunity to issue commands appropriate for this case.

Method OnDeactivateDisplay
Parameters long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called when the control is to be made invisible and deactivated again. It is called by the container to give the control the opportunity to issue commands appropriate for this case.

Dialog button handlers

Method CallTopDlgBar
Parameters short nWhichBtn

The operation ID corresponding to a button in a horizontal dialog bar of style CBRS_TOP.

VARIANT vData

Reserved

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value If operation ID is neither the equivalent of IDOK or IDCANCEL, then

HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

If operation ID is the equivalent of either IDOK or IDCANCEL, then

HRESULT

E_FAIL indicates that the associated child dialog box can be destroyed.

S_OK indicates that the associated child dialog box cannot be destroyed.

Remarks This method is called when a button on a horizontal dialog bar (style CBRS_TOP) has been pressed. The operation ID contained in nWhichBtn was specified by the control implementing this interface when its bar was created. The implementation of this method must process all operation IDs previously registered for the associated dialog bar.

Method CallLeftDlgBar
Parameters short nWhichBtn

The operation ID corresponding to a button in a left, vertical dialog bar of style CBRS_LEFT.

VARIANT vData

Reserved

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called when a button on a vertical dialog bar (style CBRS_LEFT) has been pressed. The operation ID contained in nWhichBtn was specified by the control implementing this interface when its bar was created. The implementation of this method must process all operation IDs previously registered for the associated dialog bar.

Method CallBottomDlgBar
Parameters short nWhichBtn

The operation ID corresponding to a button in a bottom, horizontal dialog bar of style CBRS_BOTTOM.

VARIANT vData

Reserved

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called when a button on a horizontal dialog bar (style CBRS_BOTTOM) has been pressed. The operation ID contained in nWhichBtn was specified by the control implementing this interface when its bar was created. The implementation of this method must process all operation IDs previously registered for the associated dialog bar.

Method CallRightDlgBar
Parameters short nWhichBtn

The operation ID corresponding to a button in a right, vertical dialog bar of style CBRS_RIGHT.

VARIANT vData

Reserved

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called when a button on a vertical dialog bar (style CBRS_RIGHT) has been pressed. The operation ID contained in nWhichBtn was specified by the control implementing this interface when its bar was created. The implementation of this method must process all operation IDs previously registered for the associated dialog bar.

Control access methods

Method GetRefToMe
Parameters VARIANT* pvMe

This control should store a this pointer to itself in this variable. In a C++ control, this will generally be equivalent to a pIStandardControlInterface. In a Visual Basic control, this will generally be equivalent to a reference to the control itself.

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called to retrieve a pointer to the object. It is most useful in the case where a Visual Basic control wants to use this reference to call a Visual Basic control.

Method IsVBComponent
Parameters VARIANT_BOOL *pbVBComponent

Set to TRUE if the control was created with Visual Basic, and set to FALSE if the control was not created with Visual Basic.

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called to learn whether a control was created with Visual Basic.

Method GetCtrlDefinedData
Parameters int nWhichData

Specified by the control, this parameter helps to identify the data to be retrieved.

int nIndex

Specified by the control, this parameter helps to identify the data to be retrieved.

int *nOptionalDataSize

Specified by the control, this parameter helps to identify the size of the data to be retrieved.

VARIANT* pvData

Specified by control, the data retrieved

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called to retrieve data from a control. All parameters are specified by the control.

Method SetCtrlDefinedData
Parameters int nWhichData

Specified by the control, this parameter helps to identify the data to be retrieved.

int nIndex

Specified by the control, this parameter helps to identify the data to be retrieved.

int *nOptionalDataSize

Specified by the control, this parameter helps to identify the size of the data being sent to the control and the size actually received by the control.

VARIANT vData

Specified by control, the data being sent

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called to send data to the control. This data will generally be initialization text for the user. Since this can be sent at any time by the container, the control should store the new settings in global variables and establish a rule about when to look for this data; for example, it might examine the settings whenever an OnReactivateDisplay is invoked, or only once—during OnInitialDisplay.

Miscellaneous methods and properties

Method GetMainButtonInfo
Parameters dBSTR *pbstrText

Button label

long *phIconID

The Resource ID (container's resource) for the icon to display in the button.

VARIANT_BOOL *pbTextOnly

Set to TRUE if the button has only text, and set to FALSE if the button has only an icon.

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called to retrieve data for the proper display of the button in the main dialog bar—for primary controls only.

Method get_ControlID
Parameters short *pVal

Receives control ID of this control

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks This method is called to retrieve the control ID of this control.

Method put_ControlID
Parameters short newVal

The control ID of this control.

long hr

This must be the same as the return code; it allows Visual Basic controls to access the return code.

Return Value HRESULT

E_FAIL indicates an error in processing.

S_OK indicates that the processing occurred successfully.

Remarks Never use this method.

IManageActiveXControls

Each control can take advantage of services offered by the container through this interface. It is described by the following IDL:

   [
      object,
      uuid(F2421612-6F20-11D1-BD36-0080C73C6D96),
      dual,
      helpstring("IManageActiveXControls Interface"),
      pointer_default(unique)
   ]
   interface IManageActiveXControls : IDispatch
   {
      import "oaidl.idl";
      [id(1), helpstring("method AssignMyID")]
      HRESULT AssignMyID([in,out]int* pnMyID);
      [id(2), helpstring("method CreateNewChildCtrl")]
      HRESULT CreateNewChildCtrl([in]int nMyID,
               [in,out]int* pnChildID,
               [in]long lClsid1,
               [in]long lClsid2,
               [in]long lClsid3,
               [in]long lClsid4,
               [in]short nClientRectTop,
               [in]short nClientRectLeft,
               [in]short nClientRectBottom,
               [in]short nClientRectRight,
               [in]VARIANT_BOOL bCanResize,
               [in]VARIANT_BOOL bUseNewWindow,
               [in]short nDlgBoxHintTop,
               [in]short nDlgBoxHintLeft,
               [in]VARIANT_BOOL bShowOKCancel,
               [in]long lOKID,
               [in]long lCancelID);
      [id(3), helpstring("method DestroyCtrl")]
      HRESULT DestroyCtrl([in]int nMyID,
               [in]int nChildID);
      [id(4), helpstring("method GetRefToCtrl")]
      HRESULT GetRefToCtrl([in]int nMyID,
               [in]int nChildID,
               [in,out]VARIANT *vRef);
      [id(5), helpstring("method GetStdInterfaceToCtrl")]
      HRESULT GetStdInterfaceToCtrl([in]int nMyID,
               [in]int nChildID,
               [in,out]VARIANT *vRef);
      [id(6), helpstring("method IsCtrlVBComponent")]
      HRESULT IsCtrlVBComponent([in]int nCtrlID,
               [in,out]VARIANT_BOOL *pbVBComponent);
      [id(7), helpstring("method GetCtrlInfo")]
      HRESULT GetCtrlInfo([in]int nMyID,
               [in,out]int* pnParentID,
               [in,out]long* phwndCtrlWnd,
               [in,out]long* phwndCtrlDlgBox,
               [in,out]long* phwndParentView,
               [in,out]long* phwndMainFrame);
      [propget, id(8), helpstring("property
             CentralManageAXObject")]
      HRESULT CentralManageAXObject([out, retval] long *pVal);
      [propput, id(8), helpstring("property
            CentralManageAXObject")]
      HRESULT CentralManageAXObject([in] long newVal);
   };

Return codes

All return codes for these methods are HRESULT. This value will be E_FAIL if the container experienced some error during processing. This value will be S_OK if the container processed the request successfully.

Special comments on methods

Methods/Parameters Parameter Descriptions Remarks
AssignMyID

[out]int* pnMyID

Reserved Do not use.
CreateNewChildCtrl

[in]int nMyID

[out]int* pnChildID

[in]long lClsid1

[in]long lClsid2

[in]long lClsid3

[in]long lClsid4

[in]short nClientRectTop

[in]short nClientRectLeft

[in]short nClientRectBottom

[in]short nClientRectRight

[in]VARIANT_BOOL bCanResize

[in]VARIANT_BOOL bUseNewWindow

[in]short nDlgBoxHintTop

[in]short nDlgBoxHintLeft

[in]VARIANT_BOOL bShowOKCancel

[in]long lOKID

[in]long lCancelID

ID of calling control

Receives value of child control ID

16 bytes corresponding to the class ID of the control

Client coordinates of the bounding RECT for the control

Reserved, no automatic resizing

Reserved, child controls should always use new windows

Displacements from bounding RECT; use 0, 0 if defaults are OK

TRUE if dialog box should have OK/Cancel buttons

op ID, should use IDOK

op ID, should use IDCANCEL

Creates new child control. The calling control will be the parent control.

After this routine returns, the parent should call the child's OnInitialDisplay method so the child can initialize itself.

DestroyCtrl

[in]int nMyID

[in]int nChildID

ID of calling control

ID of child control ID

Destroys nChildID control. Calling control must be the parent or nChildID itself.
GetRefToCtrl

[in]int nMyID

[in]int nChildID

[out]VARIANT *vRef

ID of calling control

ID of child control ID

Pointer to reference to nChildID control

Uses nChildID's IStandardControlInterface:: GetRefToMe method to retrieve ref to nChildID.
GetStdInterfaceToCtrl

[in]int nMyID

[in]int nChildID

[out]VARIANT *vRef

ID of calling control

ID of child control ID

Pointer to reference to nChildID control

Retrieves container's internal pointer to nChildID's IStandardControlInterface.
IsCtrlVBComponent

[in]int nCtrlID

[out]VARIANT_BOOL *pbVBComponent

ID of control to interrogate

Receives TRUE if nCtrlID is VB

Calls nCtrlID's IStandardControlInterface:: IsVBComponent method to set pbVBComponent.
GetCtrlInfo

[in]int nMyID

[out]int* pnParentID

[out]long* phwndCtrlWnd

[out]long* phwndCtrlDlgBox

[out]long* phwndParentView

[out]long* phwndMainFrame

ID of control requesting information

Receives ID of control's parent

Receives control's HWND

Receives dialog box holding control, if any

Receives HWND of view which owns the control

Receives HWND of container's main frame

Permits the control to obtain valuable environmental information. These values allow control to interact with the container and user via messaging. Control should only call this when it is active—if the control needs accurate view information.
get_CentralManageAXObject

[out, retval] long *pVal

Reserved Do not use.
put_CentralManageAXObject

[in] long newVal

Reserved Do not use.

Please see the sample code for examples of how to use these methods.

IManageDlgBars

Each control can take advantage of services offered by the container through this interface. It is described by the following IDL:

   [
      object,
      uuid(F2421612-6F21-11D1-BD36-0080C73C6D96),
      dual,
      helpstring("IManageDlgBars Interface"),
      pointer_default(unique)
   ]
   interface IManageDlgBars : IDispatch
   {
      import "oaidl.idl";
      [id(1), helpstring("method CreateNewDlgBar")]
      HRESULT CreateNewDlgBar([in]int nMyID,
               [in,out]int* pnDlgBarID,
               [in]int nWhere,
               [in]VARIANT_BOOL bExclusivelyMine);
      [id(2), helpstring("method AddNewRadioButton")]
      HRESULT AddNewRadioButton([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID,
               [in]VARIANT_BOOL bGroup,
               [in]VARIANT_BOOL bTextOnly,
               [in]BSTR strText,
               [in]long lResID,
               [in]int nWhichOperation);
      [id(3), helpstring("method AddNewCheckBox")]
      HRESULT AddNewCheckBox([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID,
               [in]VARIANT_BOOL bGroup,
               [in]VARIANT_BOOL bTextOnly,
               [in]BSTR strText,
               [in]long lResID,
               [in]int nWhichOperation);
      [id(4), helpstring("method AddNewPushButton")]
      HRESULT AddNewPushButton([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID,
               [in]VARIANT_BOOL bTextOnly,
               [in]BSTR strText,
               [in]long lResID,
               [in]int nWhichOperation);
      [id(5), helpstring("method AddNewSpaceButton")]
      HRESULT AddNewSpaceButton([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID);
      [id(6), helpstring("method ShowDlgBar")]
      HRESULT ShowDlgBar([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nCmd);
      [id(7), helpstring("method ShowButton")]
      HRESULT ShowButton([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nButtonID,
               [in]int nCmd);
      [id(8), helpstring("method EnableDisableDlgBar")]
      HRESULT EnableDisableDlgBar([in]int nMyID,
               [in]int nDlgBarID,
               [in]VARIANT_BOOL bEnable);
      [id(9), helpstring("method EnableDisableButton")]
      HRESULT EnableDisableButton([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nButtonID,
               [in]VARIANT_BOOL bEnable);
      [id(10), helpstring("method DestroyButton")]
      HRESULT DestroyButton([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nButtonID);
      [id(11), helpstring("method DestroyDlgBar")]
      HRESULT DestroyDlgBar([in]int nMyID,
               [in]int nDlgBarID);
      [id(12), helpstring("method GetLastNonExclusiveDlgBar")]
      HRESULT GetLastNonExclusiveDlgBar([in]int nMyID,
               [in]int nWhere,
               [in]int* pnDlgBarID);
      [propget, id(13), helpstring("property
            CentralManageDlgBarObject")]
      HRESULT CentralManageDlgBarObject([out, retval] long *pVal);
      [propput, id(13), helpstring("property
            CentralManageDlgBarObject")]
      HRESULT CentralManageDlgBarObject([in] long newVal);
   };

Return codes

All return codes for these methods are HRESULT. This value will be E_FAIL if the container experienced some error during processing. This value will be S_OK if the container processed the request successfully.

Special comments on methods

Method/Parameters Parameter Descriptions Remarks
CreateNewDlgBar

[in]int nMyID

[out]int* pnDlgBarID

[in]int nWhere

[in]VARIANT_BOOL bExclusivelyMine

ID of calling control

Receives dialog bar ID of new dialog bar

location of dialog bar, valid values are: CBRS_TOP, CBRS_LEFT, CBRS_BOTTOM, CBRS_RIGHT

Reserved. Do not use.

Creates a new dialog bar and associates it with control nMyID. This control becomes "parent control" of the new dialog bar
AddNewRadioButton

[in]int nMyID

[in]int nDlgBarID

[out]int* pnButtonID

[in]VARIANT_BOOL bGroup

[in]VARIANT_BOOL bTextOnly

[in]BSTR strText

[in]long lResID

[in]int nWhichOperation

Control ID of calling control

ID of dialog bar that will create new button

Receives button ID of new button; control does not have to store this, unless control plans to destroy buttons selectively later

TRUE if new group is started

TRUE if only text should appear on button

Text to appear on button

Container's res ID of icon to appear on button

CRITICAL. The value that will be returned by container to this control when this button is pressed

Adds new radio button to dialog bar nDlgBarID. nMyID must be the parent control of this dialog bar.
AddNewCheckBox

[in]int nMyID

[in]int nDlgBarID

[out]int* pnButtonID

[in]VARIANT_BOOL bGroup

[in]VARIANT_BOOL bTextOnly

[in]BSTR strText

[in]long lResID

[in]int nWhichOperation

Same as in AddNewRadioButton Same as in AddNewRadioButton
AddNewPushButton

[in]int nMyID

[in]int nDlgBarID

[out]int* pnButtonID

[in]VARIANT_BOOL bTextOnly

[in]BSTR strText

[in]long lResID

[in]int nWhichOperation

The same as in AddNewRadioButton, except that bGroup is not applicable to push buttons. The same as in AddNewRadioButton, except that bGroup is not applicable to push buttons.
AddNewSpaceButton

[in]int nMyID

[in]int nDlgBarID

[out]int* pnButtonID

Control ID of calling control

ID of dialog bar that will create new button

Receives button ID of new LOGICAL button; this value should not be saved unless user is given option of building dialog bar dynamically

Adds more space between last button created and the next button to be created. Call multiple times to increase space. Once the next button is created, spacing is reset to default.
ShowDlgBar

[in]int nMyID

[in]int nDlgBarID

 [in]int nCmd

Control ID of calling control

ID of dialog bar to manipulate

TRUE, if dialog bar is to be displayed, FALSE, if it is to be deactivated and made invisible—but not destroyed

Activates and displays

OR

Deactivates and make invisible dialog bar nDlgBarID

ShowButton

[in]int nMyID

[in]int nDlgBarID

[in]int nButtonID

[in]int nCmd

Control ID of calling control

ID of dialog bar to manipulate

ID of button to manipulate

TRUE, if button is to be displayed, FALSE, if it is to be deactivated and made invisible—but not destroyed

Activates and displays

OR

Deactivates and make invisible button nButtonID

EnableDisableDlgBar

[in]int nMyID

[in]int nDlgBarID

[in]VARIANT_BOOL bEnable

Control ID of calling control

ID of dialog bar to manipulate

TRUE, if dialog bar is to be displayed, FALSE, if it is to be deactivated and made invisible—but not destroyed

Activates and displays

OR

Deactivates and make invisible dialog bar nDlgBarID

EnableDisableButton

[in]int nMyID

[in]int nDlgBarID

[in]int nButtonID

[in]VARIANT_BOOL bEnable

Control ID of calling control

ID of dialog bar to manipulate

ID of button to manipulate

TRUE, if button is to be displayed, FALSE, if it is to be deactivated and made invisible—but not destroyed

Activates and displays

OR

Deactivates and make invisible button nButtonID

DestroyButton

[in]int nMyID

[in]int nDlgBarID

[in]int nButtonID

Control ID of calling control

ID of dialog bar to manipulate

ID of button to manipulate

Destroys button nButtonID on dialog bar nDlgBarID. The parent control of this dialog bar must be nMyID
DestroyDlgBar

[in]int nMyID

[in]int nDlgBarID

Control ID of calling control

ID of dialog bar to manipulate

Destroys dialog bar nDlgBarID. The parent control of this dialog bar must be nMyID
GetLastNonExclusiveDlgBar

[in]int nMyID

[in]int nWhere

 [in]int* pnDlgBarID

Control ID of calling control

location of dialog bar to be found, valid values are: CBRS_TOP, CBRS_LEFT, CBRS_BOTTOM, CBRS_RIGHT

Retrieves ID of dialog bar to manipulate

Used to locate ID of most recently created dialog bar at position specified by nWhere. Control nMyID can then add buttons to this dialog bar. The control must remove these buttons prior to its own destruction.
get_CentralManageDlgBarObject

[out, retval] long *pVal

Reserved Don not use.
put_CentralManageDlgBarObject

[in] long newVal

Reserved Do not use.

Please see the sample code for examples of how to use these methods.

IExecuteStdCtrl

This interface is implemented by the Execute.dll ATL COM object to allow Visual Basic controls to communicate reliably and consistently with the container and other controls. This is essentially a wrapper for the previous three interfaces and should be initialized in the control's IStandardControlInterface::SetMainHelperData method. For descriptions of these methods, see the previous three sections.

   [
      object,
      uuid(7CE24B90-961A-11D1-BD71-000000000000),
      dual,
      helpstring("IExecuteStdCtrl Interface"),
      pointer_default(unique)
   ]
   interface IExecuteStdCtrl : IDispatch
   {
      [id(1), helpstring("method OnInitialDisplay")]
      HRESULT OnInitialDisplay([in] long ptrInterface,
                   [in] BSTR bstrTitle,
                   [in] BSTR bstrDisplayText1,
                   [in] BSTR bstrDisplayText2,
                   [in,out] long *phrResult);
      [id(2), helpstring("method OnReactivateDisplay")]
      HRESULT OnReactivateDisplay([in] long ptrInterface,
                     [in,out] long *phrResult);
      [id(3), helpstring("method OnDeactivateDisplay")]
      HRESULT OnDeactivateDisplay([in] long ptrInterface,
                     [in,out] long *phrResult);
      [id(4), helpstring("method OnClose")]
      HRESULT OnClose([in] long ptrInterface,
                  [in,out] long *phrResult);
      [id(5), helpstring("method OkToClose")]
      HRESULT OkToClose([in] long ptrInterface,
               [in,out] VARIANT_BOOL *pbCanClose,
               [in,out] BSTR *pbMsg,
               [in,out] long *phrResult);
      [id(6), helpstring("method ShowModalPrimaryDlg")]
      HRESULT ShowModalPrimaryDlg([in] long ptrInterface,
               [in] BSTR bstrCaption,
               [in,out]long* phWnd,
               [in,out] long *phrResult);
      [id(7), helpstring("method ShowModelessPrimaryDlg")]
      HRESULT ShowModelessPrimaryDlg([in] long ptrInterface,
                     [in] BSTR bstrCaption,
                     [in,out]long* phWnd,
                     [in,out] long *phrResult);
      [id(8), helpstring("method GetRefToMe")]
      HRESULT GetRefToMe([in] long ptrInterface,
                [in,out]VARIANT* pvMe,
                [in,out] long *phrResult);
      [id(9), helpstring("method CallTopDlgBar")]
      HRESULT CallTopDlgBar([in] long ptrInterface,
                    [in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(10), helpstring("method CallLeftDlgBar")]
      HRESULT CallLeftDlgBar([in] long ptrInterface,
                    [in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(11), helpstring("method CallBottomDlgBar")]
      HRESULT CallBottomDlgBar([in] long ptrInterface,
                    [in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(12), helpstring("method CallRightDlgBar")]
      HRESULT CallRightDlgBar([in] long ptrInterface,
                    [in]short nWhichBtn,
                    [in]VARIANT vData,
                    [in,out] long *phrResult);
      [id(13), helpstring("method GetMainButtonInfo")]
      HRESULT GetMainButtonInfo([in] long ptrInterface,
                    [in,out]BSTR *pbstrText,
                    [in,out]long *phIconID,
                    [in,out]VARIANT_BOOL *pbTextOnly,
                    [in,out] long *phrResult);
      [id(14), helpstring("method IsVBComponent")]
      HRESULT IsVBComponent([in] long ptrInterface,
                    VARIANT_BOOL *pbVBComponent,
                    [in,out] long *phrResult);
      [id(15), helpstring("method GetCtrlDefinedData")]
      HRESULT GetCtrlDefinedData([in] long ptrInterface,
               [in]int nWhichData,
               [in]int nIndex,
               [in,out]int *pnOptionalDataSize,
               [in,out]VARIANT* pvData,
               [in,out] long *phrResult);
      [id(16), helpstring("method SetCtrlDefinedData")]
      HRESULT SetCtrlDefinedData([in] long ptrInterface,
               [in]int nWhichData,
               [in]int nIndex,
               [in,out]int *pnOptionalDataSize,
               [in]VARIANT vData,
               [in,out] long *phrResult);
      [id(17), helpstring("method SetMainHelperData")]
      HRESULT SetMainHelperData(
               [in]long lManageActiveXControls,
               [in]long lManageDlgBars,
               [in,out] long *phrResult);
      [id(18), helpstring("method OnManageACCreateNewChildCtrl")]
      HRESULT OnManageACCreateNewChildCtrl([in]int nMyID,
               [in,out]int* pnChildID,
               [in]long lClsid1,
               [in]long lClsid2,
               [in]long lClsid3,
               [in]long lClsid4,
               [in]short nClientRectTop,
               [in]short nClientRectLeft,
               [in]short nClientRectBottom,
               [in]short nClientRectRight,
               [in]VARIANT_BOOL bCanResize,
               [in]VARIANT_BOOL bUseNewWindow,
               [in]short nDlgBoxHintTop,
               [in]short nDlgBoxHintLeft,
               [in]VARIANT_BOOL bShowOKCancel,
               [in]long lOKID,
               [in]long lCancelID,
               [in,out] long *phrResult);
      [id(19), helpstring("method OnManageACDestroyCtrl")]
      HRESULT OnManageACDestroyCtrl([in]int nMyID,
               [in]int nChildID,
               [in,out] long *phrResult);
      [id(20), helpstring("method OnManageACGetRefToCtrl")]
      HRESULT OnManageACGetRefToCtrl([in]int nMyID,
               [in]int nChildID,
               [in,out]VARIANT *vRef,
               [in,out] long *phrResult);
      [id(21), helpstring("method
            OnManageACGetStdInterfaceToCtrl")]
      HRESULT OnManageACGetStdInterfaceToCtrl([in]int nMyID,
               [in]int nChildID,
               [in,out]VARIANT *vRef,
               [in,out] long *phrResult);
      [id(22), helpstring("method OnManageACIsCtrlVBComponent")]
      HRESULT OnManageACIsCtrlVBComponent([in]int nCtrlID,
               [in,out]VARIANT_BOOL *pbVBComponent,
               [in,out] long *phrResult);
      [id(23), helpstring("method OnManageACGetCtrlInfo")]
      HRESULT OnManageACGetCtrlInfo([in]int nMyID,
               [in,out]int* pnParentID,
               [in,out]long* phwndCtrlWnd,
               [in,out]long* phwndCtrlDlgBox,
               [in,out]long* phwndParentView,
               [in,out]long* phwndMainFrame,
               [in,out] long *phrResult);
      [id(24), helpstring("method OnManageDBCreateNewDlgBar")]
      HRESULT OnManageDBCreateNewDlgBar([in]int nMyID,
               [in,out]int* pnDlgBarID,
               [in]int nWhere,
               [in]VARIANT_BOOL bExclusivelyMine,
               [in,out] long *phrResult);
      [id(25), helpstring("method OnManageDBAddNewRadioButton")]
      HRESULT OnManageDBAddNewRadioButton([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID,
               [in]VARIANT_BOOL bGroup,
               [in]VARIANT_BOOL bTextOnly,
               [in]BSTR strText,
               [in]long lResID,
               [in]int nWhichOperation,
               [in,out] long *phrResult);
      [id(26), helpstring("method OnManageDBAddNewCheckBox")]
      HRESULT OnManageDBAddNewCheckBox([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID,
               [in]VARIANT_BOOL bGroup,
               [in]VARIANT_BOOL bTextOnly,
               [in]BSTR strText,
               [in]long lResID,
               [in]int nWhichOperation,
               [in,out] long *phrResult);
      [id(27), helpstring("method OnManageDBAddNewPushButton")]
      HRESULT OnManageDBAddNewPushButton([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID,
               [in]VARIANT_BOOL bTextOnly,
               [in]BSTR strText,
               [in]long lResID,
               [in]int nWhichOperation,
               [in,out] long *phrResult);
      [id(28), helpstring("method OnManageDBAddNewSpaceButton")]
      HRESULT OnManageDBAddNewSpaceButton([in]int nMyID,
               [in]int nDlgBarID,
               [in,out]int* pnButtonID,
               [in,out] long *phrResult);
      [id(29), helpstring("method OnManageDBShowDlgBar")]
      HRESULT OnManageDBShowDlgBar([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nCmd,
               [in,out] long *phrResult);
      [id(30), helpstring("method OnManageDBShowButton")]
      HRESULT OnManageDBShowButton([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nButtonID,
               [in]int nCmd,
               [in,out] long *phrResult);
      [id(31), helpstring("method OnManageDBEnableDisableDlgBar")]
      HRESULT OnManageDBEnableDisableDlgBar([in]int nMyID,
               [in]int nDlgBarID,
               [in]VARIANT_BOOL bEnable,
               [in,out] long *phrResult);
      [id(32), helpstring("method OnManageDBEnableDisableButton")]
      HRESULT OnManageDBEnableDisableButton([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nButtonID,
               [in]VARIANT_BOOL bEnable,
               [in,out] long *phrResult);
      [id(33), helpstring("method OnManageDBDestroyButton")]
      HRESULT OnManageDBDestroyButton([in]int nMyID,
               [in]int nDlgBarID,
               [in]int nButtonID,
               [in,out] long *phrResult);
      [id(34), helpstring("method OnManageDBDestroyDlgBar")]
      HRESULT OnManageDBDestroyDlgBar([in]int nMyID,
               [in]int nDlgBarID,
               [in,out] long *phrResult);
      [id(35), helpstring("method
            OnManageDBGetLastNonExclusiveDlgBar")]
      HRESULT OnManageDBGetLastNonExclusiveDlgBar([in]int nMyID,
               [in]int nWhere,
               [in]int* pnDlgBarID,
               [in,out] long *phrResult);
   };

Return codes

All return codes for these methods are HRESULT. This value will be E_FAIL if the Execute.dll object experienced some error during processing. This value will be S_OK if it processed the request successfully.

Code samples

The following code shows how to initialize the Execute.dll object from Visual Basic and how to implement the IStandardControlInterface::SetMainHelperData method:

'Object for calling sinks in IStandardControlInterface
'implementations of other controls.
Private objExecute As New EXECUTELib.ExecuteStdCtrl
Private lStandardControl As Long
Private lManageAXControls As Long
Private lManageDB As Long
Private lResult As Long
Private vInterface As Variant

Private Sub IStandardControlInterface_SetMainHelperData(_
   ByVal lManageActiveXControls As Long, _
   ByVal lManageDlgBars As Long, phrResult As Long)
   'Store the interface pointers for the container services.
   phrResult = S_OK
   lManageAXControls = lManageActiveXControls
   lManageDB = lManageDlgBars
   objExecute.SetMainHelperData lManageAXControls, lManageDB,_
      phrResult
   'Test method result.
   If (phrResult <> S_OK) Then
      MsgBox "Error [SetMainHelperData][" &
      CStr(phrResult) & _
      "]. Please ask technical support for assistance."
      Exit Sub
   End If
End Sub

The following code shows how to use the Execute.dll object from Visual Basic and how to implement the IStandardControlInterface::OnInitialDisplay method:

Private Sub IStandardControlInterface_OnInitialDisplay(_
   ByVal bstrTitle As String, _
   ByVal bstrDisplayText1 As String, _
   ByVal bstrDisplayText2 As String, _
   phrResult As Long)
On Error GoTo ErrorOnInitialDisplay
   'MsgBox "OnInitialDisplay from VB Parent Ctrl #" & CStr(ControlID)
   phrResult = S_OK
   
   'Set up a dialog bar.
   'General vars
   Dim lParentID As Long
   Dim bRetVal As Byte
   Dim strMsg As String
   Dim nDlgBarID As Long
         
   'Button vars
   Dim nButtonID As Long
   Dim bstrBtnText As String
   Dim strNum As String
         
   'Misc vars
   'For ManageACGetCtrlInfo()
   Dim hwndCtrlWnd As Long
   Dim hwndCtrlDlgBox As Long
   Dim hwndParentView As Long
   Dim hwndMainFrame As Long
   hwndCtrlWnd = 0
   hwndCtrlDlgBox = -1
   hwndParentView = 0
   hwndMainFrame = 0
   
   lParentID = -1
   hwndCtrlDlgBox = -1
         
   If (Len(bstrTitle) > 0) Then
      objExecute.OnManageACGetCtrlInfo ControlID, lParentID, _
            hwndCtrlWnd, hwndCtrlDlgBox, hwndParentView,_
            hwndMainFrame, phrResult
      'Test method result.
      If (phrResult <> S_OK) Then
         MsgBox "Error [OnManageACGetCtrlInfo][" & _
         CStr(phrResult) & _
         "]. Please ask technical support for assistance."
         Exit Sub
      End If
      If ((lParentID > 0) And (hwndCtrlDlgBox > 0)) Then
         'MsgBox "About to SetWindowText"
         bRetVal = SetWindowText(hwndCtrlDlgBox, bstrTitle)
      End If
   End If

   'Use this opportunity to create all necessary buttons on
   'aux dialog bar. Create the aux bar, if necessary.
   objExecute.OnManageDBCreateNewDlgBar ControlID, nDlgBarID, _
      CBRS_LEFT, False, phrResult
   'Test method result.
   If (phrResult <> S_OK) Then
         MsgBox "Error [OnManageDBCreateNewDlgBar][" & _
         CStr(phrResult) & _
         "]. Please ask technical support for assistance."
      Exit Sub
   End If

   'Create a few buttons.
   'Button A, Op #1
   bstrBtnText = "Aux " & CStr(ControlID) & ": A"
   objExecute.OnManageDBAddNewRadioButton ControlID, nDlgBarID,_
      nButtonID, False, True, bstrBtnText, 0, AUX_OP_1, phrResult

   'Button B, Op #2
   bstrBtnText = "Aux " & CStr(ControlID) & ": B"
   objExecute.OnManageDBAddNewRadioButton ControlID, nDlgBarID,_
      nButtonID, False, True, bstrBtnText, 0, AUX_OP_2, phrResult
   
   'Button C, Op #3
   bstrBtnText = "Aux " & CStr(ControlID) & ": C"
   objExecute.OnManageDBAddNewRadioButton ControlID, nDlgBarID,_
      nButtonID, False, True, bstrBtnText, 0, AUX_OP_3, phrResult
   
   'Button C, Op #4
   bstrBtnText = "CreateCtrl " & CStr(ControlID)
   objExecute.OnManageDBAddNewRadioButton ControlID, nDlgBarID,_
      nButtonID, False, True, bstrBtnText, 0, AUX_OP_4, phrResult
   
   'Button C, Op #5
   bstrBtnText = "DestroyCtrls " & CStr(ControlID)
   objExecute.OnManageDBAddNewRadioButton ControlID, nDlgBarID,_
      nButtonID, False, True, bstrBtnText, 0, AUX_OP_5, phrResult
   
   'Now, show the new dialog bar.
   objExecute.OnManageDBShowDlgBar ControlID, nDlgBarID, True,_
      phrResult
   
   Exit Sub
   
ErrorOnInitialDisplay:
   MsgBox "Error " & CStr(Err.Number) & ": " & Err.Description
   phrResult = E_FAIL

End Sub