OK. I finally managed to create the sample ATL called Polygon from the ATL Tutorial on MSDN using the Visual Studio 2010 Beta 1. The problems I mention in the previous post remain; I simply hand-coded the text that the ATL wizard failed to create (well, maybe simply is not appropriate here).
Anyway, back to interop.
We have two scenarios to examine:
- WPF using COM objects and Windows Forms User Controls
- Windows Forms using WPF controls
Let’s start with the first.
In the rest of this post I will describe the recipes for a number of cases. In the following post I will provide sample applications for each. The examples include the implentations of COM objects with ATL and the WPF applications that consume them.
The source code for those samples is here.
WPF Application using a Simple COM Object
When I say simple, I mean one that has no UI. All you need to do in this case is to run the command line utility tlbimp.exe followed by one argument – the name of the dll that contains the COM object. This will create a new dll with the same name as the original, appended by Lib (tlbimp MyCom.dll will create MyComLib.dll). This will create a RCW (Runtime Callable Wrapper), that is proxies for your COM objects within the MyComLib namespace. You can instantiate these classes with the new operator and consume them from any .Net code - in particular from a WPF application.
WPF Application using a Windows Form User Control
A WPF application can use a Windows Form User Control using the WindowsFormHost class from the System.Windows.Forms.Integration namespace. WindowsFormHost is a FrameworkElement which makes it a welcome member to any WPF application and at the same time, it takes any System.Windows.Forms.Control as its content (through its Child property).
WPF Application using an ATL ActiveX Object
An ActiveX is a COM object, of course, but it also implements interfaces that usually give it a graphic user interface and the ability to be hosted in other applications (the Ol’ OLE). Those interfaces work with COM containers, but not with Windows Form or WPF windows. If you want to host the ActiveX and give it GUI, it needs to be wrapped in a Windows Form User Control. Such controls can then be hosted in a WPF application as described above.
The simplest way to create a Windows Form User Control wrapper for an ActiveX is to call the command line utility aximp.exe followed by one argument – the name of the dll that contains the COM object. This will create two new dlls. One will be the same RCW produced by tlbimp.exe (as described above. So for MyCom.dll the RCW will be called MyComLib.dll). The other has the same name as the RCW with a prefix of Ax (AxMyComLib.dll). This second dll defines a UserControl in the namespace AxMyCom and it references (depends on) the RCW.
Interestingly enough the MSDN documentation offers another option. Create a new Windows Forms User Control to contain the object in AxMyComLib. Then embed the result in a WindowsFormHost element in the WPF application. One small advantage of this approach is that you dont need to run aximp or tlbimp. Instead, you add your COM component to the ToolBox (by right clicking on the ToolBox, selecting Choose Items and selecting the component from the COM tab).
You can then drag the COM component from the ToolBox onto the UserControl design surface. When you do this, Visual Studio will automatically create the two dlls produced by aximp (with an addition of the string “interop.” in the names of each) and reference them in your project. (Actually it references only the AxMyComLib.dll assembly and issues a warning proposing you to add a reference to the interop dll too).
The disadvantage of this approach is that you add an additional UserControl wrapper between the WPF application and the COM implementation.
In the next post, we will see each of these principles in code samples.