Visual Basic Concepts
Some controls can act as containers for other controls. For example, if you place controls on a Visual Basic PictureBox control, all of the controls move when you move the PictureBox. Visual Basic users take advantage of this capability to group controls, produce scrollable pictures, and so on.
You can allow developers to place controls on your ActiveX control by setting the ControlContainer property of the UserControl object to True.
Note Lightweight user controls cannot act as control containers. If the Windowless property of a UserControl object is set to True, the ControlContainer property will be ignored. Lightweight user controls are discussed in detail in "Creating Lightweight Controls" later in this chapter.
Controls a developer places on an instance of your ActiveX control can be accessed using the ContainedControls collection of the UserControl object. You can use this collection at either design time or run time.
The ContainedControls collection is different from the Controls collection, which contains only the constituent controls you have used in designing your ActiveX control. This is illustrated in Figure 9.7, which supposes that the ShapeLabel control's ControlContainer property is True.
Figure 9.7 The Controls and ContainedControls collections
You cannot access the ContainedControls collection in the Initialize event of your UserControl object. Support for the ControlContainer feature is provided by the object your control is placed on, so your control must be sited on the container object before ContainedControls is available. When the UserControl object receives its ReadProperties event, siting has occurred.
Once your control is sited, and support for the ControlContainer feature is present, the ContainedControls collection may not immediately contain references to the controls a developer has placed on your control. For example, if your control is on a Visual Basic form, the Count property of the ContainedControls collection will be zero until after the UserControl_ReadProperties event procedure has executed.
There is extra overhead required to allow a developer to place controls on instances of your ActiveX control. Clipping must be done for the contained controls, which must appear on top of all the constituent controls in your UserControl, and of course the ContainedControls collection must be maintained.
In other words, controls that serve as containers for other controls are heavyweight controls.
For best performance of your controls, you should set ContainedControls to True only if it makes sense for a particular control. For example, it doesn't make much sense for a control assembly like an Address Control to be a container for other controls.
ControlContainer support will not work for every container your control may be placed on. Visual Basic forms support the ISimpleFrame interface that enables the ControlContainer feature, so your control can always support this capability on a Visual Basic form.
If an instance of your control is placed on a container that is not aware of ISimpleFrame, ControlContainer support will be disabled. Your control will continue to work correctly in all other ways, but developers will be unable to place other controls on an instance of your control.
In order for the ContainedControls collection to be available, an ISimpleFrame-aware container must implement the IVBGetControls interface. Calls to the collection will cause errors if the container does not implement this interface, so it's a good idea to use error handling when you access the collection.
Note Controls a developer places on a container with a transparent background are not visible. If you want your control to be used as a control container by developers, don't give it a transparent background.