Resources And Information For ActiveX Control Writers

Welcome to the ActiveX Control Writer's Resource Kit! We hope to make this a one-stop shop for tips, tricks, and techniques to help you build great client-side ActiveX controls. The initial focus will be information on Microsoft and 3rd party control hosting environments, but over time you can expect to see additional topics of interest regarding control development tools, methodologies, and issues.

Other Useful Microsoft Links

OLE/COM Development

ActiveX SDK (PC) and ActiveX SDK (Macintosh)

Visual BASIC Control Creation Edition


Developing & Deploying ActiveX Controls

Click here to start

Table of Contents

Developing & Deploying ActiveX Controls

Overview

Definitions

Assumptions

Assumptions

1. Installation & Dependent Files

2. Initialization Time

3. Execution Performance

Development Tools

Visual Basic 5.0

Visual Basic 5.0

Visual Basic 5.0

Visual Basic 5.0 - Positives

Visual Basic 5.0 - Negatives

Visual Basic 5.0 - Summary

MFC

MFC - Positives

MFC - Negatives

MFC Summary

ActiveX Template Library 2.1

ATL - Positives

ATL - Positives

ATL - Negatives

ATL Summary

ActiveX SDK BaseCtl

ActiveX SDK BaseCtl - Positives

ActiveX SDK BaseCtl - Negatives

ActiveX SDK BaseCtl Summary

Visual J++ 1.1

Visual J++ Positives

VJ++ Negatives

VJ++ Summary

Development Decisions

Development Decisions

Development Decisions

Development Decisions

Deployment Decisions

Deployment Decisions

Intranet Subtleties (Simplicity)

Questions?


Building ActiveX Controls for Internet Explorer 4.0

This document covers features of Microsoft® Internet Explorer 4.0 that an ActiveX™ Control writer should take into account when targeting Internet Explorer 4.0 as a container. Some of the material in this document discusses existing technologies that have increased relevance with Internet Explorer 4.0; other sections discuss new technologies and services that are available to a control in Internet Explorer 4.0. For an in-depth description of these technologies and reference documentation, the Internet Client SDK is the best source of information. It is assumed that the reader is already familiar with ActiveX Controls and associated COM technologies.


Why Target Internet Explorer when Writing an ActiveX Control?

The primary reasons for the increased prevalence of the Internet should be fairly obvious; however, a point that might not immediately spring to mind is worthy of some consideration when planning. Internet Explorer is based on a component architecture; two of the main components are available for reuse as part of other applications as the WebBrowser control and the Mshtml.dll rendering engine. This means that an increasing number of Microsoft and third-party applications will be using the same underlying control container. Thus, if a control works well in Internet Explorer 4.0 it will also work well in future applications. This component reuse can already be seen in the Internet Explorer suite—Active Desktop and Outlook Express use the same HTML rendering engine that also is the host of ActiveX Controls.


Apartment Model Awareness

Although not a new issue for Internet Explorer 4.0, apartment model awareness is an important issue because of architectural changes in the multithreaded nature of Internet Explorer, Active Desktop, and Outlook Express, resulting in multiple instances of the container being more prevalent.

If a control is not apartment-model-aware, the control might not function correctly. At the very least, it will suffer from degraded performance because calls to the control will be marshaled. This is due to the creation of the control being handled differently by the system if the control marks itself as being apartment-model-aware.

There are two relatively simple steps involved in making a control apartment-model-aware:

  • Mark the control in the registry as "Apartment". This allows the system to recognize that the control understands the world of multithreading and to create it accordingly in its own apartment.
  • Protect global resources. When a resource or data that is shared among instances of the control is being accessed, it should be protected so that other instances of the control do not attempt to access it at the same time. For example:

    ::EnterCriticalSection(&g_cs);
    // Access global data
    // ....
    ::LeaveCriticalSection( &g_cs );


OC96 and Windowless Controls

The OC96 (or OLE Controls '96) specification is not new, but full support is only now appearing in mainstream applications such as Office 97 forms and Internet Explorer 4.0. Therefore, this specification deserves further attention. It includes many performance enhancements because one of the primary driving factors with this specification was to improve the performance of controls. One of the key features is support for windowless controls. Not only does this improve performance, but it also allows a control to have transparency and irregular shapes and thus partake in overlapping 2D layout with specific z-order. All the enhancements are designed to be compatible with existing OLE Controls technology, so a backward-compatible control should be easy to implement.

Key features of OC96 include:

  • Delayed activation. Delaying the activation of a control means that a page can instantiate and be ready for interaction with the user faster, particularly if there are multiple controls on the page. A new interface, IPointerInactive, allows a control to remain inactive but still interact minimally with the mouse and drag and drop. Although the control still activates, it only does so as the result of some interaction with the user.
  • Windowless. By not having its own window, a control can make efficient use of its container's window. Performance advantages thus are brought about by fewer resources being consumed and faster activation/deactivation. New interfaces are introduced to support windowless controls. The main new interfaces are IOleInPlaceObjectWindowless and IOleInPlaceSiteWindowless, which derive from their namesakes without the Windowless extension. When drawing itself, a control asks the IOleInPlaceSiteWindowless interface for a device context, and returns the device context after drawing. Although windowless support of a control is often seen in terms of providing transparency for interesting visual effects, supporting windowless modes of operation will further improve performance.
  • Hit detection. To complete the visual benefits of transparency that a windowless control can provide, hit detection is available so that a control can have an irregular shape. If the container detects that the rectangular extent occupied by a windowless control has been hit, it calls IViewObjectEx::QueryHitPoint (another new interface for windowless controls). The control then determines if it has been hit and returns an indication to the container.
  • Quick activation. To further speed activation of a control, a new interface, IQuickActivate is introduced and can optionally be implemented by the control. A method on this interface is called by the container to pass a structure to the control, and to receive a structure back from the control. These structures contain interface pointers frequently needed for controls and ambient properties. Using these structures to pass often-needed information during activation can cut own on the handshaking negotiation that frequently takes place when instantiating a control.


Accessing Dynamic HTML

Internet Explorer 4.0 makes a new capability available to components—to access the Dynamic HTML object model of the document in which the control is hosted. This allows a control to read the contents of the document and change it, because all the capabilities of the object model are available. Accessing the object model is very simple and consists of the following two steps:

  1. Call IOleClientSite::GetContainer. This returns the IOleContainer interface of the host of the control, and is an existing OLE interface method.
  2. Call QueryInterface on the IOleContainer interface for the IHTMLDocument2 interface.

The IHTMLDocument2 interface is the interface for the Document object, which is the object that acts as the root of all access to the object model. The following bit of code (written in ATL 2.0) shows accessing the object model to set the background color of the document to pink, and is equivalent to document.body.bgcolor = "pink".

// Get the document
CComPtr<IOleContainer> spContainer;
m_spClientSite->GetContainer(&spContainer);
CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> spDoc(spContainer);
CComPtr<IHTMLBodyElement> spBody;
if (spDoc)
    hr = spDoc->get_body(&spBody);
if (spBody)
    hr = spBody->put_bgColor(CComBSTR(_T("pink")));

It is possible to perform any of the manipulations available to script in Internet Explorer 4.0, and some functions that aren't possible from script due to security restrictions that do not apply to ActiveX Controls. A recommendation for development here is to first prove a concept by using script (JScript or VBScript, whichever is your favorite) and then translate that to interface-level manipulation.

Note One of the steps in this example is likely to change in subsequent preview releases of Internet Explorer 4.0. In the future, the get_body method will produce an IHTMLElement* from which a QueryInterface call will be necessary to get the IHTMLBODYElement. The reason for this change is to allow for frames as well as a body element. This change has not been made for the first preview release.

It is important to note that any of the new interfaces introduced with Internet Explorer 4.0 are still subject to change, and will not be frozen until the final product is released.


Multimedia Services

There are several multimedia effects available in Internet Explorer 4.0 that a control can take advantage of. A number of multimedia effect controls ship with Internet Explorer 4.0; however, these services are also available to third-party controls. These include pixel level manipulation (soon to introduce DirectDraw support), timer and synchronization services, and visual filters and transitions. The full specifications and samples are included in the Internet Client SDK.


Delivery

When delivering your control, use CAB files and sign your controls. Everyone should be well aware of the recent security issues that have received great attention. Advice to end users is not to download executable content unless it is signed, so if you do not sign your control you cannot expect users to download your product. Using CAB files also creates a better end-user experience because multiple files can be downloaded, with a single certificate presented to a user in advance of download. Details of this technology are in the Internet Client SDK.


Appendix A: Differences Between Versions, and Other Guidelines

This section details the known differences in control hosting between Internet Explorer 3.0 and Internet Explorer 4.0, and presents other guidelines for creating controls. Internet Explorer 3.0 hosted controls in a slightly more relaxed fashion than Internet Explorer 4.0; for Internet Explorer 4.0 the specifications for controls and COM interfaces have been followed more stringently. This allows Internet Explorer 4.0 to host a greater variety of controls; however, it does mean that some controls that functioned correctly in Internet Explorer 3.0 may no longer have identical functionality in Internet Explorer 3.0. Wherever possible, these differences have been minimized.

  • If a control fires an event from a thread that it creates, rather than from the thread in which it was created, the event will never make it. All calls from the control must be made on the creation thread.
  • Internet Explorer 4.0 calls FindConectionPoint on a control to hook up events even if the control exposes no events. A control should be written to expect this call.
  • As previously mentioned, non-apartment-model-aware controls might not function properly.
  • The VBScript engine no longer passes parameters to controls ByVal; they are now usually passed ByRef. Standard practice when passing a variant is to check how it is being passed before retrieving the value. If a control relies on a parameter being passed ByVal, it might not work.
  • Internet Explorer 3.0 sent DoVerb Show and Hide to controls in addition to InPlaceActivate and InPlaceDeactivate. Internet Explorer 4.0 no longer sends the verbs.
  • A control should use the WM_CONTEXTMENU message to hook in for context menus and not trigger the right-mouse-up message.
  • A control should not forcefully UIActivate itself, or assume itself to be UIActive. A control that needs the focus should have it set by the script of the document on which it is hosted. This is an area that the page author is in control of. In the case of multiple controls on a page, a UIActivate battle could cause strange results, and in the case of a control that is instantiated at the bottom of a large page, an ugly user experience might result as the control is forcefully scrolled into view.
  • It is not good practice for a control to bring up modal dialog boxes unless in immediate response to some user interaction. For example, if a control is asynchronously downloading data in the background and the link fails, a control should fire an Error event for the script to be able to react to and/or show the error in its own rendering. Bringing up a dialog box under such circumstances creates a poor user experience and might upset applications hosting the Internet Explorer 4.0 components.

© 1997 Microsoft Corporation. All rights reserved. Legal Notices.


ActiveX control support in Office 97 documents, worksheets and slides

The issues discussed here apply to ActiveX controls used with Office 97 applications. Some of these issues apply only to specific applications within the Office 97 and are called out as appropriate.

1. The ActiveX control container implementations in Word, Excel and PowerPoint 97 use the IDataObject interface and not IViewObject to draw controls. ActiveX controls (from Microsoft or other vendors) that do not support IDataObject but instead require IViewObject support in their containers will not work in Word, Excel or PowerPoint 97 documents. Access 97 does not have this limitation and can host controls that do not support IDataObject. Note that Microsoft Forms (used to create custom user dialogs in Microsoft Word, Microsoft Excel, Microsoft Outlook, and Microsoft PowerPoint 97) do not have this restriction either.

You need to contact the control vendor to determine whether an ActiveX control requires the IViewObject interface to be supported in its container.

2. ActiveX controls may behave unpredictably when seen in multiple views of the same document. For an ActiveX control to display and function properly in multiple views of the same document (windows or panes), the container application should support the IViewObject interface. Since Word, Excel and PowerPoint 97 do not support this interface (as discussed in 1 above), the behavior of an ActiveX control that is viewed in two different windows (e.g., using Window.New Window, or by using the splitter pane) may be unpredictable.

3.There is a class of ActiveX controls called simple frame controls that implement and interface called ISimpleFrame and will only work inside containers that support the ISimpleFrameSite interface. Access, Word, Excel and PowerPoint 97 do not support ISimpleFrameSite and will not be able to host such controls. This is also true for Microsoft Forms.

4. In-place limitations

a) When Excel 97 is in-place active inside a container, ActiveX controls in Excel’s worksheets cannot be activated. When the user clicks on an ActiveX control while Excel 97 is in-place active, the following alert will appear – “This control can only be used while the sheet is in a Microsoft Excel window. Open into a Microsoft Excel Window?”. This alert will have Yes and No buttons; choosing No will result in no action, choosing Yes will open the embedding in its native Excel application window where the control will be fully functional .

Note that ActiveX controls in the in-place active Excel worksheet will be displayed correctly and can even be selected in Design Mode – these controls are simply restricted from being in-place active. If it is important that controls be fully functional when an Excel sheet is in-place active, developers have the option of using built-in Excel controls available on the Forms toolbar .

b) Whenever an ActiveX control in an in-place active Word document gets UI activation (e.g., when the user clicks on a button control on a Word document embedded in Internet Explorer), Word’s toolbars and menus will un-merge themselves from those belonging to the container. When the focus returns to the Word document (e.g., the same user clicks on text anywhere in the same Word document) the Word toolbars and menus will re-merge with the container ones. This behavior may result in UI-flashing when dealing with a Word document with ActiveX controls being activated as a Binder section or as an ActiveX document inside of Internet Explorer.

5. Excel Charts cannot contain ActiveX controls

ActiveX controls cannot be inserted into Excel 97 charts. Controls may be placed on top of chart objects that are embedded in a worksheet, but such controls will not be active when the chart is activated.

6. “Component Categories” are not supported by Word, Excel or PowerPoint 97.

Word, Excel and PowerPoint 97 do not support ActiveX control categories. The implication is that controls that show up in the UI to insert non-Office controls may not necessarily work in these Office applications. There is no UI-filtering based on component categories, so it is possible, for instance, for an ISimpleFrame control to show up in the “More Controls” list for Word even though it would not work there.

Access 97 supports component categories, controls that Access does not support will not show up in their control list. This functionality requires that the control vendor building controls that support categories.

7. No automatic download of ActiveX controls embedded in Office 97 documents when browsing using Internet Explorer

While browsing an intranet web with a mixture of HTML and Office 97 documents using Internet Explorer 3.0 (or higher), ActiveX controls embedded in Office 97 documents do not get automatically downloaded to the client machine. On the other hand, IE ensures that this happens automatically in the case of HTML pages that have ActiveX controls in them. The one case where this will work is when the client machine has Office 97 installed and the document in question makes exclusive use of the ActiveX controls that ship in the Office 97 box.

8. Miscellaneous limitations

The following additional ActiveX control features are not supported in Access, Word, Excel or PowerPoint 97.

  • Restarting the machine with control active - Selecting Shut Down from the Start menu with an ActiveX control UI Active will result in the message "Cannot quit Microsoft Excel" being displayed. Workaround is to deactivate any UI Active control before shutting down the system.

  • ListFillRange property set to a named range does not reflect col/row changes - Changing the value of a named range does not automatically send a change notification to a bound control. Workaround is to reenter the value of the ListFillRange property.

  • Failing control insertion dirties workbook - If a control fails to insert, the dirty state of the workbook is not reset. Closing the workbook will result in a "Save Changes?" alert being displayed. Workaround: None.

  • Activation of an ActiveX control is not recorded. Recording the UI Activation of a control (i.e. a mouse click on the control while in run mode) is not supported. Also, property changes via the Properties window are not recorded.

  • Register Custom Control dialog doesn't automatically try default extensions. When using the Register Custom Control dialog, entering a filename without the extension could result in the control not being found. Workaround is to include the file's extension when typing in a filename.


Testing ActiveX Controls in Office97
Ross Smith (rosss@microsoft.com)

Office Test Team

March, 1997


Table of Contents

User Interface

Test Case: C1.00.00

Test Case: C2.00.00

Test Case: C2.01.00

Test Case: C2.02.00

Test Case: C2.03.00

Test Case: C2.04.00

Test Case: C2.05.00

Insertable controls

Test Case: C3.00.00

Test Case: C3.01.00

Test Case: C3.02.00

Test Case: C3.03.00

Test Case: C3.04.00

VBA Design Mode - Tools References

Test Case: C4.00.00

Test Case: C4.01.00

Object Browser

Test Case: C5.01.00

Method and Property Verification through User Interface

Test Case: C6.00.00

Test Case: C6.01.00

VBA Sample Code

Test Case: C7.00.00

Test Case: C7.01.00

Test Case: C7.02.00

Test Case: C7.03.00

Object Functionality

Test Case: C8.00.00

Test Case: C8.01.00

Test Case: C8.02.00

Appendix A - Viewing the Control Toolbox in Outlook


Test Case: C1.00.00

Title: Registering Controls through Control Toolbox

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can be registered via the control toolbox. There is no fundamental difference between registering a control this way as opposed to RegSvr32 or the OLE Control Test Container, or using the development environment itself.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Scroll to bottom of list and choose "Register Custom Control"
  • Browse to find the OCX or DLL to register
  • Click OK
  • Note: there is no visible feedback unless the control is unable to be registered
  • Verify the control has been registered by choosing Register Custom Control again and searching for control in the list.

Summary:

This test verifies that the control can be registered through Office. If there are problems, try registering with REGSVR32 (REGSVR32 myctrl.ocx), or the OLE Control Test Container that ships with Visual C++.


Test Case: C2.00.00

Title: Adding Controls: Standard

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can be added via the control toolbox. Note that the control must be registered before it can be added.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Scroll to find the control to Add
  • Click the control to add
  • Powerpoint and Excelrequire the control location to be dragged out on the document/slide/form. Word and Access will add using a default size.

Result:

Control will be added to document/slide/sheet.

Summary:

This test verifies that a control can be added to an Office97 document using the control toolbox.


Test Case: C2.01.00

Title: Adding Controls: Inline (Microsoft Word)

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can be added inline in a Word document via the control toolbox. Note that the control must be registered before it can be added.

Steps:

  • Start Microsoft Word 97
  • Create new document
  • Type some text
  • Position the cursor in between characters
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Scroll to find the control to Add
  • Click the control to add while holding the shift key.

Result:

Control will be added to document in line (in between text characters).

Summary:

This test verifies that a control can be added to an Word 97 document inline using the control toolbox.


Test Case: C2.02.00

Title: Adding Controls: Floating (Microsoft Word)

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

THIS IS THE SAME AS THE STANDARD CASE FOR WORD:

This test verifies that the control can be added via the control toolbox. Note that the control must be registered before it can be added.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Scroll to find the control to Add
  • Click the control to add

Result:

Control will be added to document/slide/sheet floating above text. Drag the control to verify that it is floating.

Summary:

This test verifies that a control can be added to a Word 97 document floating in the text using the control toolbox.


Test Case: C2.03.00

Title: Adding Controls: No IDataObject support

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

Word97, Excel97, and Powerpoint97 apps use IDataObject, not IViewObject to draw controls, so controls that do not contain support for IDataObject will not work in Office97. This test is more of a container test, but is included here for controls that do not support IDataObject. Note that Access97 does not have this limitation.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Scroll to find the control to Add
  • Click the control without IDataObject support to add it to the document

Result:

Control will not be added and an application specific error message will inform the user about the lack of IDataObject support.

Application | Invalid License Error Message
Excel | Cannot Insert Object
Word | The server application, source file, or item cannot be found. Make sure the application is properly installed, and that it has not been deleted, moved, or renamed.
Powerpoint | Cannot create ActiveX Control which does not support IDataObject
Access | you don't have the license required to use this ActiveX control.... The control could not be created because it is not properly licensed.

Summary:

This test verifies that a control contains IDataObject support by adding it to an Office97 document using the control toolbox.


Test Case: C2.04.00

Title: Adding Controls: Simple Frame (ISimpleFrameSite) Controls

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

Some controls implement ISimpleFrame and will only work inside containers that support the ISimpleFrameSite interface. Word, Excel, and Powerpoint97 do not support ISimpleFrameSite and will not be able to host such controls. Note that Access97 does not have this limitation - that is, it supports the interface.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Scroll to find the control to Add
  • Click the control that requires ISimpleFrameSite interface implementation (that is not present in Office97).

Result:

Control will not be inserted.

Summary:

This test verifies or demonstrates that a control that requires ISimpleFrameSite support will not work.


Test Case: C2.05.00

Title: Adding Controls: Verifying Missing License

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that a control that requires a license will behave correctly when license information is missing.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Scroll to find the control to Add
  • Click the control that requires license.

Result:

Error Message, depending on application

Application | Invalid License Error Message
Excel | Cannot Insert Object
Word | The server application, source file, or item cannot be found. Make sure the application is properly installed, and that it has not been deleted, moved, or renamed.
Powerpoint | License Information for this component cannot be found. You do not have an appropriate license to use this functionality in the design environment.
Access | you don't have the license required to use this ActiveX control.... The control could not be created because it is not properly licensed.

Summary:

This test verifies that a control that requires a license fails appropriately when license information is not present.


Insertable controls

These tests relate to controls that have the 'Insertable' key present in the registry. Note also that Office97 does not recognize Component Categories.


Test Case: C3.00.00

These tests relate to controls that have the 'Insertable' key present in the registry. Note also that Office97 does not recognize Component Categories.

Test Case: C3.00.00

Title: Insertable Controls: Standard

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can be added via the control toolbox. Note that the control must be registered before it can be added.

Steps:

  • Start Office97 app
  • Create new document
  • Choose Insert Object
  • Select the appropriate control
  • Click OK

Result:

Control will be added to document/slide/sheet.

Summary:

This test verifies that an Insertable control can be added to an Office97 document using the Insert Object dialog.


Test Case: C3.01.00

Title: Insertable Controls: As Icon - Default

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can be added via the control toolbox. Note that the control must be registered before it can be added.

Steps:

  • Start Office97 app
  • Create new document
  • Choose Insert Object
  • Select the appropriate control
  • Click Display As Icon (note: default icon is selected from the OLE DLL)
  • Click OK

Result:

Control will be added to document/slide/sheet, with iconic presentation.

Summary:

This test verifies that an Insertable control can be added as an icon to an Office97 document using the Insert Object dialog.


Test Case: C3.02.00

Title: Insertable Controls: As Icon - Using Icon in OCX

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can be added via the control toolbox. Note that the control must be registered before it can be added.

Steps:

  • Start Office97 app
  • Create new document
  • Choose Insert Object
  • Select the appropriate control
  • Click Display As Icon (note: default icon is selected from the OLE DLL)
  • Click Change Icon
  • Browse to find OCX selected and click OK to close Change Icon dialog
  • Click OK to close Insert Object dialog

Result:

Control will be added to document/slide/sheet as an icon, using the icon from the OCX.

Summary:

This test verifies that an Insertable control can be added as an icon to an Office97 document using the Insert Object dialog, and that the icon can be extracted from the OCX.


Test Case: C3.03.00

Title: Insertable Controls: Inline (Microsoft Word)

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can be added inline in a Word document via the control toolbox. Note that the control must be registered before it can be added.

Steps:

  • Start Microsoft Word 97
  • Create new document
  • Type some text
  • Position the cursor in between characters
  • Choose Insert Object
  • Select the appropriate control
  • Click OK while holding the shift key.

Result:

Insertable Control will be added to document in line (in between text characters).

Summary:

This test verifies that a control can be added to an Word 97 document inline using the Insert Object dialog.


Test Case: C3.04.00

Title: Insertable Controls: Floating (Microsoft Word)

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

THIS IS THE SAME AS THE STANDARD CASE FOR WORD:

This test verifies that the control can be added via the Insert Object dialog. Note that the control must be registered before it can be added.

Steps:

  • Start Office97 app
  • Create new document
  • Start Microsoft Word 97
  • Create new document
  • Choose Insert Object
  • Select the appropriate control
  • Click OK

Result:

Control will be added to document/slide/sheet, floating above the text. Drag it around to verify.

Summary:

This test verifies that a control can be added to a Word 97 document floating in the text using the Insert Object dialog.


Test Case: C4.00.00

Title: Add Reference from OCX file

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can referenced from the VBA/VBA environment.

Steps:

  • Start Office97 app
  • Create new document
  • Choose Tools Macro Visual Basic Editor (Alt+F11)
  • Inside the Visual Basic Editor, choose Tools References
  • Drop down file filter and choose ActiveX controls (*.OCX)
  • Browse to find OCX file
  • Click OK to add reference

Result:

Reference will be added to Visual Basic environment and to the document. Verify refernce in tools references dialog. Use the Object Browser (F2 in VBE) to verify the existing of the control in the document.

Summary:

This test verifies that a reference can be added to the document directly from the OCX file.


Test Case: C4.01.00

Title: Add Reference from TLB, OLB, DLL file

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

This test verifies that the control can referenced from the VBA/VBA environment from the type library.

Steps:

  • Start Office97 app
  • Create new document
  • Choose Tools Macro Visual Basic Editor (Alt+F11)
  • Inside the Visual Basic Editor, choose Tools References
  • Drop down file filter and choose ActiveX controls (*.TLB, OLB, DLL)
  • Browse to find TLB, OLB, DLL file
  • Click OK to add reference

Result:

Reference will be added to Visual Basic environment and to the document. Verify refernce in tools references dialog. Use the Object Browser (F2 in VBE) to verify the existing of the control in the document.

Summary:

This test verifies that a reference can be added to the document from the TLB, OLB, DLL file..


Test Case: C5.01.00

Title: Verify properties in Object Browser

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

These are steps on verifying control properties and methods using the Object Browser.

Steps:

  • Start Office97 app
  • Create new document
  • Choose Tools Macro Visual Basic Editor (Alt+F11)
  • Inside the Visual Basic Editor, choose View Object Browser (F2)
  • Search and find control to verify (note: this only works with registered controls)
  • Verify classes and members of control

Result:

All methods and properties that should be visible are available in the Object Browser.

Summary:

The Object Browser tool is a utility to help verify available methods and properties in a control.


Test Case: C6.00.00

Title: Verify AboutBox in Control Toolbox

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

These are steps on verifying control properties and methods using the Control Toolbox

Steps:

  • Start Office97 app
  • Create new document
  • Add a control
  • right click and select Properties
  • Click About button

Result:

AboutBox stock method will be called on control

Summary:

This tests whether the Office application can invoke the AboutBox method on the control.


Test Case: C6.01.00

Title: Verify Property Verb (PropertyPage) from Control Toolbox

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control. Container must have Control Toolbox
Sample Apps: | Microsoft Word 97, DBGrid Control
Test Category: | CONTROL

Overview:

These are steps on verifying control properties and methods using the Control Toolbox

Steps:

  • Start Office97 app
  • Create new document
  • Add a control
  • Right click and select Properties
  • Click Custom button

to invoke property page

Result:

Control's property page, if available, will be displayed

Summary:

This tests whether the Office application can invoke the Property verb to set properties through the property page.


Test Case: C7.00.00

Title: Calling Method, Setting Property in VBA in Word

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control
Sample Apps: | Microsoft Word 97, MFC Control Wizard generated control
Test Category: | CONTROL

Overview:

This sample code illustrates adding a 'test' control, and calling methods and setting properties on that control from VBA. Obviously the properties and methods will vary by control.

Steps:

  • copy and paste this code into a VBA module
  • modify the control classtype, properties, and methods to reflect those of the control.

'------------------------------------

' Word

Sub Test()

Set myCB=ActiveDocument.Shapes.AddOLEControl(ClassType:="O97CTRL.O97TestCtrl.1")

With myCB.OLEFormat.Object

.AboutBox

.MyMethod

Set myObj = .Object

End With

With myObj

.Caption = "My Caption"

Debug.Print .Caption

Debug.Print Str(.ReadyState)

End With

End Sub

Result:

Control added to document, properties and methods invoked successfully.

Summary:

This tests whether the control can be manipulated from VBA.


Test Case: C7.01.00

Title: Calling Method, Setting Property in VBA in Excel

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control
Sample Apps: | Microsoft Excel97, MFC Control Wizard generated control
Test Category: | CONTROL

Overview:

This sample code illustrates adding a 'test' control, and calling methods and setting properties on that control from VBA. Obviously the properties and methods will vary by control.

Steps:

  • copy and paste this code into a VBA module
  • modify the control classtype, properties, and methods to reflect those of the control.

'------------------------------------

'Excel

Sub Test()

Set myDocument = Worksheets(1)

myDocument.Shapes.AddOLEObject Left:=100, Top:=100, Width:=100, _ Height:=200, ClassType:="O97CTRL.O97TestCtrl.1"

ActiveSheet.OLEObjects(1).Object.AboutBox

ActiveSheet.OLEObjects(1).Object.MyMethod

Debug.Print Str(ActiveSheet.OLEObjects(1).Object.ReadyState)

OLEObjects(1).Object.Caption = "test1"

Debug.Print OLEObjects(1).Object.Caption

End Sub

Result:

Control added to sheet, properties and methods invoked successfully.

Summary:

This tests whether the control can be manipulated from VBA.


Test Case: C7.02.00

Title: Calling Method, Setting Property in VBA in PowerPoint

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control
Sample Apps: | Microsoft Powerpoint97, MFC Control Wizard generated control
Test Category: | CONTROL

Overview:

This sample code illustrates adding a 'test' control, and calling methods and setting properties on that control from VBA. Obviously the properties and methods will vary by control.

Steps:

  • copy and paste this code into a VBA module
  • modify the control classtype, properties, and methods to reflect those of the control.

'------------------------------------

'Powerpoint

Sub Test()

Dim p As Presentation, l As Integer, t As Integer, w As Integer, h As Integer

Set p = Presentations.Add(True)

With p.Slides.Add(1, ppLayoutBlank).Shapes

l = p.PageSetup.SlideWidth / 4

t = p.PageSetup.SlideHeight / 4

w = p.PageSetup.SlideWidth / 2

h = p.PageSetup.SlideHeight / 2

With .AddOLEObject(Left:=l, Top:=t, Width:=w, Height:=h, ClassName:="O97CTRL.O97TestCtrl.1")

With .OLEFormat.Object

.Caption = "This is a button"

.AboutBox

.MyMethod

End With

End With

End With

End Sub

Result:

Control added to slide, properties and methods invoked successfully.

Summary:

This tests whether the control can be manipulated from VBA.


Test Case: C7.03.00

Title: Calling Method, Setting Property in VBA in Access

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control
Sample Apps: | Microsoft Access97, MFC Control Wizard generated control
Test Category: | CONTROL

Overview:

This sample code illustrates adding a 'test' control, and calling methods and setting properties on that control from VBA. Obviously the properties and methods will vary by control.

You cannot programmatically create an ActiveX control of any particular class on an Access form. Access has a CreateControl function that permits you to create a generic ActiveX Control, but it does not let you specify the control's class. You can however copy the OleData property of an existing control

into other controls.

This means that you must use the Access UI to place at least one instance of your

ActiveX Control onto any form somewhere in your Access database. Once you've done that,

you will be able to programmatically place copies of that control onto any number of Access forms

at runtime.

for the purpose of these tests, we are just finding the control on an existing "form1", where we have added it by hand, and calling it's custom methods and setting properties

Steps:

  • copy and paste this code into a VBA module
  • modify the control classtype, properties, and methods to reflect those of the control.
  • See Notes Above

'------------------------------------

'Access

Sub Test()

'You cannot programmatically create an ActiveX control of any

'particular class on an Access form. Access has a CreateControl

'function that permits you to create a generic ActiveX Control,

'but it does not let you specify the control's class.

'You can however copy the OleData property of an existing control

'into other controls.

'This means that you must use the Access UI

'to place at least one instance of your

'ActiveX Control onto any form somewhere in your

'Access database. Once you've done that,

'you will be able to programmatically place

'copies of that control onto any number of Access forms

'at runtime.

'for the purpose of these tests, we are just finding the control on an

'existing "form1", where we have added it by hand,

'and calling it's custom methods and setting properties

Dim frm As Form

Set frm = Forms("form1")

Dim ctl As Control

Dim b As Integer

' Enumerate Controls collection.

For Each ctl In frm.Controls

' Check to see if control is Custom control

If ctl.ControlType = acCustomControl Then

Debug.Print ctl.Name

b = ctl.MyMethod()

ctl.Caption = "test"

End If

Next ctl

End Sub

Result:

Control added to slide, properties and methods invoked successfully.

Summary:

This tests whether the control can be manipulated from VBA.


Test Case: C8.00.00

Title: Object Presentation in different views

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control
Sample Apps: | Microsoft Office97 application, DBGrid Control
Test Category: | CONTROL

Overview:

This test covers presentation of the control in multiple views. Note that Word, Excel, and Powerpoint do not support IViewObject and therefore will have unpredictable results in Window New Window and the splitter pane. Access97 does support this interface and will not have the problems.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Add control to the document/slide/worksheet
  • Choose View and select each option, then verify control presentation. Options will vary depending upon the application.

Summary:

This test verifies that the control is displayed correctly in multiple views of the document.


Test Case: C8.01.00

Title: Save and Open Document with control

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control
Sample Apps: | Microsoft Office97 application, DBGrid Control
Test Category: | CONTROL

Overview:

This test covers the ability to save and reload a document with a control in it.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Add control to the document/slide/worksheet
  • Save the document
  • Close the document
  • Re-open the document and verify control properties and methods

Summary:

This test verifies that the control can be saved and reloaded along with the document.


Test Case: C8.02.00

Title: InPlace Activation of Document with control

Platforms: | Windows NT 3.51, 4.0, Windows 95
Requirements: | Office97 app, OLE control.
Sample Apps: | Microsoft Office97 application, DBGrid Control
Test Category: | CONTROL

Overview:

This test covers the ability to view or use a control while the application is in place active.

Note: ActiveX controls in an Excel worksheet will be disabled when Excel is in-place active, i.e., when Excel is activated in-situ as an OLE embedding inside containers like Word or as an ActiveX document inside Internet Explorer or in Office Binder.

Steps:

  • Start Office97 app
  • Create new document
  • Choose View Toolbars and ensure Control Toolbox is visible
  • Click on bottom right button for "More Controls"
  • Add control to the document/slide/worksheet
  • Choose Insert Object and insert another object type that supports inplace activation (Word, Excel)
  • Verify properties and control

Summary:

This test verifies that the control can be manipulated while inplace active. Note: If control is added to embedded object, presentation is blank when embedded object is deactivated.


Appendix A - Viewing the Control Toolbox in Outlook

Overview:

Outlook requires a unique set of steps to view the Control Toolbox

Steps:

  • Create new mail message
  • Choose Tools, Design Outlook form
  • Click on Control toolbox icon to display Toolbox
  • Right click on Toolbox and choose Custom Control
  • Select control then drag it into form


ActiveX Control Features Supported in MS Access 97

Microsoft Access 97, as an ActiveX control container, requires a control to support a base set of interfaces. Other interfaces and component categories are optionally supported in Microsoft Access 97, and still others are not supported at all. The following information will assist you in creating ActiveX controls with the features best suited for use in Microsoft Access 97 databases.

ActiveX Interfaces Required by Microsoft Access 97

  • IOleObject, which is the principal means by which an embedded control communicates with the Microsoft Access 97 container and vice versa.

  • IPersistStorage, which defines methods that enable Microsoft Access 97 to load and save the control. Microsoft Access 97 uses the methods in this interface to initialize the control, and to instruct the control to perform save operations or to release its storage.

  • IViewObject, which enables a control to display itself directly. Methods in this interface, for example, allow you to draw the control on the screen.

  • IOleControl, which provides features for supporting keyboard mnemonics, ambient properties, and events in control objects.

ActiveX Component Categories Supported in Microsoft Access 97

  • Simple Databinding, which is the ability to bind one property of a control to a field in a table.

  • The Controls component category.

ActiveX Component Categories and Interfaces Not Supported in Microsoft Access 97

  • Simple Frame Site Containment, which is the ability of an ActiveX control to contain other controls. Microsoft Access does not support the ISimpleFrameSite interface, which applies to any control created with Microsoft Visual Basic Control Creation Edition version 5.0 that has its ControlContainer property set to True.

  • Advanced Databinding, which allow more complex databinding scenarios than simply binding a single property of a control to a field in a table.

  • The Visual Basic private interfaces, IVBFormat and IVBGetControl. IVBFormat allows a control to better integrate into the Visual Basic environment when formatting data; IVBGetControl, for example, allows a control to enumerate other controls on a Visual Basic form with finer scope than what is capable with IOleContainer.

  • Internet aware controls; IServiceProvider and IBindHost interfaces are not implemented in Microsoft Access.

  • Windowless controls, which are controls that do not operate in their own window, and require Microsoft Access 97 to offer a shared window into which the control can draw.

    NOTE: Many windowless controls are designed to be compatible with containers that do not support this feature by creating their own window in those situations. Microsoft Access 97 may be able to use a windowless control that offers that capability.

  • Minimal support controls, which are those ActiveX controls that only support the IUnknown interface (or any subset of Interfaces that are required above).


Testing Active X Controls in Access97

Microsoft

Access97

Testing ActiveX Controls in Microsoft Access ‘97

Scott Oveson (ScottOv@Microsoft.com)

Access Test Lead

Microsoft Corporation

March 1997


Table of Contents

Introduction

Registration

Licensing

Control Initialization

Controls and the Clipboard

Design Mode State

Design-Time and Run-Time Property Persistance

Invisible-At-Runtime Controls

Print Preview of Access Forms and Reports

Custom Control Property Pages

Property Merging in the Access Property Sheet

Simple Data Binding

Event Procedures

Object Browser

Accessing properties and Methods Programmatically

Instantiating Control Instances With Events Programatically

Mnemonics and Key Handling

International Issues

Help Testing


Introduction

This document is a compilation of tips, common bugs, and interesting information relating to using and testing ActiveX Controls in Access ’97. Specifically, it calls attention to common bugs that may appear in ActiveX Controls when hosted in Microsoft Access. This is not a full test plan or comprehensive guide to everything that is tested with respect to ActiveX Controls and Access as a control container. Rather, it is an overview that highlights common mistakes, anomalies, and bugs found in ActiveX Controls as they interact with Access. It will also provide some insight into how Access interacts with controls in specific cases and some pitfalls to avoid when developing your control. This will improve the quality of interaction between ActiveX Controls and Access by arming the control developer with knowledge about scenarios that may be troublesome.


Registration

Access ’97 uses Component Categories (comcat.dll) to filter the list of controls that may be inserted, since controls may require specific interfaces that not all control containers are required to support.

When the Tools | ActiveX Controls... menu item is selected in Access, a list of available controls on the system is shown. (NOTE: Previous versions of Access scanned through a portion of the Windows registry looking for controls by looking for the Control key and the InprocServer32 key. Since ComCat in Access ’97 is providing a list of controls that match the specifications we are requesting, it returns a list of controls that we show as currently registered that we support based on this info. This however uncovers a bug in the ComCat component; they show 16 bit controls in this list even though a 32-bit container is querying this information.) When the user chooses to register or un-register a control, Access simply calls the controls self registration or un-register entry points. This should behave similarly to the case where the user is using regsvr32 to register or un-register the control. The important note here is that you should be able to register your control in this dialog (and un-register it) given that it doesn’t require some special setup procedure beyond calling the entry point for self-registration.

Access requests that ComCat filter out controls that it cannot support due to requirements for interfaces that are not implemented. For example, the Microsoft Data Bound List Controls in DBLIST32.OCX don’t appear in the list of controls to register, un-register, or insert on a form or report since these controls require that the Visual Basic interfaces for advanced data-binding be implemented by the container. This control has listed this component category as a requirement for its use. Controls that don’t have this component category flagged as a requirement will not be filtered out by ComCat, and therefore will show up in this list even though they may not work in the container. An example is the Apex Databound Grid control. This control appears in the list of insertable controls when an Access form or report is in design view since it shipped before the ComCat component was completed. When the user tries to insert the control into Access, an error occurs. Access has special cased this particular control since it ships in Visual Basic, however, other controls that require these interfaces will simply propagate an error back to the host at some point (either at insertion time or browse time depending on when the interface is queried).


Licensing

Verify that your control can be used on and Access form and report when the form is view on a system that does not have the design-time license. Also, ensure that the appropriate error is displayed when the user does try to design a form or report that contains the control and the license is not available. There are other scenarios you should test for your control involving licensing, but none particularly specific to how Access handles this any differently from other control containers.


Control Initialization

After insertion, switch immediately to browse view (View | Form View) to make sure your control doesn’t cause the error - "No object in this control." Many lightweight custom controls forget to mark themselves as dirty after insertion in the container. Access optimizes its code-path for saving cached merged type information for the extender object and the controls inserted to just those controls that have been dirtied in the current design session. When the user views the form in browse view, the form gets destroyed, and recreated. If the control has not marked itself as dirty, then just the extender object is on the form with no control inside of it. This is a common mistake when control developers use the BaseCtl framework, but the fix is simple. MFC and VB control writers don’t have to worry about this since the frameworks handle this for you. Here are some additional comments from an email thread on a similar case:

Some BaseCtl framework OCXs are getting the "There is no object in this control" error message when an Access ‘97 form containing the control is reloaded. This is because Access ‘97 expects all controls to save their binary state to a stream, and our controls only save when m_fDirty is TRUE.

To behave correctly, controls must dirty themselves before returning from their implementation of IPersistStreamInit::InitNew. Code has been added to COleControl::InitNew to dirty the control, but not all controls call COleControl::InitNew in their own implementation of the method.

Controls can do initialization in the COleControl::InitializeNewState overideable to ensure that the control will initialize properly for both IpersistStorage::InitNew and IpersistStreamInit::InitNew. Since the initialization is commonly done in IPersistStreamInit::InitNew, you should make sure m_fDirty is set to TRUE, or better yet, call COleControl::InitNew.

Note, if you move your initialization to COleControl::InitializeNewState, you are guaranteed to get dirtied for both IPersistStorage::InitNew, and IPersistStreamInit::InitNew, because COleControl's code path for both implementations of InitNew will call InitializeNewState.


Controls and the Clipboard

Another common bug with ActiveX Controls is when they are copied and pasted using the clipboard. A simple way to ensure the mechanism is working for your control is to create a new form, copy the control to the clipboard, and then paste the control back to the form. Next, select both controls, copy them to the clipboard, and paste them back. Also, try pasting the controls using PasteSpecial as each type that is listed in the dialog. Be aware that you will get an error, "You can’t paste the object as the type specified," if you have written the control using the BaseCtl framework and have not implemented the IDataObject interface. The PasteSpecial as the other two types available will work however. If you are developing your control using VB 5.0 or MFC, the framework supplies a default implementation of this for you.

PasteSpecial as type picture is often missed (or omitted) by many control developers, but can leave a rather unattractive white rectangle on the form or report. This is not terribly important if the control is not going to be used in this fashion. However, I believe this is the same code that is responsible for many controls looking unprofessional when print previewed since the metafile representation of the control is used, so it may be worth while to add it. This is discussed later in this document.

It’s also interesting to try using Edit | Undo after a paste of multiple controls, as well as after the other operations listed above.


Design Mode State

When a control is inserted into an Access form or report, it is inserted in Passive Design Mode (this term is from the Visual C++ tool ActiveX Control Test Container). In other words, the control is not UI Active, and therefore not responding to UI interaction or firing events. To get a better idea of this, insert the Calendar Control that ships with Access into the ActiveX Control Test Container. On the Options menu you will see two different modes listed: Passive Container Mode, and Simulated Design Mode. The later is the default, and therefore the most commonly used when testing a control in this tool. However, test your control using Passive Container Mode as well, since this simulates more closely how the control behaves in design view of an Access form or Report.


Design-Time and Run-Time Property Persistance

Another, relatively common bug can appear after the control is inserted onto the form or report. Resize the control, then browse the form via View | FormView. Note the size of the control, then switch back to design view and note the size of the control again. Repeat these steps: resize the control, and switching back to browse view. The control may appear to look like it was not notified that the property has changed and that the control is dirty. To see an example of this, try this with the Microsoft Web Browser Control from IE 3.0 or IE 3.01. Verify that your control is persisting appropriate property changes in design correctly, and marking the control as dirty.

The bottom line is to ensure that the control persists properties that are modified at design-time and not those modified at run-time. This not only includes when the form is finally saved and the form and control information persisted out to a jet table, but also when switching between design and browse modes since there is a sort of persistence in memory of the cached changes occurring at that time as well.


Invisible-At-Runtime Controls

These controls typically show some design-time representation of the control on the design surface, but don't allow re-sizing the control. Ensure that your control responds correctly in both the case where the user tries to resize the control using the mouse a dragging the grab handles of the bounding rectangle around the control, and by setting the Height and Width properties in the merged property sheet for the extender object. These properties can be found on the Format tab of the property sheet. Regardless of how the user attempts to modify the height and width properties, this type of control should "snap back" to its original size.


Print Preview of Access Forms and Reports

Make sure that your control paints correctly when the Metafile representation of the control’s UI is requested. Insert your control on an Access form or report and Print Preview to ensure it looks correct. Again, this should be similar to inserting your control into the ActiveX Control Test Container (the tool that ships with Visual C++) in Passive Container Mode, and then choosing Edit | Draw Metafile from the menus.

Although it is a similar code path you may want to verify that actually printing the form or report with your control on it looks correct as well. Obviously, if your control is invisible at runtime, it should not be painting when the form is browsed via View | FormView, or when printed or previewed. It also should not invalidate the region on the form or report surface where it is located either. It should not be visible at all.


Custom Control Property Pages

In form or report design, the user can double-click on a control to invoke the default verb for an OLE object. In the case of most custom controls, this default verb is to show the controls property pages. Try this for your control. Create a new form, insert the control, then double click on the control. This isn’t the case in all control containers. For example, in Visual Basic you’ll notice that you’ll always get to the default code method behind the object by doing this. In Access, you see the property pages (or the result of whatever the default OLE verb is for the object). For controls that don’t support property pages you’ll see a generic OLE error "The operation on the Foo Control object failed." It’s not required that controls supply their own property pages. However, if they do supply one or more pages, make sure they work correctly. Since Access merges all of the control's properties into its property sheet used by all of the Access intrinsic controls, you’ll still be able to set and view these properties through the UI. The Microsoft Forms 2.0 controls (that ship with Office ’97) and the Microsoft Web Browser Control are examples of controls that don’t supply property pages via a UI, but rely on the host to expose a UI.

Another way to invoke the control's property pages is to right-click and choose the name of the control on this pop-up menu. On the next pop-up menu you will see a list of the OLE verbs available and a Convert… menu item. Selecting the Properties menu shows the property pages for the control. You should try the Convert menu to ensure that the control doesn't cause any problems when this code is exercised, even though the only available option will be to convert the control to its own type. This feature is more useful for intrinsic Access controls to morph controls like listboxes to textboxes, combo-boxes, or pictures.


Property Merging in the Access Property Sheet

An interesting scenario is to verify specific property pages can be invoked from the merged Access control property sheet. When your control is selected in either form or report design view, select View | Properties from the menus. The properties defined by the control will be merged with the extender object that wraps the control and provides properties common to other Access intrinsic controls. The ActiveX Control’s properties are listed on the Other and All tabs on this property sheet below the Custom property. Ensure that for your control all of the properties (excluding hidden properties) are shown in this merged property sheet. This includes read-only properties as well. Also, ensure that the "…" builder button next to the Custom property invokes the all of the property pages for the control, given that the control supplies property pages.

Further down the list of properties in the sheet, specific properties will require only showing a single property page, like the Color property page for the BackColor property in the case of the Calendar Control, or only the General property page for the Month property. Click on the builder button next to these properties to see the single property page invoked. If applicable, ensure for your control that changes can be made to the properties on these pages, and then applied or cancelled, and the appropriate settings based on your actions have been propagated back to the merged property sheet. These properties can get converted to different types as the settings are propagated back to the property sheet. Also, verify that you can set each of these properties from within the Access merged property sheet directly.

It is also important to ensure the properties that supply a list of enumerated names instead of the underlying integer value that is persisted, show the correct strings in the merged property sheet. For example, in the Calendar Control that ships with Access, the GridCellEffect property displays a dropdown in the merged property sheet with the strings "Flat", "Raised", and "Sunken". Ensure that selecting each type of enumerated name sets the property to the appropriate value, and that typing the enumerated name into the property sheet works as well.

If you have any read-only properties, try setting the properties through the merged property sheet and verify that an acceptable error is displayed.

Verify that setting invalid values and data of the incorrect type for each control property returns an acceptable error. These errors should be similar to the errors returned by the control when invalid values are entered in the control's property pages as well.


Simple Data Binding

If your control supports simple data binding, verify that the Control Source and Locked properties are shown on the Data tab of the merged property sheet for the control. You should also verify that these properties work correct when the control is bound to columns of various data types. You can check the scenarios such as dirtying the current record using the control, or through the UI of the form by changing the value through another control (say a textbox) which is also bound to the same field in the form’s recordset. Try committing the record or canceling the change to the dirty record. Verify that binding is working correctly when the user places the control in the details section of a bound report and binds the control to a field in the report’s recordset. When the report is previewed, the control should show each value for the bound value as the underlying data for that record. Access limits this case to reports since for forms the user cannot set the Default View property to Continuous Forms when the form contains an ActiveX Control, sub-form, or bound chart.


Event Procedures

After placing a control on the form or report design surface, a user can view the code behind the form by selecting the View | Code menu item. Select the control name in the left-hand side Object dropdown in the code window, and each of the event procedures listed in the right-hand side Event Procedure dropdown. In addition to the event procedures exposed by the control through its type-library, the extender-object that Access wraps around the custom control also exposes a few event procedures as well. These events are Enter, Exit, GotFocus, LostFocus, and Updated. Currently, there is a bug that will cause a GPF if you attempt to build an event procedure for a control that contains an event name that conflicts with one of the five extender-object event names.

Verify that the parameter types are correct for each of the event procedures. For some parameter types, Access will convert to the keyword object. For example, if your event procedure has a parameter of type Node that is defined (for an example, see the Visual Basic TreeView ActiveX Control's Expand event) in the control's type-library, Access will build the event procedure as:

Private Sub ActiveXCtl1_Expand(ByVal Node As Object)

This is a slightly different behavior than you'll see building the same event procedure for the control in Visual Basic 5.0:

Private Sub TreeView1_Expand(ByVal Node As ComctlLib.Node)

Or, in Visual Basic 4.0 as:

Private Sub TreeView1_Expand(ByVal Node As Node)

Regardless, you'll see some variation here, so make sure your control's event procedures work correctly with non-standard types and that the correct parameter passing convention is used based on your expectations.


Object Browser

Once you have inserted your control on a form or report, Access creates a reference in the VBA project to your control's type library. If you haven't inserted your control onto any form or report in the database project, you can explicitly set a reference to the control. Design any module, and open the references dialog using the Tools | References menu item. From any code window you can invoke the Object browser using F2 or the appropriate menus. The control's type library will be listed in the Project\Library dropdown at the top of this window. Ensure that only the correct members are listed that you wish to expose to the user. Also, if you have specified any context sensitive help for these members, verify that the correct text is displayed when a member is selected and that the help topic links (if supplied) appear and jump to the help file successfully and with the correct context ID.


Accessing properties and Methods Programmatically

Verify that each of the properties and methods can be called programmatically. Pass invalid values and incorrect data types to ensure that errors returned are acceptable. Pay special attention to control members that have name conflicts with extender-object member names. For example, if your custom control has a property also called Enabled, or a method SetFocus or Undo, ensure that you try to access these members programmatically with and without the ".object." syntax.


Instantiating Control Instances With Events Programatically

If you have added a reference in the current databases VBA project to your control's type library (Access does this for you when you insert a control onto a form or report design surface), you can write VBA code that creates instances of your control. In addition, you can declare these objects using the WithEvents keyword in a class module which will cause events to fire on that instance of the object in class. For more information on this see the online help for the WithEvents keyword. Essentially, the object declared WithEvents shows up in the object dropdown in the class module code window. When it is selected, the right-hand dropdown containing the event procedures for the object will list all of the events. You can verify that the code in these event procedures are fired when the class is instantiated, and the instance of the control in the class, and some action or code causes the event code to fire.


Mnemonics and Key Handling

If the control supports mnemonics, make sure they work correctly when the form with additional controls is browsed and the user sends the appropriate accelerator key. For example, if you are writing an ActiveX tab control with customizable captions for each tab, the user could enter in "&Foo" for the first tab, and "B&ar" for the second tab. Verify that sending an Alt-F and Alt-A switch the tab selection in the control. Even if the focus in a textbox control on the form, the ActiveX Control will get first crack at handling the accelerator before Access does to allow say for instance the File menu commandbar to drop down in the Alt-F case. Also, arrow keys in both the Tab Control and the Calendar Control may perform tasks such as switching tabs or moving the selected day in the control. Verify the keys that the control should handle, and those that are not handled are passed on to the container.

You should also verify that if your control has set any of the miscellaneous control bits like acts-like-default-button, that this behavior is working for your control when interacting with other controls on the Access form.


International Issues

If the ActiveX Control is localized, test the control on localized operating systems, and with various international country settings for various currency, list seperators, and date\time formats.

Also, verify all of the localized property names and text is substituted by appropriate localized satellite resource DLLs or additional string tables in the control appropriately when the host application is another localized language.


Help Testing

There are many places where help for the control can be accessed. Verify that not only the custom help file for the control invokes successfully, but also the correct context ID from the follow locations:

  • Help button on your control's property pages should invoke help
  • F1 while property pages are open should jump to context of topic with the focus
  • F1 from the merged Access property sheet should jump to your control's help topic for the property that has the focus in the property sheet
  • F1 from the Object Browser while your control's library is highlighted in the dropdown
  • F1 while various control properties, methods, events, constants are selected in the Object Browser
  • Following help links from the documentation string in the lower portion of the Object Browser when members selected
  • Using the "?" help button in the Object Browser for your control


ActiveX Controls Test Plan

VC++ V5.0

06-Jan-97

(Modified from the 06-Sept-96 draft)

Overview

This plan describes basic test coverage for the ActiveX Controls within VC++ V5.0. The ActiveX containers to be tested are:

  1. Resource Editor (Dialog)

  2. Resource Editor Test Menu Item

  3. MFC Test Container

Methodology & Acceptance Criteria

Functionality:

In order to pass for acceptance, the controls must do the following:

  1. Controls can be inserted using the resource editor.

  2. Property pages can be viewed using the resource editor.

  3. Test function within the resource editor can be used to view the control.

  4. Controls generate wrappers correctly(via Component Gallery) and compile.

  5. Controls can be inserted and executed within the MFC Test Container.

Usability and Performance:

The tests in this document are compatibility tests between ActiveX controls and containers in VC++. It is outside the scope of this plan to test for usability or performance.

Area: Resource Editor Hosting

Ensure that the resource editor can insert, host, test, and compile the controls. This subsumes the first four functionality items listed above.

  1. In a single app, insert all controls in one or more dialog boxes, using the Component Gallery to generate the wrapper classes and add the control to the resource editor (Dialog).

  2. For each control, scroll through the property pages.

  3. Run in Test mode and list through all of the controls.

  4. Compile and run the app.

  5. Observe for compilation warnings and errors. (Common warnings include first chance exceptions and SetExtent warnings.)

What this suite does not test:

  • Programmatic creation/execution of the controls.

  • Insertion of controls via context menu in the resource (dialog) editor. In this scenario, wrapper classes for the controls are not generated.

Area: Databinding

Ensure that databinding controls can access SQL Server and Oracle databases and correctly populate the databound controls.

  1. Create an app that hosts the databound controls.

  2. Connect the Remote Data Control to a SQL Server or Oracle Database. Let the active query include a join.

  3. Bind the controls to the Remote Data Control.

  4. For List/Combobox styled controls, ensure that the lists populate by setting the ListSource and ListField properties.

  5. For single entry style controls like MaskedEdit, RichText and DBGrid, ensure that the MSRDC scrolls and updates the control properly.

  6. For Calendar type controls, query against a date field.

What this suite does not test:

  • Views, synonyms, stored procedures, and other non tabular data.

  • Non-text data.

  • Boundary conditions.

MBCS Considerations

The controls are not necessarily localized. This test will not do localization testing.

Notes/Open Issues

  • Programmatic testing is minimal and does not exercise all code paths.


Developing & Deploying

Slide 1 of 40


Overview

Slide 2 of 40


Definitions

Slide 3 of 40


Assumptions

Slide 4 of 40


Assumptions

Slide 5 of 40


1. Installation & Dependent Files

Slide 6 of 40


2. Initialization Time

Slide 7 of 40


3. Execution Performance

Slide 8 of 40


Development Tools

Slide 9 of 40


Visual Basic 5.0

Slide 10 of 40


Visual Basic 5.0

Slide 11 of 40


Visual Basic 5.0

Slide 12 of 40


Visual Basic 5.0 - Positives

Slide 13 of 40


Visual Basic 5.0 - Negatives

Slide 14 of 40


Visual Basic 5.0 - Summary

Slide 15 of 40


MFC

Slide 16 of 40


MFC - Positives

Slide 17 of 40


MFC - Negatives

Slide 18 of 40


MFC Summary

Slide 19 of 40


ActiveX Template Library 2.1

Slide 20 of 40


ATL - Positives

Slide 21 of 40


ATL - Positives

Slide 22 of 40


ATL - Negatives

Slide 23 of 40


ATL Summary

Slide 24 of 40


ActiveX SDK BaseCtl

Slide 25 of 40


ActiveX SDK BaseCtl - Positives

Slide 26 of 40


ActiveX SDK BaseCtl - Negatives

Slide 27 of 40


ActiveX SDK BaseCtl Summary

Slide 28 of 40


Visual J++ 1.1

Slide 29 of 40


Visual J++ Positives

Slide 30 of 40


VJ++ Negatives

Slide 31 of 40


VJ++ Summary

Slide 32 of 40


Development Decisions

Slide 33 of 40


Development Decisions

Slide 34 of 40


Development Decisions

Slide 35 of 40


Development Decisions

Slide 36 of 40


Deployment Decisions

Slide 37 of 40


Deployment Decisions

Slide 38 of 40


Intranet Subtleties (Simplicity)

Slide 39 of 40


Questions?

Slide 40 of 40


Developing & Deploying

Developing & Deploying ActiveX Controls

    Michael T. McKeown

    Support Engineer

    DS Internet Technologies Team

Next slide Back to first slide View graphic version


Overview

  • Definitions / Assumptions

  • Development Tools

    • Visual Basic 5.0
    • MFC 4.2+
    • ActiveX Template Library 2.1
    • ActiveX SDK BaseCtl
    • Visual J++ 1.1

  • Development and Deployment

    • Functionality
    • Client vs. server side


Definitions

  • “Control”

    • Embedding & in-place active interfaces
    • Design time UI w/optional run time UI
    • Design time and run time instantiation

  • “Component”

    • No-UI at design time and run time
    • Runtime instantiation only

  • “Leave your definitions at the door…”

Previous slide Next slide Back to first slide View graphic version


Assumptions

  • High- vs. low-level languages/tools

    • Complexity vs. abstraction
    • Dependent files
      • Memory footprint
      • Downloads
    • Performance speed
      So how does
      this affect
      ActiveX Controls?


Assumptions

  • Desktop app vs. browser-hosted control

      1. Installation & dependent files

      2. Initialization time
      3. Execution performance

Previous slide Next slide Back to first slide View graphic version


1. Installation & Dependent Files

  • Conventional desktop app

    • Fast CDROM or LAN
    • User expects delay

  • ActiveX Control in browser
    • Assume low bandwidth
    • Web surfer’s demanding
    • Downloads part of perception
  • Download misconceptions
  • “Dependent files”


2. Initialization Time

  • Conventional desktop app

    • Used for extended time
      • Init time insignificant

  • ActiveX Control in browser
    • Used for very short time
      • Init time is critical !
  • “Progressive rendering”


3. Execution Performance

    (Assume code & data files loaded)

  • Conventional desktop app

    • Critical for repeated tasks

  • ActiveX Control in browser
    • Less important for actions
    • Net is perf bottleneck
  • “Server vs. client side”
  • “Layered abstraction”


Development Tools

    Many Choices...

    … that complement each other!

Previous slide Next slide Back to first slide View graphic version


Visual Basic 5.0

  • “Raw” controls

    • Do not contain other controls
    • Designed from scratch
    • Programmer designs and draws interface
      • VB drawing methods
      • GDI APIs


Visual Basic 5.0

  • “Composite” controls

    • COM containment of pre-existing controls
    • Composite decides what to expose from contained controls
      • Properties, methods, and events
    • Can combine both raw and composite
    • Ex. Spin Control


Visual Basic 5.0

  • ActiveX Control Interface Wizard

    • Composite controls only
    • Does not create skeleton control like VC++
      • Control must already exist before invoking
    • Maps properties, methods, and events of contained control(s) to composite’s IDispatch


Visual Basic 5.0 - Positives

  • Design time debugging

  • Builds p-code and “native” controls

  • ISimpleFrameSite

  • Collections

    • ParentControls, DataBindings, ...

  • Ambient and extended prop objects

  • Develop controls with little code

  • Don’t need to know C/C++

Previous slide Next slide Back to first slide View graphic version


Visual Basic 5.0 - Negatives

  • Parts of COM / ActiveX cannot be used

    • “Implements” helps but is not all inclusive

  • Only supports single threading model

    • Discouraged in IE (5.1 fixes this)

  • Runtime must accompany BOTH p-code and native code versions

  • Finite (non-progressive) rendering only

  • Extremely minimal OC96 support

Previous slide Next slide Back to first slide View graphic version


Visual Basic 5.0 - Summary

  • Best for desktop apps or corp. Intranet

    • Contained controls tend to be large
    • Limited threading
    • Large dependent runtime
      • Controlled in Intranet but burden on Internet
    • Finite progressive downloads
      • Work well on fast LAN
      • Not good for slow public Internet links
    • Development easier for corp. developers


MFC

  • Quick review for most of us

    • Classes hide COM complexities
    • Slightly more complex than VB5
      • (If already know C++)
    • Great wizard support
      • Creation
      • Automation (IDispatch)


MFC - Positives

  • Great OC96 support

    • Wizards
    • Degraded behavior

  • Good asynch download support

    • CCachedDataPathProperty
    • Great readiness state support


MFC - Negatives

  • Dependent MFC runtime

    • Ships with IE - Yeah!
    • Revs often - Boo! Hiss!

  • CCachedDataPathProperty is limited

    • Not trivial to implement & no samples *
    • May want to look at other tools if doing this

  • No direct support for dual interfaces

  • Does not support Free threading model

Previous slide Next slide Back to first slide View graphic version


MFC Summary

  • Best for desktop apps or corp. Intranet

    • Limited threading
    • Progressive rendering not trivial
      • Important on public Internet
    • Large dependent runtime
      • Controlled in Intranet but burden on Internet
    • Control Wizard controls not minimally sized
    • Development easier for corp. developers


ActiveX Template Library 2.1

  • Uses C++ templates

    • Take parameters similar to macros
    • Dynamically instaniates runtime classes

  • Creates fast and small components

    • In-Process .DLL
    • Local (and Remote) .EXE
    • NT Service

  • Recommend VC++ 5.0

    • Any C++ compiler that supports templates


ATL - Positives

  • No large dependent runtime *

  • Script-based registration

    • Easy extensibility for custom registration
    • Adds small DLL if script component not compiled as part of code

  • Wizard support for props and methods

  • Creates many types of components

Previous slide Next slide Back to first slide View graphic version


ATL - Positives

  • Supports all threading models

  • Lots of advanced support

    • OC 96
    • Aggregation
    • Tear-off interfaces
    • Dual interfaces
    • Can be extended for COM functionality

  • Strategic

    • Integrated with VC++ 5.0


ATL - Negatives

  • Knowledge requirements

    • Templates
    • COM

  • Minimal asynch download support

  • No Wizard for events

Previous slide Next slide Back to first slide View graphic version


ATL Summary

  • Can be deployed anywhere

    • Shines on Internet

  • Best choice for

    • OC 96
    • Advanced COM features
    • Self-sufficient components

  • Relatively easy to extend

  • Will be improved in the future

Previous slide Next slide Back to first slide View graphic version


ActiveX SDK BaseCtl

  • “Lean and mean” ActiveX SDK sample

  • First non-MFC creation mechanism

  • Framework or base class?

    • Ex. IViewObject2::Draw

  • Classes for

    • ActiveX Control (asynch download)
    • ActiveX Control (no asynch download)
    • Automation Server


ActiveX SDK BaseCtl - Positives

  • Fast and small

    • No large dependent runtime

  • Easily extensible

  • Dual interfaces

  • Apartment model threading

  • Aggregation

  • OC 96

  • Async download

Previous slide Next slide Back to first slide View graphic version


ActiveX SDK BaseCtl - Negatives

  • A sample - NOT STRATEGIC!

  • Requires advanced COM/C++ knowledge

  • No Wizards

  • No IDE

    • Can used VC++

  • Minimal class support

  • Does not implement IDataObject

Previous slide Next slide Back to first slide View graphic version


ActiveX SDK BaseCtl Summary

  • Can be deployed anywhere

    • Shines on Internet

  • Good choice for

    • OC 96 (ATL better)
    • Advanced COM features (ATL better)
    • Self-sufficient components (Best)

  • Can be extended for special cases

Previous slide Next slide Back to first slide View graphic version


Visual J++ 1.1

  • MS Java VM implied here

  • Java classes can appear as COM objects

    • Java programmers write Java
    • Automation servers
      • Properties and events; no methods

  • Java classes can use COM objects

    • Must have type information
    • Signed applets can use COM objects


Visual J++ Positives

  • Java/COM interoperability

  • Cross platform (wrt VM)

  • Use Java to write COM objects without UI

  • Supports all threading models

  • Wizard - using Java class as COM object

    • No support for using COM objects in Java classes

  • Auto-IDispatch

Previous slide Next slide Back to first slide View graphic version


VJ++ Negatives

  • Requires COM-compliant VM

  • Does not create conventional controls

    • Automation servers
    • No attributes of controls

  • Can’t use conventional controls via Automation

    • Not always a good idea anyways

  • Calling an non-Java COM object or ActiveX services affects portability

Previous slide Next slide Back to first slide View graphic version


VJ++ Summary

  • Best cross-platform choice

  • Use on Web page

    • VJ++ creates applets
      • Signed class files can call COM objects
    • VJ++ creates COM objects (non-applets)
      • Good Wizard support
      • Not used where UI is needed
    • VJ++ uses COM objects (non-applets)
      • Primarily for use in Java applications


Development Decisions

  • File dependencies

    • Yes - VB5, MFC
    • Maybe - BaseCtl, ATL, Java

  • OC 96

    • ATL, MFC, BaseCtl

  • Platform independence

    • VJ++


Development Decisions

  • Easily entensible

    • BaseCtl, ATL, MFC (somewhat)

  • Threading models

    • ATL, VJ++ (Auto servers only)

  • Corporate developers and Intranet

    • VB5, MFC

  • Public Internet

    • VJ++, ATL, BaseCtl


Development Decisions

  • Progressive rendering

    • MFC, BaseCtl, ATL (minimal)

  • Flexible persistence

    • ATL, BaseCtl

  • Control containment

    • VB5, MFC (not trivial)

  • Design time control debugging

    • VB5, MFC (not as straightforward)


Development Decisions

  • Different tools for different roles

  • Some considerations...

    • Ship dates
    • Developer skill sets
    • Range of distribution
    • Functionality required
    • Hosting containers

  • Most ISVs using many tools

Previous slide Next slide Back to first slide View graphic version


Deployment Decisions

    1. Runtime user interface

    • Server side - none allowed
    • Client side - optional

    2. Performance (if no UI)

    • Client side - Many individual requests to server
    • Server side - one input triggers many actions with one output


Deployment Decisions

    3. Size and dependent files (if no UI and no performance differences)

    • Try to minimize for client downloads

    Summary - If no performance difference, functionality not affected, and no runtime UI --> Keep on server!

Previous slide Next slide Back to first slide View graphic version


Intranet Subtleties (Simplicity)

  • If no specific benefits on client, keep non-UI, internal components on the server

    • Avoid code signing issues
    • Avoid packaging of control licenses (.LPK)
    • Avoid size focus during component development
      • Actual size of .OCX & dependent files
        • Simpler tool can be used (MFC, VB5)
      • Avoid needing .CAB and .INF (for remote users)
      • File size usually not an issue on intranet
        • Fast LAN and client side configuration control


Questions?

    ….maybe answers!

Previous slide Back to first slide View graphic version