Implementing the 3DVIA Composer Player ActiveX in Windows Presentation Foundation

In this post I want to address a technological issue related to the use of the relatively old ActiveX technology together with newer technologies provided by Microsoft that do not natively support plugins such as ActiveX controls.

History

In the past, Microsoft provided us with Windows Forms for developing user interfaces for Windows – these were pretty straight forward visual elements that could be placed upon a surface by drag and drop. So, for instance a button or a list box could be placed on the form and resized to meet the developer’s requirements. These were fairly static elements that were pre-defined, even though the user had some control over colors and size, etc. Windows Forms and ActiveX controls were developed around the same time and used a similar architecture that enabled an Active X control to be embedded in a Windows form with no more effort than drag and drop.

In 2006 Microsoft released .NET 3.0. Included in this release was a new architecture for building applications named Windows Presentation Foundation or WPF for short

WPF Overview

Microsoft Windows Presentation Foundation (WPF) is a user interface (UI) framework for building Windows client applications with immersive and intuitive user experiences. It is a subset of the Microsoft .NET Framework and was first introduced by Microsoft as part of .NET 3.0. It combines the application UI, 2D graphics, 3D graphics, documents, and multimedia into a single framework to help developers create rich and interactive applications. Its vector-based rendering engine takes advantage of the hardware acceleration of modern graphic cards. This makes the UI faster, scalable, and resolution independent.

The predecessor to WPF is Windows Forms, but WPF differs fundamentally in that it builds on top of DirectX, a technology that originally focused on multimedia and game programming. This adds the ability to implement advanced visual behavior such as animated cartoons, videos, or immersive 3D environments as well as take advantage of hardware acceleration when it is available. As it is still a subset of the .NET Framework, the WPF programming experience should be similar to Windows Forms or ASP.NET; however, the programming model is closer to web development with the “code-behind” approach. It should also be noted that WPF was not created to replace Windows Forms for every application as there are still cases where Windows Forms are good enough. Rather, WPF will continue to grow in popularity as a modern UI design tool and must be considered for any application that stands to benefit from a richer user experience.

WPF also fulfills the need for technology and tools that make it natural to separate the UI from the rest of the implementation as much as possible. The WPF system lets developers decouple visual behavior from the underlying program logic and provides a unified API and supporting tools for creating sophisticated UIs.

Microsoft’s Silverlight provides functionality that is mostly a subset of WPF to provide embedded web controls comparable to Adobe’s Flash.

WPF Benefits

There are many benefits to using WPF over Windows Forms below is a subset of the key benefits that I have found while building applications:

  1. 1.       Reusable Templates –WPF makes it easy to create reusable elements for your UIs. There are two types of templates in WPF: control templates and data templates. With control templates, you can redefine the way a control looks. For example, if your application needs to have all its list boxes with a blue background and a red border, you could use a control template to redefine the visual appearance of list boxes. Control templates also make it easier for designers to create the “look” for a UI control through a control template, with little to no impact on the actual development process. Data templates are similar, except that instead of defining the way a control looks, they define the way certain types of data are rendered. Imagine that you have an application dealing with people, such as a contact manager, and that you represent people in code with instances of a Person class. You can create a data template that defines how an instance of a Person is rendered in the UI. For example, an instance of Person might be visualized as a business card with a picture, first name, last name, and telephone number. If you use such a data template, whenever a Person instance is bound to some UI element, such as a list box, WPF will use the corresponding data templates. In practice, you will find that data templates are really handy when dealing with lists or other collections of data.
  2. 2.       Data Binding – When you hear about binding in WPF, you probably jump immediately to the concept of data binding. Data binding has already been made popular with Windows Forms and ASP.NET Web Forms, and has demonstrated its usefulness there. Although WPF has significant data binding features—significant in that it greatly outclasses its predecessors—it also allows you to declaratively bind other things such as commands, key bindings, animations, and events. For example, you can declaratively bind a button control to a command for pasting.
  3. 3.       Vector Graphics System for Harnessing the Power of Graphics Hardware Acceleration – WPF exploits whatever graphics processing unit (GPU) is available on a system by offloading as much work as possible to it. Modern interfaces also shouldn’t be constrained by the limitations of bit-mapped graphics. Accordingly, WPF relies entirely on vector graphics in contrast to raster graphics. This allows an image to be automatically scaled and resized to fit the size and resolution of the screen it’s displayed on, making the UI more device-independent. Rather than create different graphics for display on a small monitor and a big-screen television, the developer can let WPF handle this to display at the highest resolution supported by the device display without loss of quality. This additionally uses a retained mode graphics system, meaning that everything you draw persists and does not need to be redrawn after the window has been minimized. Retained mode allows the graphics system to optimize the display process.
  4. 4.       Rich interface design – WPF really shines when it comes to making an application look pretty. You can do such things as make the background of a text box red or surround a button with a thick blue border. Styles are also easy to reuse and allow you to skin controls almost similar to cascading style sheets (CSS) for HTML. Again, WPF styles are richer and have less ambiguity. They encompass all the visual characteristics you would expect, such as padding, margin, position, color, and so on. But you can also use styles to declare nonvisual properties.

For more information on WPF please refer to this link: http://msdn.microsoft.com/en-us/library/aa970268.aspx

Using Windows Forms Components with WPF

As mentioned above, Windows Forms and WPF are two very different architectures that really have nothing in common with each other. This being the case, implementing an old technology such as ActiveX inside WPF should not be supported – and originally this was the case! However, very quickly Microsoft acknowledged that developers had built many controls and components that they needed to reuse within WPF based applications. In order to accommodate their developers and increase the acceptance of WPF as the new standard for Windows development, Microsoft was nice enough to provide a control inside WPF that can host Windows forms components – aptly named the WindowsFormsHost. It is this control that enables us to embed our 3DVIA Composer Player inside a WPF application.

Creating a WPF Project Using 3DVIA Composer Player

So, let’s get started. Using Visual Studio, start a new WPF Project. I’m using version 2012 for this example, however any version from 2008 onwards will be supported. In these examples I’m also using C# as my preferred programing language however feel free to use Visual Basic if you so wish.

 7-18-2013 8-51-10 AM

Once the Project opens you will be presented with an empty Window as shown below. The screen is divided into two main areas – the design surface and the resulting XAML code. The toolbox should be located on the left by default.

 7-18-2013 8-56-21 AM

Placing Controls

Locate the WindowsFormsHost Control from the toolbox and drag and drop it onto the window as shown. As you place the control on the window you will notice how the XAML code updates. The control is inserted with some basic defaults that need editing. Either edit the XAML directly or use the Properties window on the right to resize the control as follows:

<Grid>

        <WindowsFormsHost x:Name=”playerHost” HorizontalAlignment=”Stretch” Height=”Auto” Margin=”2,2,2,40″ VerticalAlignment=”Stretch” Width=”Auto”/>

</Grid>

This will stretch the control over the complete window leaving a margin at the bottom where we can place a button.

Drag and drop a button from the toolbox onto the Window surface and place it near the bottom of the window. You can edit the XAML code as follows:

<Button x:Name=”btnClose” Content=”Close” HorizontalAlignment=”Right” Margin=”6,6″ VerticalAlignment=”Bottom” Width=”75″ Click=”btnClose_Click”/>

Note:  I added the “Click” event to the control by typing “Click”. Visual Studio did the rest for me and created the appropriate event. This can also be added through the properties window.

Adding Composer Player References

Now we have our basic layout we can add references to the 3DVIA Composer Player so that it can be used inside our WPF application.

In the past, using Windows Forms, we could add the Player control directly into the Visual Studio toolbox and then drag and drop it onto the form. Windows Forms created the required references for us automatically. However, with WPF, ActiveX controls are not natively supported and they therefore do not appear in the Toolbox. Instead, we can add a reference to the controls and manually add them into our WPF application. There are two DLL’s that we need to reference in our application, by default the DLLs that we need are not included with the Composer installation (since they are created through Visual Studio). The easiest way to create these DLLs is by creating a Windows Forms Application that uses the Player Control. If you haven’t done this previously, you can reference the Visual Studio project provided with the Sample in the Composer installation directory.

Once you have the two DLL’s required: AxInterop.DS3DVIAPlayerActiveXLib and Interop.DS3DVIAPlayerActiveXLib add a reference to these two DLL’s as shown below:

Right click the References node in the Solution explorer tree.

 7-18-2013 9-14-10 AM

Browse to the location on your disk where these two DLLs are located and add them in as references.

 7-18-2013 9-16-28 AM

Click on the Interop.DS3DVIAPlayerActiveXLib and edit its properties as shown below:

 7-18-2013 9-17-09 AM

Editing the Code Behind

Now that we have a reference to the 3DVIA Composer Player we need to add in a little code to make it all come together. Collapse the references tree and expand MainWindow1.xaml. Double click to open the code behind.

 7-18-2013 9-23-01 AM

If you created the Click event for the button you should have an event stub created for you as shown below. Edit the code so that it looks similar to the code shown below.

(click this image to enlarge it)

 7-18-2013 9-24-24 AM

There are really only two lines that are key to our integration at this point and these are as follows:

In the class MainWindow we define a reference to the ActiveX Control as follows:

AxDS3DVIAPlayerActiveXLib.AxDS3DVIAPlayerActiveX dsPlayer = new AxDS3DVIAPlayerActiveXLib.AxDS3DVIAPlayerActiveX();

In this case I have named the ActiveX control “dsPlayer”. All of the 3DVIA Composer Player APIs can now be accessed through this reference.

The next stage is to assign the player to the WindowsFormsHost control as a child of that control. This is achieved through the line defined here.

playerHost.Child = dsPlayer;

playerHost is the name that I gave to the windowsFormsHost Control in the XAML code.

Now compile and run the code – you should receive the Player embedded in the window as shown below. Note that the settings that we used in the XAML code allow the Player to be stretched to fit the window as we resize it.

<WindowsFormsHost x:Name=”playerHost” HorizontalAlignment=”Stretch” Height=”Auto” Margin=”2,2,2,40″ VerticalAlignment=”Stretch” Width=”Auto”/>

The Margin defines the placement of the control within the context of the parent control – in this case the window. The Horizontal and Vertical Alignment definitions define that the control should be stretched in both directions and the since the Height and width are set to Auto, the control will scale according to the size of the window.

 

7-18-2013 9-22-10 AM

 

Accessing the Player Libraries

Now that we have the ActiveX control embedded in our WPF application, we have all of its API and capabilities available to our application. As shown below, I can now create Player events and dynamically load files as required.

(click this image to enlarge it)

 7-18-2013 9-30-39 AM

The result of this code is to load the Player in the window and once it’s loaded go and load an SMG file from a pre-defined location. Once the file completes loading in the Player, the user is notified that the file has been loaded.

 7-18-2013 9-31-48 AM

From this point onwards, accessing and programing business logic into the Player is just the same as with the windows Forms implementation. Obviously with the power of WPF, you can do a lot more than with the windows forms implementation. Here, for instance I used the code behind to implement the events and much of the business logic; however this would be better placed in separate classes therefore separating GUI from logic. Obviously you can complete your program by putting all the code in the Mainwindow code behind file, but this will create a very big and unmanageable file. For more information on separating code please refer to “WPF Apps With The Model-View-ViewModel Design Pattern”  http://msdn.microsoft.com/en-us/magazine/dd419663.aspx