DCSIMG
WPF, Windows Forms and ATL Part 2 - David Sackstein's Blog

WPF, Windows Forms and ATL Part 2

Continuing from Part 1.

We are still discussing the first scenario for WPF Interop, namely using COM and Windows Forms User Controls in a WPF application. Here I will be giving some examples. In the next post I will discuss the second scenario – hosting a WPF control in a Windows Form application.

You can download all the source code for Part 1 and Part 2 of this article here.

Please note: All projects were prepared with Visual Studio 2010 Beta 1.

WPF Application using a Simple COM Object (ATL)

I used ATL to create a Simple COM Object using these steps.

  1. Add a new project of type ATL Project (under “Other Languages”. Interesting how the demoted king of object-oriented languages is now just “another” language).
  2. Call it SimpleControl.
  3. Check “Allow merging of proxy/stub code”.
  4. Use Add Class to add an “ATL Simple Object” and name it Calculator.
  5. Enable Connection Points on the new object before completing the Wizard.
  6. Add a Multiply method (with 2 double operands and returning a double) to the ICalculator interface.
  7. Fill in the implementation of the Multiply method in Calculator.cpp.
  8. Add another method called MultipleAsync (with 2 double operands returning void). This will be an asynchronous call to Multiply.
  9. Add a MultiplyCompleted event in the ICalculatorEvents interface using the Wizard. This step in the Wizard fails to add the method to the events interface in the .idl file, so you have to add it yourself.
  10. Implement the CProxy_ICalculatorEvents interface in _ICalculatorEvents_CP.h using the Wizard. This step in the Wizard also fails and does not generate the Fire_MultiplyCompleted method. So you will have to write it yourself or copy a similar routine from elsewhere and make the required modifications.
  11. My implementation of MultiplyAsync involves a background thread which fires the MultiplyCompleted event after a 3 second sleep and the calculation is complete.

Now we have that in place, lets run tlbimp on the SimpleControl.dll, to create the RCW SimpleControlLib.dll.

Create a console application (as the Calculator control has no GUI there was no point making the same a WPF application) and add a reference to the SimpleControlLib.dll.

We can now consume the COM control through the managed wrapper as follows:

using SimpleControlLib;

 

namespace ConsoleCalculatorApp

{

    class Program

    {

        static void Main(string[] args)

        {

            Calculator calculator = new CalculatorClass();

 

            double result = calculator.Multiply(3, 5);

            Console.WriteLine(result);

 

            calculator.MultiplyCompleted += calculator_MultiplyCompleted;

            calculator.MultiplyASync(5, 6);

 

            Console.ReadLine();

        }

 

        static void calculator_MultiplyCompleted(double result)

        {

            Console.WriteLine(result);

        }

    }

}

WPF Application using a Windows Form User Control

A good example of using a Windows Form User Control is the one shown in the Walkthrough: Hosting an ActiveX Control in Windows Presentation Foundation. Though the title of the walkthrough indicates that it describes a method to host ActiveX controls in a WPF application, in fact, it does so by creating a Windows Form User Control that hosts the ActiveX control and then hosts the User Control in the WPF application using the WindowsFormsHost, so it shows how to host any Windows Forms UserControl in a WPF application.

To demonstrate the technique in the walkthrough we will need an ATL ActiveX Control (once called “Full Control”) to work with.

This is where the Polygon sample from the MSDN documentation comes in. As I bemoaned in an earlier post, I wasn’t successful in running that code in VS 2008 nor did the ATL wizard work in Visual Studio 2010 when I tried to build it myself guided by the tutorial. In the end I hand coded some of the mixing text and the result is the Polygon project in the code for this article.

I am including in the source code for the article two more projects:

  1. WfPolygonUserControlLibrary which is the Windows Forms User Control Library which defines WfPolygonUserControl that wraps the ActiveX.
  2. WpfPolygonAppWithUserControl which demonstrates the use of the WfPolygonUserControl in a WPF project.

As previousltymentioned, this approach is simple to implement (there is no need to call aximp on the command line. All you need to do is to select Choose Items on the Tool Box and wait for 10 minutes to add the ActiveX component to the Tool Box from the COM tab).

However, in a way, it is inefficient because in order for Visual Studio to add the ActiveX control to the Tool Box it needs to generate two assemblies. One is the RCW (with the name Interop.PolygonLib.dll) and a second (called AxInterop.PolygonLib.dll) contains a Control that wraps the RCW .

The next section demonstrates the approach that I prefer which is to use tlbimp and host the control it creates directly in the WindowsFormsHost without building an intermediate WfPolygonUserControl.

WPF Application using an ATL ActiveX Object

I ran tlbimp on the Polygon.dll dll to create AxPolygonLib.dll (UserControl) and PolygonLib.dll (RCW).

Then I created a new WPF project called WpfPolygonApp to which I added the following references:

  • WindowsFormsIntegration (for the WindowsFormsHost)
  • PolygonLib.dll
  • AxPolygonLib.dll

This is the code for my window, in which you can see the WindowsFormsHost in action.

<Window x:Class="WpfPolygonApp.Window1"

       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

       xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"

       xmlns:uc="clr-namespace:AxPolygonLib;assembly=AxPolygonLib"

       Title="Window1"

       Height="300"

       Width="300">

   <Grid>

      <wfi:WindowsFormsHost>

         <uc:AxPolyCtl x:Name="polyCtl"

                      ClickIn="polyCtl_ClickIn"

                      ClickOut="polyCtl_ClickOut" />

      </wfi:WindowsFormsHost>

   </Grid>

</Window>

And this is the code behind:

    public partial class Window1 : Window

    {

        public Window1()

        {

            InitializeComponent();

        }

 

        void polyCtl_ClickIn(object sender, _IPolyCtlEvents_ClickInEvent e)

        {

            polyCtl.Sides++;

            polyCtl.FillColor = System.Drawing.Color.Green;

        }

 

        void polyCtl_ClickOut(object sender, _IPolyCtlEvents_ClickOutEvent e)

        {

            polyCtl.Sides--;

            polyCtl.FillColor = System.Drawing.Color.Red;

        }

    }

As you can see, I followed the example in Step 7 of the ATL Tutorial which builds an html page for the polyCtl control and implements event handlers such that when clicking inside the polygon the number of sides increases and when clicking outside, the number of sides decreases.

Here I also added a change of the FillColor to demonstrate use of the Stock Property that we added in the ATL control (Step 2 in the ATL Tutorial).

This concludes our discussion on consuming COM objects (simple UI-less controls and ActiveX controls) and Windows Forms Controls in WPF Applications.

In the next post I will review the reverse – using a WPF control in a Windows Forms application.

Published Monday, May 25, 2009 2:55 AM by David Sackstein
תגים:, , , ,

Comments

# WPF Interop Part 1 - David&#39;s Blog

Monday, May 25, 2009 3:47 AM by WPF Interop Part 1 - David's Blog

Pingback from  WPF Interop Part 1 - David&#39;s Blog

# WPF Interop Part 3

Monday, May 25, 2009 6:32 PM by David's Blog

Continued from Part 2 . So now for the second scenario. Hosting WPF controls in legacy containers. Well

# Volvo 244 Wholesale Auto Parts, 244 Bulb Quality 1984 Volvo - 379.tgrconversions.com

Pingback from  Volvo 244 Wholesale Auto Parts, 244 Bulb Quality 1984 Volvo - 379.tgrconversions.com

# Sale Bueno Yaris, 2002 Toyota Yaris Window Motor - 366.tgrconversions.com

Pingback from  Sale Bueno Yaris, 2002 Toyota Yaris Window Motor - 366.tgrconversions.com

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above:
Powered by Community Server (Commercial Edition), by Telligent Systems