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
- Create the hosted window with the WS_CHILD style and the WPF-provided hwndParent.
- If wrapping an existing window, reparent it with SetParent to the WPF parent and add WS_CHILD via SetWindowLong.
- 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
- Always include WS_CHILD in window creation styles for HwndHost content.
- Do not modify window styles after creation in ways that remove WS_CHILD.
- Use SetWindowLong to add WS_CHILD when wrapping pre-existing windows.
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
- SR.ChildWindowMustHaveCorrectParent
- SR.ChildWindowNotCreated
- ArgumentNullException
- InvalidOperationException
- InvalidOperationException
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)