ActiveX .NET Controls: Best of Both Worlds

ActiveX .NET Controls: Best of Both Worlds

When you place an ActiveX control on a Windows form, something interesting happens. The control becomes part ActiveX, part .NET something we call an ActiveX .NET control. The ActiveX portion is the core control that defines the behavior of the control you know and love. The .NET part is a translation layer that is wrapped around the control to help make it fit in with other .NET controls and objects. This section describes how ActiveX controls are supported in .NET.

ActiveX Interop Ax Wrapper: The Windows Forms Wrapper

For Windows Forms to be able to position and display your ActiveX control, additional properties, events, and methods are added to the control. You can think of these as extended properties, methods, and events (PMEs) of your control. Figure 13-1 illustrates how an ActiveX control is extended to include properties such as Location, Tag, and Visible. These extended PMEs are combined with the public PMEs of your ActiveX control to form a new wrapper class. When you write code against the control, you are actually writing it against the wrapper class. The wrapper class in turn delegates to the ActiveX control. If you are setting a public property that is available on the ActiveX control, the wrapper class simply passes the property setting straight through to the control. If you are setting an extended property not found on the ActiveX control, the wrapper takes care of performing the operation on the control, such as toggling visibility or changing its size.

Figure 13-1

An Ax wrapper encapsulates and extends an ActiveX control.

The Ax (short for ActiveX) wrapper is officially known as the Windows Forms Wrapper (WFW). It is called this because the wrapper is specifically generated when the control is placed on a Windows form. If you place an ActiveX control on any other type of .NET form, such as a Web form, the Ax wrapper is not generated.

The concept of a wrapper class is not new. Visual Basic 6 wraps ActiveX controls in a similar fashion. However, the way controls are wrapped in the two environments is quite different. This leads to a number of interesting issues when the code is hosted on a Visual Basic .NET form.

note

If you create a new Visual Basic .NET Windows application project and place an ActiveX control on the form, the control name is prefixed with Ax. For example, if you place an ActiveX TreeView control on the form, the resulting name of the control is AxTreeView. As the name implies, when you write code against AxTreeView you are actually programming against the Ax wrapper class for the control, not the control itself.

Property and Parameter Type Mappings

One purpose of the Windows Forms ActiveX control wrapper is to expose ActiveX properties in such a way that they can be naturally assigned to other .NET component properties. For example, in Visual Basic 6, the Picture property is based on the StdPicture object, which implements the IPicture and IPictureDisp interfaces. In Visual Basic .NET, however, the Picture property for .NET components is type System.Drawing.Image. The problem is that you cannot directly assign a property of type StdPicture to a System.Drawing.Image property. To help alleviate this problem and avoid nasty-looking conversion code around every property assignment, the wrapper automatically exposes your ActiveX control s Picture property as System.Drawing.Image. Figure 13-2 illustrates how the Ax wrapper exposes an ActiveX property such as Picture as a .NET type such as System.Drawing.Image.

Figure 13-2

Picture property translated to System.Drawing.Image.

In a similar manner, the Windows Forms Ax wrapper exposes other common ActiveX properties, such as Font and Color, as the respective .NET type. Table 16-1 lists the ActiveX property types that the Windows Forms Ax wrapper exposes as the appropriate .NET type.

Table 16-1 Ax Wrapper Mapping of ActiveX Types to .NET Types

ActiveX Control Property Type

Maps to Ax Wrapper Property Type

OLE_COLOR

System.Drawing.Color

Font

System.Drawing.Font

Picture (bitmap)

System.Drawing.Image

Take, for example, the following Visual Basic 6 code, which assigns a Picture to the Picture property of a ListView ActiveX control:

ListView1.BackColor = vbRed Set ListView1.Picture = _ LoadPicture(Environ("WINDIR") & "\Prairie Wind.bmp") Set Picture1.Picture = ListView1.Picture

The code is upgraded to the following Visual Basic .NET code:

ListView1.BackColor = System.Drawing.Color.Red ListView1.Picture = _ System.Drawing.Image.FromFile(Environ("WINDIR") & _ "\Prairie Wind.bmp") Picture1.Image = ListView1.Picture

Variant and Object Types: Mapping Not!

As you can see, you can assign native .NET types such as System.Drawing.Color.Red or System.Drawing.Image to ActiveX control properties such as BackColor or Picture, respectively. This strategy works great when the ActiveX control property or method parameter is strongly typed. In this case Windows Forms sees that the property type for BackColor is OLE_COLOR and the type for Picture is IPictureDisp. Seeing these types, Windows Forms automatically maps the properties to their .NET equivalents when creating the wrapper. What happens when Windows Forms cannot tell the property type? For example, what happens when a property or method parameter is of type Variant or Object?

If an ActiveX control property or method parameter is not strongly typed that is, if it is a generic type such as Variant or Object the type is mapped to a .NET Object type in the wrapper. This commonly occurs when the ActiveX control exposes a property or a method that contains optional parameters. In order for a parameter to be optional it must also be of type Variant. If, for example, you are calling an ActiveX control method that takes an optional Picture, Color, or Font, you must explicitly pass the underlying ActiveX type as the parameter value. This means that you will need to convert a .NET type to the equivalent ActiveX type before making the call. Doing so can lead to some ugly-looking, but necessary, code.

Consider the following Visual Basic 6 code, which adds an image to an ActiveX ImageList control:

ImageList1.ListImages.Add , , _ LoadPicture(Environ("WINDIR") & "\Zapotec.bmp")

If you right-click the line of code in Visual Basic 6 and choose Object Browser and then navigate to the ListImages type, you will see the following declaration:

Function Add([Index], [Key], [Picture]) As ListImage

Each parameter contained in square brackets is an optional parameter of type Variant. Although the third parameter is named Picture, it is of type Variant, so Visual Basic .NET does not know to map this property to System.Drawing.Image. If you upgrade this code to Visual Basic .NET, you end up with the following:

ImageList1.ListImages.Add( , , _ VB6.ImageToIPictureDisp(System.Drawing.Image.FromFile( _ Environ("WINDIR") & "\Zapotec.bmp")))

If the Picture parameter had been treated as a System.Drawing.Image type, the call to System.Drawing.Image.FromFile would be sufficient. In this case, however, the Picture parameter is mapped to Object and requires the underlying ActiveX type IPictureDisp. The compatibility library function ImageToIPictureDisp is required to convert the Image object to an IPictureDisp the underlying interface type for Picture and the resulting IPictureDisp is passed as the Picture argument to the Add method. Without this conversion you will encounter a run-time COMException returned from the ImageList control, containing the error Invalid picture.

Fortunately, as in the case just described, the Upgrade Wizard handles most of these conversions for you. In rare cases you will need to call a conversion helper function to convert a .NET type to the equivalent ActiveX type.



Upgrading Microsoft Visual Basic 6.0to Microsoft Visual Basic  .NET
Upgrading Microsoft Visual Basic 6.0 to Microsoft Visual Basic .NET w/accompanying CD-ROM
ISBN: 073561587X
EAN: 2147483647
Year: 2001
Pages: 179

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net