[WinUI3]Fix Windows 10 title bar borders (#36429)

* Fix borders for windows in the Settings UI

* Fix HOSTS window

* Fix Advanced Paste

* Fix Environment Variables

* Fix File Locksmith

* Fix Peek, with a caveat

* Fix Registry Preview

* Remove unused imports

* Clean up imports in OobeShellPage

* Move OSVersionHelper from Common.UI up into ManagedCommon
This commit is contained in:
Neil McAlister 2025-01-13 17:13:16 +02:00 коммит произвёл GitHub
Родитель aa9f3bb540
Коммит df48a33bb9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
23 изменённых файлов: 68 добавлений и 25 удалений

Просмотреть файл

@ -42,6 +42,9 @@ namespace ManagedCommon
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
[DllImport("dwmapi")]
internal static extern IntPtr DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
@ -100,5 +103,14 @@ namespace ManagedCommon
INPUT_KEYBOARD = 1,
INPUT_HARDWARE = 2,
}
[StructLayout(LayoutKind.Sequential)]
internal struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
}
}

Просмотреть файл

@ -4,10 +4,15 @@
using System;
namespace Common.UI
namespace ManagedCommon
{
public static class OSVersionHelper
{
public static bool IsWindows10()
{
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Minor < 22000;
}
public static bool IsWindows11()
{
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= 22000;

Просмотреть файл

@ -35,5 +35,20 @@ namespace ManagedCommon
}
}
}
/// <summary>
/// Workaround for a WinUI bug on Windows 10 in which a window's top border is always
/// black. Calls <c>DwmExtendFrameIntoClientArea()</c> with a <c>cyTopHeight</c> of 2 to force
/// the window's top border to be visible.<br/><br/>
/// Is a no-op on versions other than Windows 10.
/// </summary>
public static void ForceTopBorder1PixelInsetOnWindows10(IntPtr handle)
{
if (OSVersionHelper.IsWindows10())
{
var margins = new NativeMethods.MARGINS { cxLeftWidth = 0, cxRightWidth = 0, cyBottomHeight = 0, cyTopHeight = 2 };
NativeMethods.DwmExtendFrameIntoClientArea(handle, ref margins);
}
}
}
}

Просмотреть файл

@ -82,6 +82,7 @@ namespace AdvancedPaste
};
WindowHelpers.BringToForeground(this.GetWindowHandle());
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(this.GetWindowHandle());
}
private void OnActivated(object sender, WindowActivatedEventArgs args)

Просмотреть файл

@ -40,6 +40,7 @@ namespace EnvironmentVariables
var handle = this.GetWindowHandle();
RegisterWindow(handle);
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(handle);
WindowHelpers.BringToForeground(handle);
MainPage = App.GetService<EnvironmentVariablesMainPage>();

Просмотреть файл

@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using ManagedCommon;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
@ -22,6 +22,7 @@ namespace FileLocksmithUI
SetTitleBar(AppTitleBar);
Activated += MainWindow_Activated;
AppWindow.SetIcon("Assets/FileLocksmith/Icon.ico");
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(this.GetWindowHandle());
var loader = ResourceLoaderInstance.ResourceLoader;
var title = isElevated ? loader.GetString("AppAdminTitle") : loader.GetString("AppTitle");

Просмотреть файл

@ -39,6 +39,7 @@ namespace Hosts
var handle = this.GetWindowHandle();
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(handle);
WindowHelpers.BringToForeground(handle);
Activated += MainWindow_Activated;

Просмотреть файл

@ -5,7 +5,7 @@
using System;
using ColorPicker.Helpers;
using Common.UI;
using ManagedCommon;
using Wpf.Ui.Controls;
namespace ColorPicker

Просмотреть файл

@ -7,9 +7,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Common.UI;
using ImageResizer.ViewModels;
using ManagedCommon;
using Microsoft.Win32;
using Wpf.Ui.Controls;

Просмотреть файл

@ -6,6 +6,7 @@ using System;
using System.IO;
using System.Windows;
using System.Windows.Media;
using ManagedCommon;
using Microsoft.Win32;
using Wox.Infrastructure.Image;
using Wox.Infrastructure.UserSettings;
@ -50,7 +51,7 @@ namespace PowerLauncher.Helper
private void SetSystemTheme(ManagedCommon.Theme theme)
{
_mainWindow.Background = Common.UI.OSVersionHelper.IsWindows11() is false ? SystemColors.WindowBrush : null;
_mainWindow.Background = OSVersionHelper.IsWindows11() is false ? SystemColors.WindowBrush : null;
_mainWindow.Resources.MergedDictionaries.Clear();
_mainWindow.Resources.MergedDictionaries.Add(new ResourceDictionary
@ -66,7 +67,7 @@ namespace PowerLauncher.Helper
Source = new Uri(themeString, UriKind.Absolute),
};
_mainWindow.Resources.MergedDictionaries.Add(fluentThemeDictionary);
if (!Common.UI.OSVersionHelper.IsWindows11())
if (!OSVersionHelper.IsWindows11())
{
// Apply background only on Windows 10
// Windows theme does not work properly for dark and light mode so right now set the background color manual.
@ -95,7 +96,7 @@ namespace PowerLauncher.Helper
{
Source = new Uri(styleThemeString, UriKind.Relative),
});
if (Common.UI.OSVersionHelper.IsWindows11())
if (OSVersionHelper.IsWindows11())
{
// Apply background only on Windows 11 to keep the same style as WPFUI
_mainWindow.Background = new SolidColorBrush

Просмотреть файл

@ -15,6 +15,7 @@ using System.Windows.Interop;
using System.Windows.Media.Imaging;
using Common.UI;
using ManagedCommon;
using Microsoft.PowerLauncher.Telemetry;
using Microsoft.PowerToys.Telemetry;
using PowerLauncher.Helper;

Просмотреть файл

@ -7,8 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Common.UI;
using ManagedCommon;
using Microsoft.Win32;
using Wox.Plugin.Common.VirtualDesktop.Interop;
using Wox.Plugin.Common.Win32;

Просмотреть файл

@ -48,7 +48,8 @@ namespace Peek.UI
ViewModel = Application.Current.GetService<MainWindowViewModel>();
TitleBarControl.SetTitleBarToWindow(this);
AppWindow.TitleBar.ExtendsContentIntoTitleBar = true;
ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(this.GetWindowHandle());
AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
AppWindow.SetIcon("Assets/Peek/Icon.ico");

Просмотреть файл

@ -231,7 +231,7 @@ namespace Peek.UI.Views
if (AppWindowTitleBar.IsCustomizationSupported())
{
AppWindow appWindow = mainWindow.AppWindow;
appWindow.TitleBar.ExtendsContentIntoTitleBar = true;
mainWindow.ExtendsContentIntoTitleBar = true;
appWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
appWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
appWindow.TitleBar.ButtonForegroundColor = ThemeHelpers.GetAppTheme() == AppTheme.Light ? Colors.DarkSlateGray : Colors.White;

Просмотреть файл

@ -38,8 +38,8 @@ namespace RegistryPreview
OpenWindowPlacementFile(settingsFolder, windowPlacementFile);
// Update the Win32 looking window with the correct icon (and grab the appWindow handle for later)
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
Microsoft.UI.WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle);
IntPtr windowHandle = this.GetWindowHandle();
WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle);
appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
appWindow.SetIcon("Assets\\RegistryPreview\\RegistryPreview.ico");
@ -49,6 +49,7 @@ namespace RegistryPreview
// Extend the canvas to include the title bar so the app can support theming
ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(windowHandle);
SetTitleBar(titleBar);
// if have settings, update the location of the window

Просмотреть файл

@ -3,8 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
using Common.UI;
using ManagedCommon;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{

Просмотреть файл

@ -241,6 +241,10 @@ namespace Microsoft.PowerToys.Settings.UI
// https://github.com/microsoft/microsoft-ui-xaml/issues/7595 - Activate doesn't bring window to the foreground
// Need to call SetForegroundWindow to actually gain focus.
WindowHelpers.BringToForeground(settingsWindow.GetWindowHandle());
// https://github.com/microsoft/microsoft-ui-xaml/issues/8948 - A window's top border incorrectly
// renders as black on Windows 10.
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
}
else
{
@ -255,6 +259,7 @@ namespace Microsoft.PowerToys.Settings.UI
OobeWindow oobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.Overview);
oobeWindow.Activate();
oobeWindow.ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
SetOobeWindow(oobeWindow);
}
else if (ShowScoobe)
@ -263,6 +268,7 @@ namespace Microsoft.PowerToys.Settings.UI
OobeWindow scoobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.WhatsNew);
scoobeWindow.Activate();
scoobeWindow.ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
SetOobeWindow(scoobeWindow);
}
else if (ShowFlyout)
@ -310,6 +316,7 @@ namespace Microsoft.PowerToys.Settings.UI
// Window is also needed to show MessageDialog
settingsWindow = new MainWindow();
settingsWindow.ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow));
settingsWindow.Activate();
settingsWindow.NavigateToSection(StartupPage);
ShowMessageDialog("The application is running in Debug mode.", "DEBUG");

Просмотреть файл

@ -6,12 +6,13 @@ using System;
using System.Collections.ObjectModel;
using System.Globalization;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using WinRT.Interop;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
@ -306,6 +307,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
// A custom title bar is required for full window theme and Mica support.
// https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization
u.ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(u));
u.SetTitleBar(AppTitleBar);
}
}

Просмотреть файл

@ -14,6 +14,7 @@ using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
using Windows.Data.Json;
using Windows.System;
using WinRT.Interop;
namespace Microsoft.PowerToys.Settings.UI.Views
{
@ -421,6 +422,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
// A custom title bar is required for full window theme and Mica support.
// https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization
u.ExtendsContentIntoTitleBar = true;
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(u));
u.SetTitleBar(AppTitleBar);
var loader = ResourceLoaderInstance.ResourceLoader;
AppTitleBarText.Text = App.IsElevated ? loader.GetString("SettingsWindow_AdminTitle") : loader.GetString("SettingsWindow_Title");

Просмотреть файл

@ -6,9 +6,8 @@ using System;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text.Json;
using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;

Просмотреть файл

@ -4,9 +4,8 @@
using System;
using System.Runtime.CompilerServices;
using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;

Просмотреть файл

@ -10,8 +10,6 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;

Просмотреть файл

@ -9,9 +9,8 @@ using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Timers;
using Common.UI;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;