ActiveX controls

Hyperlinking

The UserControl object exposes the Hyperlink property, which returns a Hyperlink object that you can use to navigate to other HTML pages. The Hyperlink object exposes three methods, the most important of which is the NavigateTo method:

Hyperlink.NavigateTo Target, [Location], [FrameName]

Target is the URL to which you navigate, Location is an optional argument that points to a specific location in an HTML page, and FrameName is the optional name of a frame in a page. If the ActiveX control is running inside a browser, the new page is shown within the browser itself; if the control isn't running in a browser, the default browser is automatically launched.

The Hyperlink object exposes two more methods, GoBack and GoForward, which let you navigate the browser's history list. Unless you're absolutely sure that the history list isn't empty, you should always protect these methods with an On Error statement:

Private Sub cmdBack_Click()
    On Error Resume Next
    Hyperlink.GoBack
    If Err Then MsgBox "History is empty!"
End Sub

Tip

You can navigate many kinds of documents, not just HTML pages. For example, Internet Explorer can display Microsoft Word and Microsoft Excel files, so you can use it as a document browser, as the following code demonstrates:

Hyperlink.NavigateTo "C:\Documents\Notes.Doc

Asynchronous download

ActiveX controls authored in Visual Basic support asynchronous downloading of properties. Let's say that you have a PictureBox-like ActiveX control that can read its contents from a GIF or BMP file. Instead of waiting for the image to be completely downloaded, you'll do better to start an asynchronous download operation and immediately return the control to the user. The key to asynchronous downloading is the AsyncRead method of the UserControl object, whose syntax is this:

AsyncRead Target, AsyncType, [PropertyName], 

[AsyncReadOptions]

Target is the URL of the property to be downloaded. AsyncType is the type of the property and can be one of the following values: 0-vbAsyncTypePicture (an image that can be assigned to a Picture property), 1-vbAsyncTypeFile (a file created by Visual Basic), or 2-vbAsyncTypeByteArray (a Byte array). PropertyName is the name of the property whose value is being downloaded and is useful when there are many properties that can be downloaded asynchronously. But keep in mind that there can be only one AsyncRead operation active at one time.

The AsyncRead method supports a new AsyncReadOptions argument, a bit-fielded integer that accepts the values listed in Table 17-1. Using this values you can fine-tune the performance of your asynchronous download operation and decide whether the control can use the data in the local cache.

Table 17-1. The available values for the AsyncReadOptions argument of the AsyncRead method.

Constant

Value

AsyncRead Behavior

vbAsyncReadSynchronousDownload

1

Returns only when the down load is complete (synchronous download).

vbAsyncReadOfflineOperation

8

Uses only the locally cached resource.

vbAsyncReadForceUpdate

16

Forces the download from the remote Web server, ignoring any copy in the local cache.

vbAsyncReadResynchronize

512

Updates the copy in the local cache only if the version on the remote Web server is more recent.

vbAsyncReadGetFromCacheIfNetFail

&H80000

Uses the copy in the local cache if the connection to the remote Web server fails.

On the companion CD, you'll find the complete source code of a ScrollablePictureBox ActiveX control, which supports scrolling of large images as well as their asynchronous downloading from the Internet. (See Figure 17-19.) The asynchronous download feature is provided in the form of a PicturePath property that, when assigned, starts the downloading process:

Public Property Let PicturePath(ByVal New_PicturePath As String)
    m_PicturePath = New_PicturePath
    PropertyChanged "PicturePath"
    If Len(m_PicturePath) Then
        AsyncRead m_PicturePath, vbAsyncTypePicture, "Picture"
    End If
End Property

You can cancel an asynchronous download operation at any moment using the CancelAsyncRead method:

CancelAsyncRead "Picture"


Figure 17-19.
The ScrollablePictureBox control running inside Internet Explorer.

When the asynchronous download terminates, Visual Basic fires an AsyncReadComplete event in the UserControl module. This event receives an AsyncProperty object, whose most important properties are PropertyName and Value:

Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)
    If AsyncProp.PropertyName = "Picture" Then
        Set Image1.Picture = AsyncProp.Value
    End If
End Sub

The AsyncProperty object has been greatly enhanced in Visual Basic 6 and now includes properties such as BytesMax, ByteRead, Status, and StatusCode. For additional information, see the language documentation. Visual Basic 6 also exposes the AsyncReadProgress event, which fires when new data is available locally. You can use this event to display a progress bar that informs the user about the status of the operation:

Private Sub UserControl_AsyncReadProgress(AsyncProp As AsyncProperty)
    If AsyncProp.PropertyName = "Picture" Then
        Dim percent As Integer
        If AsyncProp.BytesMax > 0 Then
            percent = (AsyncProp.BytesRead * 100&) \ AsyncProp.BytesMax
        End If
    End If
End Sub

The AsyncReadProgress and AsyncReadComplete events fire immediately if the data is stored on a local disk (in this case, PicturePath is the path of a file) or if it is in the local cache. If you aren't downloading an image (therefore, AsyncProp.AsyncType is 1-vbAsyncTypeFile or 2-vbAsyncTypeByteArray), you can read and process the data while it's being downloaded. This arrangement slows the process slightly, but usually the overhead isn't noticeable. If you open a file, you must close it before exiting the event procedure, and you must avoid calling DoEvents to avoid reentrancy problems. The AsyncReadProgress and AsyncReadComplete events occur when the download is complete: You can learn when this happens in the AsyncReadProgress event by checking that the AsyncProp.StatusCode property returns the value 6vbAsyncStatusCodeEndDownloadData.

Accessing the browser

A control on an HTML page can do more than simply modify its appearance and behavior: It can manipulate the attributes of the page itself and of the other controls on it. You can access the container page using the Parent object, as this code does:

' Changing the HTML page's foreground and background colors
With Parent.Script.document
    .bgColor = "Blue"
    .fgColor = "White"
End With

You can also access and manipulate all the controls on the page using the ParentControls collection. But this method requires that you set the ParentControlsType property of ParentControls collection to the value vbNoExtender. This setting is necessary because Internet Explorer exposes an Extender object that can't be used from Visual Basic code.

I don't have enough room to describe all the things that you can do once you have a reference to the page that contains the ActiveX control. If you're interested, you should look for additional information on the Internet Explorer Scripting Object Model on the Microsoft Web site.

Tip

If you're writing a control that can be used on both regular forms and HTML pages, you need to know which container it's running in. You can do this by looking at the object returned by the Parent object:

' Test if the control runs in an HTML page.
If TypeName(Parent) = "HTMLDocument" Then ...

Show and Hide events

The Show event fires in the UserControl module when the page that contains it becomes visible, while the Hide event fires when the page becomes invisible but is still in the cache. Eventually, the page might become visible again, thus firing another Show event, or the browser might remove the page from the cache (for example, when the browser itself is closed), in which case the control receives a Terminate event.

Multithreaded ActiveX controls

If you're going to use the ActiveX control with Microsoft Explorer or a multithreaded Visual Basic application, you should make the control apartment-threaded by selecting the corresponding Threading Model option in the General tab of the Project Properties dialog box. Beware, however, of a documented bug: Multithreaded controls don't fire the Hide event when they run under Internet Explorer 4.0. For an ActiveX control to behave correctly, you must mark it as single-threaded and enable the Active Desktop option. For more information, see article Q175907 of the Microsoft Knowledge Base.

Component Download

When you're creating an HTML page that contains one or more ActiveX controls, you must provide a way for the browser to download and install the ActiveX control if it isn't already registered on the client machine.

Creating a package for deployment

The mechanism used for deploying the ActiveX controls on client machines is based on Cabinet(CAB) files. CAB files are compressed files that can include multiple ActiveX controls (as well as other types of files, such as EXEs and DLLs) and that can be digitally signed if necessary. You create CAB files by running the Package and Deployment Wizard and selecting Internet Package in its second step. The wizard also creates a sample HTM file that you can use as a model for the page that will host the control. This file contains the correct value for the CODEBASE attribute, which informs the browser of the name of the CAB file and the version of the ActiveX control. The browser then downloads the CAB file if the control with that CLSID isn't registered on the client machine or if its version is older than the one specified in the HTML page. This is a portion of the sample HTML file created for the ClockOCX control:

<OBJECT ID="Clock"
CLASSID="CLSID:27E428E0-9145-11D2-BAC5-0080C8F21830"
CODEBASE="ClockOCX.CAB#version=1,0,0,0">
</OBJECT>

CAB files can embed all the ancillary files that the ActiveX control needs to work properly, including data files and satellite DLLs. The list of dependencies of an ActiveX control is described in an INF file, which is produced by the Package and Deployment Wizard and also included in the CAB file itself.

ActiveX controls authored in Visual Basic also require the Visual Basic runtime files. The default option in the Package and Deployment Wizard instructs the installing procedure to download the runtime files from the Microsoft Web site. This setting ensures that the user always receives the most recent version of those files and also reduces the burden on your Web site.

Safety

When an ActiveX control is running in the browser, it could do all sort of evil things to the user's system, such as deleting system files, trashing the Registry, or stealing confidential data. You must, therefore, assure users that not only are your controls not so rude, but also that no other developer can use your controls to damage the machines they're running on.

To broadcast the promise that your control doesn't (and can't) misbehave, you can mark it as "Safe for initialization" or "Safe for scripting." If you declare that your control is safe for initialization, you're telling the browser that there's no way for an HTML page author to accidentally or intentionally do any harm by assigning values to the control's properties through the <PARAM> tags in the <OBJECT> section of the page. If you mark your control as safe for scripting, you're going a bit further because you're declaring that there's no way for a script on the page to set a property or call a method that can damage the system. By default, Microsoft Internet Explorer refuses to download components that aren't marked as safe for initialization and safe for scripting.

Marking your control as safe for initialization or safe for scripting isn't a decision that you should take lightly. The fact that your control doesn't purposely do any damage isn't enough in most cases. Just to give you an idea of the subtleties that you must account for, imagine these scenarios:

  • You provide a method that lets developers save data to any path. The control isn't safe for scripting because a malicious developer might use this feature to overwrite important system files.

  • You decide the location in which a temporary file is stored, but you leave developers free to write any amount of data to it. Again, the control isn't safe for scripting because a developer might deliberately consume all the free space on disk and bring Windows to an abrupt crash.

You mark your component as safe for initialization or safe for scripting in the Package and Deployment Wizard, as shown in Figure 17-20.

Tip

You can quickly learn which ActiveX controls on your machine are safe for initialization or for scripting by using the OleView utility that comes with Visual Studio. This is the portion of the Registry that marks a control as safe:

HKEY_CLASSES_ROOT
  \CLS
    \<your control's CLSID>
      \Implemented Categories
        \{7DD95802-9882-11CF-9FA9-00AA006C42C4}
        \{7DD95801-9882-11CF-9FA9-00AA006C42C4}

The last two lines of the listing indicate safe for initialization and safe for scripting, respectively. Once you know how this information is recorded in the Registry, you can use the Regedit utility to modify these setting by adding or removing these keys.

 


Figure 17-20.
The Package and Deployment Wizard lets you mark your controls as Safe For Initialization and Safe For Scripting.

A more sophisticated way to address the safety problem is through the IObjectSafety ActiveX interface, which allows your component to programmatically specify which methods and properties are safe. This approach offers greater flexibility than just marking the component as safe. This is an advanced topic, however, and I won't cover it in this book.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“God could create the world in six days because he didn't have to make it compatible with the previous version.”