diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/HwndHost.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/HwndHost.cs
index 15e744e420d..54c17063a61 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/HwndHost.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Interop/HwndHost.cs
@@ -976,23 +976,28 @@ private void BuildOrReparentWindow()
UnsafeNativeMethods.SetParent(_hwnd, new HandleRef(null,hwndParent));
}
}
- else
+ else if (_hwnd.Handle != IntPtr.Zero)
{
// Reparent the window to notification-only window provided by SystemResources
// This keeps the child window around, but it is not visible. We can reparent the
// window later when a new parent is available
var hwnd = SystemResources.GetDpiAwarenessCompatibleNotificationWindow(_hwnd);
- UnsafeNativeMethods.SetParent(_hwnd, new HandleRef(null, hwnd.Handle));
- // ...But we have a potential problem: If the SystemResources listener window gets
- // destroyed ahead of the call to HwndHost.OnDispatcherShutdown(), the HwndHost's window
- // will be destroyed too, before the "logical" Dispose has had a chance to do proper
- // shutdown. This turns out to be very significant for WebBrowser/ActiveXHost, which shuts
- // down the hosted control through the COM interfaces, and the control destroys its
- // window internally. Evidently, the WebOC fails to do full, proper cleanup if its
- // window is destroyed unexpectedly.
- // To avoid this situation, we make sure SystemResources responds to the Dispatcher
- // shutdown event after this HwndHost.
- SystemResources.DelayHwndShutdown();
+ Debug.Assert(hwnd != null);
+ Trace.WriteLineIf(hwnd == null, $"- Warning - Notification Window is null\n{new System.Diagnostics.StackTrace(true).ToString()}");
+ if (hwnd != null)
+ {
+ UnsafeNativeMethods.SetParent(_hwnd, new HandleRef(null, hwnd.Handle));
+ // ...But we have a potential problem: If the SystemResources listener window gets
+ // destroyed ahead of the call to HwndHost.OnDispatcherShutdown(), the HwndHost's window
+ // will be destroyed too, before the "logical" Dispose has had a chance to do proper
+ // shutdown. This turns out to be very significant for WebBrowser/ActiveXHost, which shuts
+ // down the hosted control through the COM interfaces, and the control destroys its
+ // window internally. Evidently, the WebOC fails to do full, proper cleanup if its
+ // window is destroyed unexpectedly.
+ // To avoid this situation, we make sure SystemResources responds to the Dispatcher
+ // shutdown event after this HwndHost.
+ SystemResources.DelayHwndShutdown();
+ }
}
}
finally
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs
index 4817baac88c..1bc74098942 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs
@@ -1023,7 +1023,7 @@ internal static void OnThemeChanged()
/// This is the default HWND used to listen for theme-change messages.
///
/// When is true, additional notification windows are created
- /// on-demand by or
+ /// on-demand by
/// as the need arises. For e.g., when calls into ,
/// we would look for a notify-window that matches both (a) DPI Awareness Context and (b) DPI Scale factor of the foreign window from HwndHost to return. If none is found,
/// we would create one and add it to our list in and return the newly created notify-window.
@@ -1054,27 +1054,6 @@ private static void EnsureResourceChangeListener()
}
}
- ///
- /// Ensures that the notify-window corresponding to a given has been
- /// created.
- ///
- /// DPI Awareness Context for which notify-window has to be ensured
- private static void EnsureResourceChangeListener(DpiAwarenessContextValue dpiContextValue)
- {
- EnsureResourceChangeListener();
-
- // Test if _hwndNotify has a key that contains dpiContextValue - otherwise create and add a notify-window with
- // this DPI Awareness Context
- if (_hwndNotify.Keys.FirstOrDefault((hwndDpiContext) => hwndDpiContext.DpiAwarenessContextValue == dpiContextValue) == null)
- {
- var hwndDpiInfo = CreateResourceChangeListenerWindow(dpiContextValue);
- if (!_dpiAwarenessContextAndDpis.Contains(hwndDpiInfo))
- {
- _dpiAwarenessContextAndDpis.Add(hwndDpiInfo);
- }
- }
- }
-
///
/// Ensures that a notify-window corresponding to a given HwndDpiInfo(=DpiAwarenessContextValue + DpiScale) has been
/// created.
@@ -1085,9 +1064,16 @@ private static void EnsureResourceChangeListener(DpiAwarenessContextValue dpiCon
/// whose characteristics we are trying to match, we are guaranteed that the DPI Scale factor of the newly created HWND
/// would be identical to that of the reference HWND.
///
- private static void EnsureResourceChangeListener(DpiUtil.HwndDpiInfo hwndDpiInfo)
+ private static bool EnsureResourceChangeListener(DpiUtil.HwndDpiInfo hwndDpiInfo)
{
EnsureResourceChangeListener();
+
+ // It's meaningless to ensure RCL for Invalid DACV
+ if (hwndDpiInfo.DpiAwarenessContextValue == DpiAwarenessContextValue.Invalid)
+ {
+ return false;
+ }
+
if (!_hwndNotify.ContainsKey(hwndDpiInfo))
{
var hwndDpiInfoKey =
@@ -1095,13 +1081,15 @@ private static void EnsureResourceChangeListener(DpiUtil.HwndDpiInfo hwndDpiInfo
hwndDpiInfo.DpiAwarenessContextValue,
hwndDpiInfo.ContainingMonitorScreenRect.left,
hwndDpiInfo.ContainingMonitorScreenRect.top);
- Debug.Assert(hwndDpiInfo == hwndDpiInfoKey);
- if (!_dpiAwarenessContextAndDpis.Contains(hwndDpiInfo))
+ if (hwndDpiInfoKey == hwndDpiInfo && // If hwndDpiInfoKey != hwndDpiInfo, something is wrong, abort.
+ !_dpiAwarenessContextAndDpis.Contains(hwndDpiInfo))
{
_dpiAwarenessContextAndDpis.Add(hwndDpiInfo);
}
}
+
+ return _hwndNotify.ContainsKey(hwndDpiInfo);
}
///
@@ -1113,7 +1101,7 @@ private static void EnsureResourceChangeListener(DpiUtil.HwndDpiInfo hwndDpiInfo
/// y-coordinate position on the screen where the window is to be created
///
/// Assumes that and have been initialized. This method
- /// must only be called by or
+ /// must only be called by or
///
/// of the newly created , which is also a new key added into
private static DpiUtil.HwndDpiInfo CreateResourceChangeListenerWindow(DpiAwarenessContextValue dpiContextValue, int x = 0, int y = 0, [System.Runtime.CompilerServices.CallerMemberName] string callerName = "")
@@ -1652,8 +1640,12 @@ internal static HwndWrapper GetDpiAwarenessCompatibleNotificationWindow(HandleRe
DpiUtil.GetExtendedDpiInfoForWindow(hwnd.Handle, fallbackToNearestMonitorHeuristic: true) :
new DpiUtil.HwndDpiInfo(processDpiAwarenessContextValue, GetDpiScaleForUnawareOrSystemAwareContext(processDpiAwarenessContextValue));
- EnsureResourceChangeListener(hwndDpiInfo);
- return _hwndNotify[hwndDpiInfo].Value;
+ if (EnsureResourceChangeListener(hwndDpiInfo))
+ {
+ return _hwndNotify[hwndDpiInfo].Value;
+ }
+
+ return null;
}
///