0

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?

  • A lot of the older Display technologies do not support proper Transparency. Windows Forms for example never had "true" transparency https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-give-your-control-a-transparent-background wich MS aknowleged "Windows Forms controls do not support true transparency. The background of a transparent Windows Forms control is painted by its parent. ". So it is not unlikely that there is no such way. Asuming nobody has better inforamtion, asume the combination you want is impossible. – Christopher Apr 15 '18 at 16:27
  • AFAIK since Windows 2000 layered windows are supported and if you set `AllowsTransparency` it adds the WS_EX_LAYERED flag to the Extended Styles of the window. This will automatically blend the window with all the other windows underneath as well as with the desktop background. – Tamas Karpati Apr 15 '18 at 16:36

1 Answers1

0

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://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#layered-windows

Anna Dolbina
  • 1,054
  • 1
  • 7
  • 7