In short terms: I would like to use some elements from UWP in my WPF application. My issue is that the UWP elements always appear on top of all my other WPF UI elements (e.g. buttons, rectangles,...).
I cannot share the original example, but I'm currently trying to get it working with the following example: https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/tree/master/dotnet/WPF/HelloComposition
In this example there is the "CompositionHostControl". Just to prove that I can put a WPF UI control in front of it I added a rectangle:
<local:CompositionHostControl x:Name="CompositionHostControl1"
Grid.Row="1" Grid.Column="1"
VerticalAlignment="Top"
Width="600" Height="500"
BorderBrush="LightGray" BorderThickness="3" Panel.ZIndex="1"/>
<Rectangle Fill="Aqua" Width="200" Height="200" Grid.Row="1" Grid.Column="1" Panel.ZIndex="2" />
Based on my understanding of "Panel.ZIndex" the rectangle should be infront (=top most) of the CompositionHostControl.
However, this does not work. The rectangle is always rendered behind the CompositionHostControl.
I also looked into the 'CompositionHostControl.xaml.cs' but could not find anything that sets this control to be topmost.
In the 'CompositionHost.cs' I changed line 119 from
interop.CreateDesktopWindowTarget(hwndHost, true, out raw);
to
interop.CreateDesktopWindowTarget(hwndHost, false, out raw);
since the second parameter has the name 'isTopmost'. However, that also had no effect.
I had a look at https://learn.microsoft.com/en-us/windows/uwp/composition/visual-layer and to me it looks like it should be possible to change the Z order, but I did not find out how to do it.
I also had a look at https://mtaulty.com/2015/12/17/m_15996/ where it more or less clearly says "I can also combine some or all of 1-4 above in order to allow the separate technologies to play to their strengths – e.g. I might have some Direct3D game sitting underneath a set of game controls provided by a XAML layer."
Last but not least, I'm in general aware of the Air Space problem: https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-3.0/aa970688(v=vs.85)?redirectedfrom=MSDN However, my understanding was that this would not be the case since everything is based on the visual layer.
This problem is still a matter of airspace, this limitation comes from mixing different technologies at the window manager level, not a WPF implementation decision.
CompositionHostControl is essentially a Win32 child window and you cannot draw WPF content on top of it.
It is recommended to use SetWindowRgn
to limit the drawing of some areas. For example, if you want to add a WPF Rectangle above, you can use CombineRgn
to get a region with a rectangular hole, so that the content of WPF can be displayed.
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
// Create Window
hwndHost = IntPtr.Zero;
hwndHost = CreateWindowEx(0, "static", "Win32Window",
WS_CHILD | WS_VISIBLE ,
0, 0,
hostWidth, hostHeight,
hwndParent.Handle,
(IntPtr)HOST_ID,
IntPtr.Zero,
0);
// Create Dispatcher Queue
dispatcherQueue = InitializeCoreDispatcher();
// Build Composition Tree of content
InitComposition(hwndHost);
var hrgn = CreateRectRgn(0, 0, hostWidth, hostHeight);
var wpfRgn = CreateRectRgn(300, 300, 200, 200);
var region = CreateRectRgn(0, 0, 0, 0);
CombineRgn(region, hrgn, wpfRgn, RGN_DIFF); //RGN_DIFF=4
int regionType = SetWindowRgn(hwndHost, region, true);
return new HandleRef(this, hwndHost);
}