Win32 native control in layered (transparent) WPF window is invisible

921 views Asked by At

I want to host a native Win32 (Qt widget) control in a WPF window. My problem is that in case I host it in a normal WPF window, everything works fine, but when I set AllowsTransparency of the WPF window to true, the native content won't be rendered anymore. I've made a simple test application which creates only a Win32 button to see if Qt is the culprit, but it's not.

This is the HwndHost implementation I have:

using System;
using System.Runtime.InteropServices;
using System.Windows.Interop;

namespace WpfHwndHostLayeredWindow
{
    class NativeButton : HwndHost
    {
        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {
            var hwnd = PInvoke.User32.CreateWindowEx(
                0, // EX_STYLE
                "BUTTON",
                "Win32 Button",
                PInvoke.User32.WindowStyles.WS_CHILD,
                0, 0, 100, 100,
                hwndParent.Handle,
                IntPtr.Zero, // hMenu
                new IntPtr(PInvoke.User32.GetWindowLong(hwndParent.Handle, PInvoke.User32.WindowLongIndexFlags.GWLP_HINSTANCE)),
                IntPtr.Zero // lParam
            );

            return new HandleRef(this, hwnd);
        }

        protected override void DestroyWindowCore(HandleRef hwnd)
        {
            PInvoke.User32.DestroyWindow(hwnd.Handle);
        }
    }
}

And the XAML for the WPF window:

<Window x:Class="WpfHwndHostLayeredWindow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfHwndHostLayeredWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        WindowStyle="None" ResizeMode="CanResizeWithGrip" AllowsTransparency="True">
    <Grid>
        <TextBlock Text="If you see this, the native control doesn't render properly"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"/>

        <local:NativeButton Margin="16"/>
    </Grid>
</Window>

I've tried setting the WS_EX_LAYERED flag but it didn't do anything.

Is there any way to make it work or is it a (known) limitation of WPF/HwndHost?

1

There are 1 answers

0
Anna Dolbina On

The layered window is a window that draws its content off-screen. That means the system automatically composes and repaints layered windows and the windows of underlying applications.

If we embed a native window into a layered window, the child window content may not be painted due to the window types conflict in some environments.

See https://learn.microsoft.com/en-us/windows/win32/winmsg/window-features#layered-windows