.NET Zone is brought to you in partnership with:

Jonathan creates software, mostly with C#, XAML, and HTML5/JS. He was awarded the Microsoft MVP in the "Client Application Development section in January 2011 Jon is a DZone MVB and is not an employee of DZone and has posted 23 posts at DZone. You can read more from them at their website. View Full User Profile

WPF 4.5 – Part 8: Solving Airspace Problems

08.19.2012
| 6347 views |
  • submit to reddit

weakEventIntegrating a Win 32 component is already possible in WPF 4.0, even in WPF 3.5 but there is the well-know issue called airspace problems. Each render technology belongs to only one airspace only. So when you place Win32 components in your WPF application they behave as a black hole for input and render transformations are not (well) applied, etc.

With this 4.5 release, the WPF team solves this drawback. In this post more explanation and an example of how it improves developers’ life will be given.

This post is a part of a series on WPF 4.5 new features.

What can’t be done in WPF4.0

I’ll only write about the integration of Winform/Win32 controls into WPF because this is the only subject I know well.
Before WPF 4.5, if you add a Win32 component into a wpf application using the hwndhost control you have some limitations:

  • Resizing is limited because only the container(hwndhost) will be resized, not the contained component itself.
  • Forget about rotation and skewing.
  • The hosted component is a black hole for your application : always at the top (forget the z-order!).
  • Opacity can’t be applied to an hosted Win32 control.
  • VisualBrush do not work with Win32 controls.
  • etc.

This is really annoying when you are used to WPF and this is why hosting a Win32 control into a WPF 4.0 apps is rarely done.

What’s new in WPF 4.5 ?

There is two main properties which are new in WPF 4.5 and related to this feature on the HwndHost class: IsRedirected and CompositionMode.

IsRedirected is a boolean which can be understand as : “do we solve airspace issue and share the screen between Win32 controls and WPF? You may wonder as I am why this is not set to true by default. I have the opinion that enabling it can lead to performance issues and is something you have to do only if needed.

CompositionMode is an enumeration which tells how deep the integration has to be done :

  • None: this is the default behavior and no integration is done: the airspace problems are still here :-(
  • OutputOnly: The airspace problem are solved but the user (and the input system) can’t interact with the hosted win32 component.
  • Full: the airspace problems are solved and interaction with the win32 component is possible.

This two properties have to be set before any rendering is done otherwise an exception will be thrown.

An example with the WebBrowser control

You may know that the WPF WebBrowser is in fact the Win32 one disguised as a WPF control. It means that every drawbacks that we have seen before are present when you use it on a application.

With WPF 4.5 you can now use it as if it is a standard control. All you have to do is to set the two properties we’ve seen before to the correct values.

So let’s say that I want to display a WebBrowser with an opacity of 0.6 and that I want it to be scaled to the half of it size. Because I am evil, I also want to display a VisualBrus of it inside a Rectangle just next to it. The XAML meeting these requirements will then be :

<UniformGrid Columns="2" x:Name="grid">
    <WebBrowser x:Name="_webBrowser" Source="http://www.jonathanAntoine.com"
                Margin="5" Opacity="0.6">
        <WebBrowser.RenderTransform>
            <ScaleTransform ScaleX="0.5" ScaleY="0.5" />
        </WebBrowser.RenderTransform>
    </WebBrowser>
    <Rectangle Margin="5">
        <Rectangle.Fill>
            <VisualBrush Visual="{Binding ElementName=_webBrowser}" />
        </Rectangle.Fill>
    </Rectangle>
</UniformGrid>

Then to make it works, I have to activate the redirecting and to set the composition mode of the WebBrowser internal HwndHost. The WPF team thought at this usage and you can find the same property on it. I do it in the Window constructor to be sure that no rendering has be done:

public MainWindow()
{
    InitializeComponent();
 
    _webBrowser.CompositionMode = System.Windows.Interop.CompositionMode.Full;
    _webBrowser.IsRedirected = true;
}

That’s all. Here is a comparison of the rendering in WPF 4.0 and 4.5:

This Demo project is available in my DropBox folder after registration.

Published at DZone with permission of Jon Antoine, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)