Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Child window hosted in third-party application invisible on Windows 7 Aero themes

I have a WPF window which has to behave as an overlay of a window in a third-party running application. My WPF window must be mostly transparent with some visible controls, always be positioned right on top of the other window in the z-order, move with it, etc. In short: I want it to behave like a child window.

I have reviewed the techniques offered here (WPF HwndSource technique) and here (WPF SetParent technique). The HwndSource technique doesn't work at all. The SetParent technique works on Windows 7, but only with the basic theme. With Windows 7 Aero themes, it doesn't work: my child window is invisible.

I am looking for a solution that will work on all Windows 7 themes.

My test application creates a test window and calls SetParent to make it a child window of a (hard-coded HWND to) a Notepad window.

Under the basic theme, it looks like so:

Basic Theme

Under the Windows 7 theme, I don't see it:

Aero Theme

Child window XAML:

<Window x:Class="WpfApplication22.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TestWindow" Height="300" Width="300" Background="#63000000" ShowInTaskbar="False" WindowStyle="None" Initialized="Window_Initialized" Loaded="Window_Loaded" AllowsTransparency="True">
    <Grid>
        <Ellipse Height="87" HorizontalAlignment="Left" Margin="12,12,0,0" Name="ellipse1" Stroke="Black" VerticalAlignment="Top" Width="167" Fill="#FFBE3A3A" />
    </Grid>
</Window>

The child window form load handler code:

    var parentHwnd = new IntPtr(0x01DE0DFC); // Running Notepad
    var guestHandle = new WindowInteropHelper(this).Handle;

    var style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_CHILD | WS_POPUP;
    SetWindowLong(guestHandle, GWL_STYLE, (int)(style));
    SetParent(guestHandle, parentHwnd);

(I've tried un-setting the WS_POPUP style. It has no effect.)

like image 621
Udi Bar-On Avatar asked Apr 08 '13 16:04

Udi Bar-On


1 Answers

Instead of using SetParent, set WindowInteropHelper.Owner of your WPF "child" window to the window you want to display above.

Note that in .NET 3.5, if you do this in any of the "child" window's event handlers, even as early as OnSourceInitialized, the window owner doesn't really get set. Apparently it's too late to set an owner at that point.

Instead, set the Owner in the code that creates the window, before you call Show(). .NET 4 seems to allow setting the Owner from within SourceInitialized.

  • Jack
like image 88
Jack Juiceson Avatar answered Nov 08 '22 20:11

Jack Juiceson