WPF being a fairly new technology might need to communicate with the components that are made in other technologies so in this section we will have a look as to how we can communicate with other systems that are built in Windows Forms or Activex.
Mixed UI Technologies
So if our WPF application needs to use controls that were developed earlier or just merely in different technology or we need to integrate with legacy plug ins or maybe there is some stuff which is available in WPF or we are moving our application to WPF but module by module. In all these cases our application will be hybrid of WPF and other applications.
WPF and HWNDs
The only major issue in WPF is that WPF is designed differently from Win32. The major difference is in the composition of the Window i.e how different elements combine to form a Window. In a classic Win32 app the composition works by partitioning the window into different elements. It UI elements gets the ownership of the window. This portioning is tied to the Window Handle or HWND. HWND is the type that represents Window handle in User 32. So each Win32 control has its own HWND owns all the pixels in some region of the screen, whereas in WPF the composition works in different way. WPF treats the entire window as one big canvas and all the components get to paint on that. So the individual WPF components don’t get to won a region individually. SO WPF creates just one HWND to fill the entire window. If we run the tool designed to explore the window handle then we can see that WPF window has one HWND.
As you see in the image below I have run Microsoft Spy++ and as you could see the WPFInteropSample application has a HWND wrapper. So we can see that WPF has just one big HWND for the application. However Pop ups have their own HWND as they are separate top level windows.
Interop Not Free
You might think that using the existing components might be cheaper but that’s not the case with interop in the long run.
- The development cost if more as you are using a mixture of technologies.
- There might be design compromises due the limitation of using multiple technologies in application.
- During the runtime the application memory usage will increase by using both Windows Forms and WPF in one application.
- There can CPU costs as well.
- Also the WPF and Winforms control only almost look alike and the difference becomes more obvious
So we should use hybrid applications with discretion.
Limitations of Interop
When WPF was being designed it was not planned to be run on older version of windows bu after lot a demand Microsoft changed that and made it available to run on Windows Server 2003 and Windows XP which was great. But to get this accomplished there were changes that were made and those led to a few limitations. The major issues are as below:
This is the major issue. Just like two aircrafts cannot occupy the same airspace similarly two different technologies cannot occupy the same pixel space. The WPF window needs to partitioned so that each area can be used by WPF, Win32 or Directx. We cannot have more than one technologies rendering on the same pixel.
The directx limitation might seem strange as we know that WPF uses directx but the reason is that WPF does not want to share its directx services. In .NET 3.5 SP1 we can take the output of directx and use it as a brush in WPF. So it is possible to get the directx output into a region of the window. But still the control is with WPF and the HWND control handled by WPF
The transforms applied in WPF will not apply to other technologies even though the component of other technology may be a child of WPF content.
Event bubbling does not work across technology boundaries either.
Multi-level hybrid Nesting
There are limitations on how deeply we can nest the content. We cannot host a Windows Forms Controls inside a WPF Control that is hosted inside a Windows forms controls that is the child of the WPF window.
Airspace Issues in WPF
- Animated Objects
- Pseudo Transparency
Multiple Top Level Windows
A simple solution to all the airspace problem is to use multiple top level windows as all the airspace issues occur when Win32 and WPF components share the same window. Airspace limitations do not apply to the desktop level. So a simple solution to the Z-order problem is to put all the content that needs to go on top in a different window. This is the same way in which pop up works. It shows up on top of all the other windows and content. We can make use of layered windows introduced by windows 2000 as after that it has been possible for multiple windows to share pixel screen. Also the WPF application can make use of transparent windows (Window.AllowsTransparency).
Another issue in WPF interop is handling the user input as event bubbling and tunneling is tied into WPF visual tree. So if the mouse goes into the other technology elements then events won’t bubble out of it. So the properties like IsMouseOver, IsFocusWithin, etc will not return what we are looking for.
The following table show how easy or difficult the various Interop combinations are. The easiest interop to do is with Windows forms. It is slightly harder to interop with Win32 components because we are dealing with C++ code. Hosting an activeX control inside WPF is easy but vice versa is difficult. If we want to host WPF content inside HTML then it’s easy but user restrictions are applied to WPF xbap inside the browser.
|Technology||WPF Inside||WPF Outside|
|Win32||Fairly Easy||Fairly Easy|
|HTML||Easy (With Limitations)||Easy|
WPF in Win32
The most important thing to do is to host the WPF content inside the Win32 because without this we would not be able to display the WPF content at all. This service is provided by the HwndSource class as it connects the WPF visual tree to an Hwnd. We can do this as shown in the code below. We just need to pass the parameters inside the constructor and then set the WPF visual tree as the root visual.
All the WPF content uses an HwndSource and we can retrieve this by the following code. We can get hold of the Hwdn in which the WPF content is displayed and this is useful as Win32 components require us to know Hwnd.
Win32 in WPF
To host the Win32 content inside the WPF we can use HwnHost and derive from it. Then overriding the methods to create, destroy window and for handling its windows messages.
HwndHost Keyboard Handling
HwndHost host has some optional overrides for dealing with keyboard inputs. If we want the keyboard accelerators to work perfectly whether inside WPF content or Win32 content then we need to override these methods.
If we are hosting WPF content in a Win32 application then we need to modify the Message Loop to provide the WPF Dispatcher with the opportunity it needs to manage the window messages. The Class ComponenetDispatcher that offers various static methods that we should call for message handling when a message arrives or when it’s going idle. Also WPF needs to know when you have entered the model state so that WPF can stop responding to UI inputs.
Note that we don’t need to do this when we are integrating Windows forms and WPF. WPF and Windows Forms collaborate to provide our application with message handling.
WPF inside Windows Forms
In the code below we can see WPF content inside a Windows Forms container. There is a class called ElementHost that derives from WindowsFormsControl class so that we can edit any windows forms user interface. Buts cild property is of type FramworkElement that allows us to host any WPF element.
Create a WPF Control Library and add the following code to the UserControl.
Now add a Windows Forms application to the solution and refer this control library in that project.
When we select the main form we see that theUserControl1 is available for us to use.
Just drag it on to the windows form and run the application and we can see the WPF control inside the Windows Forms application.
Windows Form inside WPF
Hosting Windows forms content inside a WPF application is almost identical. Instead of ElementHost we have WindowsFormsHost and this derives from framework element and we can add it to any WPF UI and its child property accepts a Windows Forms Control.
Windows Forms and Layout
While using the ElementHost or WindowFormsHost WPF does its best to bridge between the two layout engines and overall it works fine (Docking, Anchoring and Auto-Sizing). Even the scaling transform works for WindowsForm inside WPF.
Ambient Property in Windows Forms
These are like WPF inherited properties. Windows forms uses these to make sure that the foreground color, background color and mouse cursor are propagated to child controls.
WindowsFormHost and ElementHost both have a PropertyMap which they use to manage the transition back and forth between the inherited properties and Ambient properties and it works fine most of times.
If want to modify this then we can register a callback that will be called while propagation of any property across the interop boundary.
Any questions, comments or feedback are most welcome.
The code for this post can be found here.