Microsoft Corporation
January 30, 1998
Introduction
Design Overview
Design Detail
This document describes the container supporting the AMF BOSS System, version 1.0, Phase II client application.
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.
The two primary requirements for the client application are:
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.
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.
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.
Figure 12 identifies the primary container and control components and depicts the interaction between them.
Figure 12. Primary container and control components
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.
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.
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.
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.
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:
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
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);
};
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.
Additional text information to be displayed.
Additional text information to be displayed.
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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
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.
An optional message to be displayed at user's workstation when *pbCanClose is set to TRUE.
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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. |
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
|
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
|
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. |
Method | CallTopDlgBar |
Parameters | short nWhichBtn
The operation ID corresponding to a button in a horizontal dialog bar of style CBRS_TOP.
Reserved
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
If operation ID is the equivalent of either IDOK or IDCANCEL, then
|
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.
Reserved
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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.
Reserved
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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.
Reserved
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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. |
Method | GetRefToMe |
Parameters | VARIANT* pvMe
This control should store a
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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.
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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.
Specified by the control, this parameter helps to identify the data to be retrieved.
Specified by the control, this parameter helps to identify the size of the data to be retrieved.
Specified by control, the data retrieved
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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.
Specified by the control, this parameter helps to identify the data to be retrieved.
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.
Specified by control, the data being sent
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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. |
Method | GetMainButtonInfo |
Parameters | dBSTR *pbstrText
Button label
The Resource ID (container's resource) for the icon to display in the button.
Set to TRUE if the button has only text, and set to FALSE if the button has only an icon.
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
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.
This must be the same as the return code; it allows Visual Basic controls to access the return code. |
Return Value | HRESULT
|
Remarks | Never use this method. |
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);
};
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.
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.
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);
};
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.
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.
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);
};
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.
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