C# WPF create dpi aware child window


I want to create a dpi aware child window inside a WPF window. The child window will be used for directX rendering.

I created a minimal example with the window as follows:

<Window ...
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="TestItem"/>
        <Border Background="Blue" x:Name="BorderHost"/>

The Border will be used to host my child window. The HwndHost for the border creates the directX swap chain and looks like this:

 public class ChildWindow : HwndHost
        private readonly Border parent;
        private IntPtr hWnd = IntPtr.Zero;

        public SwapChain SwapChain { get; private set; }

        public ChildWindow(Border parent)
            this.parent = parent;
            parent.SizeChanged += ParentOnSizeChanged;

        private void ParentOnSizeChanged(object sender, SizeChangedEventArgs e)
            // problem: width and height is not correctly scaled
            SwapChain?.Resize((int)(parent.ActualWidth), (int)(parent.ActualHeight));

        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
            // create subwindow
            hWnd = CreateWindowEx(
                0, // dwstyle
                "static", // class name
                "", // window name
                WS_CHILD | WS_VISIBLE, // style
                0, // x
                0, // y
                (int)parent.ActualWidth, // renderWidth
                (int)parent.ActualHeight, // renderHeight
                hwndParent.Handle, // parent handle
                IntPtr.Zero, // menu
                IntPtr.Zero, // hInstance
                0 // param

            // directx swap chain
            // problem: width and height is not correctly scaled
            SwapChain = new SwapChain(hWnd, (int)parent.ActualWidth, (int)parent.ActualHeight);

            return new HandleRef(this, hWnd);

        protected override void DestroyWindowCore(HandleRef hwnd)

        [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
        internal static extern bool DestroyWindow(IntPtr hwnd);

        [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
        internal static extern IntPtr CreateWindowEx(
            int dwExStyle,
            string lpszClassName,
            string lpszWindowName,
            int style,
            int x, int y,
            int width, int height,
            IntPtr hwndParent,
            IntPtr hMenu,
            IntPtr hInst,
            [MarshalAs(UnmanagedType.AsAny)] object pvParam

        internal const int
            WS_CHILD = 0x40000000,
            WS_VISIBLE = 0x10000000;

The main window intializes the child window and clears its background to black or white after a mouse move:

public partial class MainWindow : Window
        private ChildWindow child;
        private float childColor = 1.0f;

        public MainWindow()

        private void OnLoaded(object sender, RoutedEventArgs e)
            child = new ChildWindow(BorderHost);
            BorderHost.Child = child;

        private void MainWindow_OnMouseMove(object sender, MouseEventArgs e)
            if (child == null) return;
            if (child.SwapChain == null) return;

            // switch between black and white background
            childColor = 1.0f - childColor;

            // clear child background
            Device.Get().ClearRenderTargetView(child.SwapChain.Rtv, new RawColor4(childColor, childColor, childColor, childColor));

The full source code can be found on https://github.com/kopaka1822/DpiAwareChildwindow.


  • I cannot create a directx device and swap chain at once because I need to work with an already existing directx device. Thus the deferred swap chain initialization.
  • I have two monitors with different DPI and I want my app to be properly displayed on both devices.

In order to add dpi awareness to my app, I added a manifest with:

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
      <gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>

I set gdiScaling to true, because I want all WPF components inside the window to scale as usual.

The window looks fine when the monitor DPI is 1.0: fine

However, the child window position and size is wrong on my monitor with DPI 2.0: not_fine

How do I properly scale and position my child window?

Edit: This is what I get when I don't use the gdiScaling scaling inside the manifest and move my window from the 2.0 dpi to my 1.0 dpi screen: still_broken The window looks fine on the 2.0 dpi screen but the title bar of my window is now over sized on my 1.0 dpi screen.

asked on Stack Overflow Jan 5, 2020 by Felix Brüll • edited Jan 11, 2020 by Felix Brüll

1 Answer


According to the document, I modified gdiScaling to the following format, and it work for me.

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
      <!--<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>-->
    <windowsSettings xmlns="https://schemas.microsoft.com/SMI/2017/WindowsSettings">
answered on Stack Overflow Jan 10, 2020 by Drake Wu - MSFT

User contributions licensed under CC BY-SA 3.0