某些控件可以作为其它控件的容器。例如,如果在 Visual Basic 的 PictureBox 控件上放置控件,那么当 PictureBox 移动时,所有的控件都跟着移动。Visual Basic 用户可以利用这种功能对控件分组,或者生成可滚动的图片,等等。
将 UserControl 对象的 ControlContainer 属性置为 True,即可允许开发者在 ActiveX 控件上放置控件。
注意 轻量用户控件不能作为控件容器使用。如果一个 UserControl 对象的 Windowless 属性被设置为 True,那么其 ControlContainer 属性将被忽略。关于轻量用户控件的细节,请参阅本章后面的“创建轻量控件”。
开发者在 ActiveX 控件实例上放置的控件可以通过 UserControl 对象的 ContainerControl 集合访问。在设计时或运行时都可以使用该集合。
与 Controls 集合不同,ContainedControls 集合只包含设计 ActiveX 控件时用到的子控件。图 9.7 说明了这一点,其中假定 ShapeLabel 控件的 ControlContainer 属性为 True。
图 9.7 Controls 和 ContainedControls 集合
在 UserControl 对象的 Initialize 事件中不能访问 ContainedControls 集合。对 ControlContainer 特性的支持由用来放置控件的对象提供,所以控件必须在 ContainerControls 成为可用的之前放置在容器对象上。当 UserControl 对象收到 ReadProperties 事件时,定位已经完成。
当控件被定位,并且已经提供了对 ControlContainer 特性的支持之后,ContainedControls 集合也许不会立即包含对放置在您的控件上的控件的引用。例如,如果控件在 Visual Basic 窗体上,则 ContainedControls 集合的 Count 属性将一直为零,直到执行了 UserControl_ReadProperties 事件过程为止。
如果允许开发者在 ActiveX 控件实例上放置其它控件,就将导致额外的开销。必须对被包含的控件进行裁剪,而且被包含的控件必须出现在 UserControl 中所有的子控件之上,并且显然需要对 ContainedControl 集合进行维护。
换句话说,作为其它控件的容器的控件是严重影响性能的控件。
为了提高控件的性能,仅在特殊情况下确实需要时才把 ContainedControls 置为 True。有的控件组合是没有什么意义的,例如,让 Address 控件成为其它控件的容器。
并非对放置控件的每个容器都能提供 ControlContainer 支持。因为 Visual Basic 窗体支持 ISimpleFrame 接口,而该接口支持 ControlContainer 特性,所以在 Visual Basic 窗体上的控件总能提供该支持。
如果控件实例放置在不支持 ISimpleFrame 的容器上,ControlContainer 支持将是不可用的。控件在其它方面都能正常工作,但却不能往该控件实例上放置其它控件。
为了使 ContainedControls 集合成为可用的,ISimpleFrame 的容器必须实现 IVBGetControls 接口。如果容器没有实现该接口,则在调用该集合的时候就会出错,所以在访问集合的时候应使用错误处理。
注意 开发人员放在有透明背景的容器上的控件是不可见的。要想使该控件成为控件容器,就不要使用透明背景。