理解容器的扩展对象

在“属性”窗口中观察控件实例的属性时,会发现有许多自己没有定制的属性。这些扩展属性由控件所在的容器提供,但它们看上去与控件结合得很好,如图 9.6 所示。

图 9.6 由容器提供的扩展属性、方法和事件

UserControl 对象可以通过它的扩展对象来访问 extender 的属性。例如,“创建一个 ActiveX 控件”中的 ShapeLabel 控件使用以下代码来初始化它的 Caption 属性:

Private Sub UserControl_InitProperties()
   ' Caption 属性的初值
   '赋为这个 ShapeLabel 实例的名称。
   Caption = Extender.Name
End Sub

Extender 属性是为使用控件的开发者提供的。一般来说,控件制作者不需要在 UserControl 中用代码设置它们。例如,应该由开发者决定控件实例的位置(Top 和 Left)属性,以及在拖动控件时使用的图标。

Extender 属性是后期约束的

在编译控件部件时,Visual Basic 没有办法确定它将被放到什么容器上。所以,对扩展属性的引用总是后期约束的。

标准扩展属性

以下是 ActiveX 控件规格说明中列出的容器应提供的所有属性:

属性 类型 访问 含义
Name String R 用户赋予控件实例的名称。
Visible Boolean RW 指示控件是否是可见的。
Parent Object R 返回包含控件的对象,例如 Visual Basic 窗体。
Cancel Boolean R 当控件是容器的取消按钮时,为 True。
Default Boolean R 当控件是容器的缺省按钮时,为 True。

尽管建议容器需要实现这些属性,但容器并不是必须要实现它们。因此,在代码中引用扩展对象的属性时,即使是标准属性,也需要使用错误捕获处理。

许多容器提供额外的扩展属性,如 Left、Top、Width 和 Height 属性。

注意 要想使控件在运行时是不可见的,需要把 UserControl 对象的 InvisibleAtRuntime 属性置为 True,这在本章后面的“使控件在运行时成为不可见的”中讨论。不要为此而使用扩展对象的 Visible 属性。

使用特定容器的控件

如果设计的控件需要特定的扩展属性,那么这样的控件就不能用在未提供这些属性的容器上。构造这样的特定容器控件没有什么错误,只是市场前景将受到一些限制。

如果设计的控件就是为了用于某些特殊的容器,那么就不需要考虑上述问题。然而,认真地使用错误捕获处理是有益的,因为如果控件被放置在非期望的容器上,需要防止控件导致意外的损失。

了解容器的限制

Visual Basic 提供了大量的扩展属性和事件,这些已都列在扩展对象的帮助信息中。许多容器只是提供其中一个很小的子集。

一般来说,控件的制作者不用考虑扩展属性、方法和事件。许多扩展属性,诸如 Top 和 Left 或 WhatsThisHelpID,不能让控件来实现,因为容器必须提供对这些属性所需的支持。

控件和扩展属性的冲突

如果控件实例的属性名与它所在的容器的扩展的属性名重名,则将只会看到扩展的属性。

例如,假设为控件设计了 Tag 属性。当在 Visual Basic 窗体上放置控件实例时,Tag 属性由窗体的扩展对象提供。如果控件名为 ShapeLabel,则使用者可能编写如下的代码:

ShapeLabel1.Tag = "Triceratops"

以上代码把字符串“Triceratop”保存到 Visual Baisc 窗体的扩展对象提供的 Tag 属性中。如果把控件实例放置在某个容器上,该容器的扩展对象没有 Tag 属性,则这段代码就会把该字符串保存到控件的 Tag 属性中。

为了访问放置在 Visual Basic 窗体上的控件的 Tag 属性,可使用扩展对象的另一个属性,代码如下:

ShapeLabel1.Object.Tag = "Triceratops"

Object 属性返回对控件制作者设计的接口的引用,该接口没有任何扩展属性。