dotnet/wpf · error · InvalidOperationException

SR.HostedWindowMustBeAChildWindow

Error message

SR.HostedWindowMustBeAChildWindow

What it means

After BuildWindowCore returns, HwndHost verifies that the created window has the WS_CHILD style. If the window is not a child window, BuildWindow throws InvalidOperationException (SR.HostedWindowMustBeAChildWindow) because HwndHost can only host child windows inside the WPF window hierarchy.

Solutions

  1. Create the hosted window with the WS_CHILD style and the WPF-provided hwndParent.
  2. If wrapping an existing window, reparent it with SetParent to the WPF parent and add WS_CHILD via SetWindowLong.
  3. Do not strip WS_CHILD in post-creation style adjustments.

Example fix

// before
CreateWindowEx(0, cls, "", WS_OVERLAPPEDWINDOW, ...);
// after
CreateWindowEx(0, cls, "", WS_CHILD | WS_VISIBLE, ...);
Defensive patterns

Strategy: validation

Validate before calling

int style = UnsafeNativeMethods.GetWindowLong(new HandleRef(null, hwnd), NativeMethods.GWL_STYLE);
if ((style & NativeMethods.WS_CHILD) == 0)
    throw new InvalidOperationException("Hosted window must have WS_CHILD style");

Type guard

bool IsChildWindow(IntPtr hwnd) =>
    (UnsafeNativeMethods.GetWindowLong(new HandleRef(null, hwnd), NativeMethods.GWL_STYLE)
        & NativeMethods.WS_CHILD) != 0;

Prevention

When it happens

Trigger: A derived BuildWindowCore creates a top-level (WS_POPUP/WS_OVERLAPPED) window, or creates a child window then removes/overrides the WS_CHILD style bit.

Common situations: Reusing existing top-level native windows as hosted content, copying window-creation code that omits WS_CHILD, or altering styles via SetWindowLong after creation.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/b158a0fdc40b6860. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/HwndHost.cs:1018

        private void BuildWindow(HandleRef hwndParent)
        {
            // Demand unmanaged code to the caller. IT'S RISKY TO REMOVE THIS
            DemandIfUntrusted();

            // Allow the derived class to build our HWND.
            _hwnd = BuildWindowCore(hwndParent);

            if(_hwnd.Handle == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(_hwnd))
            {
                throw new InvalidOperationException(SR.ChildWindowNotCreated);
            }

            // Make sure that the window that was created is indeed a child window.
            int windowStyle = UnsafeNativeMethods.GetWindowLong(new HandleRef(this,_hwnd.Handle), NativeMethods.GWL_STYLE);
            if((windowStyle & NativeMethods.WS_CHILD) == 0)
            {
                throw new InvalidOperationException(SR.HostedWindowMustBeAChildWindow);
            }

            // Make sure the child window is the child of the expected parent window.
            if(hwndParent.Handle != UnsafeNativeMethods.GetParent(_hwnd))
            {
                throw new InvalidOperationException(SR.ChildWindowMustHaveCorrectParent);
            }

            // Test to see if hwndParent and _hwnd have different DPI_AWARENESS_CONTEXT's
            if (DpiUtil.GetDpiAwarenessContext(_hwnd.Handle) != DpiUtil.GetDpiAwarenessContext(hwndParent.Handle))
            {
                _hasDpiAwarenessContextTransition = true;
            }

            // Only subclass the child HWND if it is owned by our thread.
            int idWindowProcess;
            int idWindowThread = UnsafeNativeMethods.GetWindowThreadProcessId(_hwnd, out idWindowProcess);

View on GitHub (pinned to 81131a70a4)