Introducing Microsoft .NET (Pro-Developer)
|
I’ve written previously of the enormous popularity of ActiveX controls. If .NET couldn’t use them, many developers wouldn’t use .NET, which would mean that ActiveX developers wouldn’t have a large enough market to merit converting their controls, and the whole .NET concept would be stillborn on the client side. Therefore, the developers of Windows Forms wisely decided to include support for hosting ActiveX controls. Since ActiveX controls work by means of COM, I’d strongly suggest that anyone interested in pursuing this topic go back to Chapter 2 and read the section about interoperation between COM and .NET.
Windows Forms can host ActiveX controls.
A Windows Forms application does not inherently know how to use an ActiveX control. It only understands controls written with its own managed Windows Forms architecture. For a Windows Forms application to host an ActiveX control, you need to generate a wrapper class that will contain the ActiveX control, mediate between its COM-based world view and the .NET world view of its container, and present it to Windows Forms as if it were a native Windows Forms control. You essentially need a monster runtime callable wrapper, as described in Chapter 2, that consumes all the COM interfaces that an ActiveX control provides, while also providing the COM interfaces that an ActiveX control requires from its host. This architecture is shown in Figure 5-4. If you think that sounds like a hell of a lot of work, you’re right, but don’t worry because the common language runtime provides a prefabricated class that does it all for you, called System.Windows.Forms.AxHost.
A Windows Forms application hosts an ActiveX control by generating a wrapper class similar to the runtime callable wrapper that wraps a COM object.
You need to derive a separate wrapper class from AxHost for each class of ActiveX control that your application wants to host. This class will contain the class ID or program ID used to create the ActiveX control and will expose in a native .NET format the properties, methods, and events of the wrapped ActiveX control. This will feel familiar to anyone who has ever imported an ActiveX control into Visual C++ or Visual J++. You generate this wrapper class using a command-line utility, called AxImp.exe, that comes with the .NET Framework SDK. If you are using Visual Studio, you can simply right-click on the toolbox, pick Customize Toolbox from the shortcut menu, and you will see the dialog box in Figure 5 5, which offers the list of what Microsoft now calls COM Controls. (So long “ActiveX,” and good riddance. One less MINFU in the world.)
You create the wrapper class using Visual Studio or a command-line utility.
When you select a control from this list, Visual Studio runs AxImp.exe internally and generates this wrapper class for you. It’s built into a separate DLL as part of your project. You can’t see the source code directly, at least not currently, but you can view its methods and properties in the Object Browser, shown in Figure 5-6. The new control will appear on your toolbox, and you can use it in the familiar manner.
I’ve written a sample Windows Forms program that uses the Microsoft Web Browser ActiveX control. Figure 5-7 shows a screen shot of it, displaying the Web page of the first edition of this book.
ActiveX controls work by means of COM, so the warning that I gave about COM in Chapter 2 applies to ActiveX controls as well. Using them means that your apps require the privilege of accessing unmanaged code, which administrators don’t like to grant. And since ActiveX controls are unmanaged, they don’t perform their internal memory allocations from the managed heap, which means they’re subject to memory leaks. My clients report that they’re good as a stopgap only, that you really want to get managed Windows Forms controls written as soon as possible instead. You can download a chapter about Windows Forms controls from this book’s Web site, http://www.introducingmicrosoft.net.
I imported the ActiveX control into Visual Studio as described previously. I then placed the control on my form and wrote the code shown in Listing 5-4. When the user clicks the Fetch button, I call the wrapper class’s Navigate method, passing the URL that the user has entered. The wrapper class transforms this call into a COM call and passes it to the wrapped ActiveX control.
Listing 5-4: Windows Forms ActiveX sample code.
‘ Call method on RCW of Web Browser ActiveX control to ‘ fetch the requested page. Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click AxWebBrowser1.Navigate(TextBox1.Text) End Sub
|