From d99cf673a9937d48a8559ea62f847f76fdd2ec72 Mon Sep 17 00:00:00 2001 From: Sam Johnson Date: Sat, 27 Jun 2026 01:25:34 -0500 Subject: [PATCH] Fix AppBars not receiving WM_DPICHANGED on Win11 Applied workaround so that the window does not receive the WS_EX_TOOLWINDOW style, but has an owner window that gets it instead. The drawback of the workaround is that the AppBar is displayed in Task Manager. --- src/ManagedShell.AppBar/AppBarWindow.cs | 5 ++++ .../Helpers/WindowHelper.cs | 29 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/ManagedShell.AppBar/AppBarWindow.cs b/src/ManagedShell.AppBar/AppBarWindow.cs index 2162db9d..ea72e7dd 100644 --- a/src/ManagedShell.AppBar/AppBarWindow.cs +++ b/src/ManagedShell.AppBar/AppBarWindow.cs @@ -136,6 +136,11 @@ public AppBarWindow(AppBarManager appBarManager, ExplorerHelper explorerHelper, PropertyChanged += AppBarWindow_PropertyChanged; ResizeMode = ResizeMode.NoResize; + if (EnvironmentHelper.IsWindows11OrBetter) + { + // With Windows 11, we cannot use the normal way to hide from taskbar (setting as a tool window) because that breaks receiving WM_DPICHANGED. + ShowInTaskbar = false; + } Title = ""; Topmost = true; UseLayoutRounding = true; diff --git a/src/ManagedShell.Common/Helpers/WindowHelper.cs b/src/ManagedShell.Common/Helpers/WindowHelper.cs index 6058f0a2..df8835ed 100644 --- a/src/ManagedShell.Common/Helpers/WindowHelper.cs +++ b/src/ManagedShell.Common/Helpers/WindowHelper.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Text; using static ManagedShell.Interop.NativeMethods; namespace ManagedShell.Common.Helpers @@ -102,7 +103,33 @@ public static IntPtr GetLowestDesktopChildHwnd() public static void HideWindowFromTasks(IntPtr hWnd) { - SetWindowLong(hWnd, GWL_EXSTYLE, (GetWindowLong(hWnd, GWL_EXSTYLE) & ~(int)ExtendedWindowStyles.WS_EX_APPWINDOW) | (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW); + int style = GetWindowLong(hWnd, GWL_EXSTYLE) & ~(int)ExtendedWindowStyles.WS_EX_APPWINDOW; + if (EnvironmentHelper.IsWindows11OrBetter) + { + // If the window has a Hidden Window owner, set the owner as a tool window instead so that we still receive WM_DPICHANGED on Windows 11. + // Hidden Window is the owner when ShowInTaskbar=false. Unfortunately, the window will not be hidden from Task Manager. + // https://github.com/dotnet/wpf/issues/10422 + IntPtr hwndOwner = GetWindow(hWnd, GetWindow_Cmd.GW_OWNER); + if (hwndOwner == IntPtr.Zero) + { + style |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW; + } + else + { + int TITLE_LENGTH = 1024; + StringBuilder titleBuilder = new StringBuilder(TITLE_LENGTH); + GetWindowText(hwndOwner, titleBuilder, TITLE_LENGTH + 1); + if (titleBuilder.ToString() == "Hidden Window") + { + SetWindowLong(hwndOwner, GWL_EXSTYLE, GetWindowLong(hwndOwner, GWL_EXSTYLE) | (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW); + } + } + } + else + { + style |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW; + } + SetWindowLong(hWnd, GWL_EXSTYLE, style); ExcludeWindowFromPeek(hWnd); }