用 Visual Basic 创建的 ActiveX 控件能够支持属性值的异步下载,例如,可能包含位图的 Picture 属性。通过 UserControl 对象的 Hyperlink 属性,它们也可以请求浏览器跳到 URL,或漫游“历史”列表。
当控件被放置在提供必要支持功能的容器上时,例如 Microsoft Internet Explorer,就可以利用这些功能。
有人也许希望设计的控件能够支持两种属性值装载方式:既能从 PropertyBag 中正常地载入属性值(浏览器不提供该支持),又能异步地下载属性值。
注意 任何应用程序都可异步下载本地文件。必须使用绝对文件路径(即从根目录开始的路径)。相对路径将不起作用。
控件可以通过调用 UserControl 的 AsyncRead 方法实现属性的异步下载。该方法可以从控件的任何事件、方法或属性过程中调用,只要控件已经在容器上定位。
调用立即返回,下载操作在后台处理,如图 9.8a 所示。
图 9.8a 启动位图属性的异步下载
当容器已经取得整个属性值时,控件就会收到 AsyncReadComplete 事件,该事件标识出取得的值是哪个属性的。然后,控件就可以访问取回的数据,并用它设置属性值,如图 9.8b 所示。
图 9.8b 异步下载完成
本主题中的示例代码使用这种方法创建了一个显示位图的简单控件。
为试用此例,先打开一个新的 Standard EXE 工程。使用“工程”菜单往工程中添加一个 UserControl。然后在 UserControl 上放置 PictureBox 控件,并按照下表设置属性:
对象 | 属性 | 值 |
UserControl | Name | AsyncBitmap |
PictureBox | Name | picBitmap |
AutoSize | True |
该控件有两个属性,一个是普通的 Picture 属性,另一个是相关的 PictureFromURL 属性。Picture 属性是用三个属性过程实现的,因为 Picture 对象可以通过 Set 语句进行赋值,也可以不这样。
Public Property Get Picture() As Picture
Set Picture = picBitmap.Picture
End Property
Public Property Let Picture(ByVal NewPicture _
As Picture)
Set picBitmap.Picture = NewPicture
PropertyChanged "Picture"
End Property
Public Property Set Picture(ByVal NewPicture _
As Picture)
Set picBitmap.Picture = NewPicture
PropertyChanged "Picture"
End Property
ActiveX 控件的 Picture 属性被简单地委派给了图片框 picBitmap
的 Picture 属性。由图片框完成位图的显示。
新的属性覆盖了 UserControl 的 Picture 属性。以后使用未经限定的 Picture 属性得到的都是 ActiveX 控件的 Picture 属性。为了访问 UserControl 的 Picture 属性,必须使用 UserControl.Picture
。
注意 PropertyChanged 的用途和重要性将在本章后面的“在控件中添加属性”中讨论。
把一个 URL 字符串赋给 ActiveX 控件的 PictureFromURL 属性之后,Property Let 就开始下载位图。下载完成后,该位图就被赋给 Picture 属性。因此,PictureFromURL 是 Picture 属性赋值的另一种方法。
PictureFromURL 属性把 URL 字符串保存在 UserControl 声明部分的一个私有数据成员中:
Option Explicit
Private mstrPictureFromURL As String
Property Get 只是简单地返回该字符串,所以程序可以知道图片是从哪里下载的。Property Let 完成所有的工作:
Public Property Get PictureFromURL() As String PictureFromURL = mstrPictureFromURL End Property Public Property Let PictureFromURL(ByVal NewString _ As String) '
(验证路径或者URL
合法性的代码,此处省略之。)mstrPictureFromURL = NewString
If (Ambient.UserMode = True) _
And (NewString <> "
)Then
'
如果程序处于运行模式,并且URL
字符串非空,'
则开始下载。AsyncRead NewString, vbAsyncTypePicture, _
"PictureFromURL"
End If
PropertyChanged "PictureFromURL"
End Property
当 URL 字符串赋给了 PictureFromURL 属性之后,该字符串就被保存在私有变量中。如果控件所在的工程处于运行模式(HTML 主页上的控件一直处于该状态),而且 URL 字符串非空,那么 Property Let 就开始异步下载,然后退出。
调用 UserControl 的 AsyncRead 方法即可启动异步下载,语法如下:
AsyncRead Target, AsyncType [, Property]
Target 参数指示数据的地点。该参数可以是路径或 URL。主机能够确定检索数据的正确方法。
AsyncType 参数指定了提供检索到的数据的形式。它可以是如下的值:
常数 | 描述 |
VbAsyncTypePicture | 检索到的数据以 Picture 对象的形式提供。 |
VbAsyncTypeFile | 检索到的数据放在 Visual Basic 创建的文件中。并提供包含该文件路径的字符串。当数据中包含将要运行的 AVI 文件时,该方法非常有用。控件的制作者可以把该字符串赋给相应子控件的文件名属性。 |
VbAsyncTypeByteArray | 检索到的数据以字节数组提供。假定控件制作者知道如何处理这些数据。 |
Property 参数为字符串,其值为需要下载的属性的名称。可以利用它来进行并行下载,因为 AsyncReadComplete 事件将返回同样的字符串,并可以在 Select 语句中使用。
Property 参数的值还可作为 CancelAsyncRead 方法的参数,如下所述。
每个下载请求完成后,控件都会收到 AsyncReadComplete 事件。AsyncReadComplete 事件的参数是对某个 AsyncProperty 对象的引用,该对象用来标识被下载的属性,并用来取得下载数据。
Private Sub UserControl_AsyncReadComplete( _
AsyncProp As VB.AsyncProperty)
On Error Resume Next
Select Case AsyncProp.PropertyName
Case "PictureFromURL"
Set Picture = AsyncProp.Value
Debug.Print "Download complete"
End Select
End Sub
需要在该事件过程中添加错误处理代码,因为某些出错条件可能会导致下载被中断。如果发生了这种情况,当您访问 AsyncProperty 的 Value 属性时就会发生错误。
下载的位图赋给 Picture 属性之后,控件将重新进行绘制。
注意 除了包含下载数据的 Value 属性和包含被下载属性名的 PropertyName 属性,AsyncProperty 对象还有一个 AsyncType 属性。该属性包含的值与启动下载的 AsyncRead 方法的 AsyncType 参数相同。
至此,该示例还不能保存设计时赋与的位图。也就是说,在 InitProperties、ReadProperties 和 WriteProperties 中没有代码。那些代码被省略了,因为该示例的目的在于说明本地文件的异步下载。
以下新增的一点代码是非常有用的。它使用图片框来显示位图,而不是简单地使用 UserControl 的 Picture 属性,这是为了利用图片框的 AutoSize 属性。当由于新的位图到达使图片框改变大小时,以下代码就调整整个控件的大小。
Private Sub picBitmap_Resize() '
如果赋予了一个Picture
,调整大小。If picBitmap.Picture <> 0 Then
UserControl.Size picBitmap.Width, _
picBitmap.Height
End If
End Sub
只有当图片框中真正包含 Picture 对象时才进行大小调整。在下载未完成之前,用户可以指定空图片框的大小。代码如下:
Private Sub UserControl_Resize()
If picBitmap.Picture = 0 Then
picBitmap.Move 0, 0, ScaleWidth, ScaleHeight
Else
If (Width <> picBitmap.Width) _
Or (Height <> picBitmap.Height) Then
Size picBitmap.Width, picBitmap.Height
End If
End If
End Sub
如果没有 Picture 对象,图片框的大小就会充满 UserControl 的可见区域。如果有 Picture 对象,并且 UserControl 对象被重新调整大小,那么它将调整到图片框的大小。
关闭 UserControl 设计器。控件就处于运行状态了,虽然工程的其它部分仍处于设计模式。工具箱上的控件缺省图标被激活,现在可以把控件的实例加到 Form1 上。
在计算机上找一个大的位图,越大越好。注意文件的名称和路径。把以下代码添加到 Form1 的 Declarations 部分,并用位图的文件名和路径取代代码中所显示的:
Option Explicit
Const DOWNLOADFILE = "file:\windows\forest.bmp"
确认字符串以 file:\
开始,这样才是本地文件的 URL。
注意 将 URL 传递到 AsyncRead 方法,这将不是相对的 URL。也就是说,对局部文件不能指定相对路径名。
在窗体的 Load 事件中添加如下代码:
Private Sub Form_Load()
AsyncBitmap1.PictureFromURL = DOWNLOADFILE
DEBUG.PRINT "Load event complete"
End Sub
当窗体被载入时,本地位图文件的 URL 将赋给 PictureFromURL 属性,于是下载开始了。
按 F5 键运行该工程。注意“立即”窗口中的第一条消息为“Load event complete”,然后是 AsyncReadComplete 事件发出的“Download complete”消息。
如果位图很大的话,可以注意到,当下载仍在进行的时候,Form1 就开始了绘制。关闭 Form1,回到设计模式。
再次运行该工程,这一次看到 Form1 就立即单击 Close 按钮。因为下载是在后台异步处理的,在位图载入之前窗体是激活的,并能响应用户的输入。
到现在为止,示例还只是演示了本地文件的下载。它不能用于 Web 主页上,因为 Standard EXE 工程中的控件不能被其它应用程序使用。为使用其它工程中的控件,将源文件添加到 ActiveX 控件工程,并将其作为 .ocx 文件来编译;例如,下面保存 Picture 属性。
Private Sub UserControl_InitProperties() '
在初始化时使用Nothing
作为缺省值,'
读、写图片属性,'
如果没有图片'
就不需要.frx
文件。Set Picture = Nothing
End Sub
Private Sub UserControl_InitProperties()
'
在初始化时使用Nothing
作为缺省值,'
读、写图片属性,'
如果没有图片'
就不需要.frx
文件。Set Picture = Nothing
End Sub
Private Sub UserControl_ReadProperties( _
PropBag As PropertyBag)
Set Picture = _
PropBag.ReadProperty("Picture", Nothing)
End Sub
Private Sub UserControl_WriteProperties( _
PropBag As PropertyBag)
PropBag.WriteProperty "Picture", Picture, Nothing
End Sub
可使用 ActiveX 控件接口将标准属性、方法和诸如 MouseMove 之类的事件添加到控件上。
调用 CancelAsyncRead 方法可以取消异步数据下载。CancelAsyncRead 把属性名作为参数;该参数必须和前面调用 AsyncRead 方法时的 PropertyName 参数的值相同。
只有指定的数据载入被取消了。其它的仍能继续正常工作。
详细信息 您还可以使用 AsyncReadProgress 事件来监控异步下载过程。AsynchReadProgress 事件在中“建立 ActiveX 文档”的“异步下载数据”中讨论。
Hyperlink 对象使控件能够访问 ActiveX 的超连接功能。利用 Hyperlink 对象的属性和方法,控件可以请求诸如 Microsoft Internet Explorer 之类的能识别超连接的容器,使之跳跃到指定的 URL 或者漫游“历史”列表。
可以通过 UserControl 对象的 Hyperlink 属性来访问 Hyperlink 对象。以下的代码假定控件的 URLText 属性中包含 URL 字符串。单击该控件会导致它请求容器漫游到该 URL。
Private Sub UserControl_Click()
HyperLink.NavigateTo Target:=URLText
End Sub
如果目标不是有效的 URL 或文档,就会发生出错。如果控件定位在不支持超连接的容器上,那么就会启动一个注册为支持超连接的应用程序,以处理该请求。
NavigateTo 方法有一个可选参数 Location,该参数标识目标 URL 中的位置。如果该位置没有被标识,服务器将跳到 URL 或文档的顶部。
NavigateTo 方法还接收另一个可选参数 FrameName,该参数标识目标 URL 中的某个框架。
注意 如果控件放置在不支持 IHLink 接口的容器上,UserControl 对象的 Hyperlink 属性将返回空。在使用 Hyperlink 对象时,应测试一下该属性的值。
可调用 GoForward 和 GoBack 方法在“历史”列表中移动。例如:
Hyperlink.GoForward
如果容器不能向前移动,则调用 GoForward 和 GoBack 时会出错。如果容器不支持超连接,则 GoForward 和 GoBack 都会出错。
关于更多信息 Internet 支持 ActiveX 控件的细节可在 Microsoft Visual Basic Web 站点上找到。
有关用 Visual Basic 设计 Internet 与 intranet 应用程序的信息可在“建立 Internet 应用程序”查找。