[WPF] 在 Windows 11 中处理 WindowChrome 的圆角
1. Windows 11 的圆角#
在直角统治了微软的 UI 设计多年以后,微软突然把直角骂了一顿,说还是圆角好看,于是 Windows 11 随处都可看到圆角设计。Windows 11 使用 3 个级别的圆角,具体取决于要应用圆角的 UI 组件及该组件相对于相邻元素的排列方式。
圆角半径 | 使用情况 |
---|---|
8px | 窗体、Flyout 、弹出菜单等 。另外,当窗体最大化或使用对齐布局时不应用圆角。 |
4px | 页面内的元素,如按钮或列表等。 |
0px | 与其它直边相交的直边不使用圆角。 |
也就是说在 Windows 11 上窗体需要应用半径为 8px 的圆角。
2. 处理 WindowChrome 的圆角#
对于 WPF,如果使用原生 Window 的话不需要额外处理圆角,如果使用了 WindowChrome 自定义窗体样式的话呢?
结论是,如果自定义的 Window 使用了 1 像素的窄边框或无边框的样式,那就可能不需要额外处理。
下面这两张图是同一个自定义的 Window 分别在 Windows 11 和 10 上的样子:
可以看到这是个模仿 Windows 10 的 Window 样式,边框只有 1 像素。在 Windows 11 里 WindowChrome 会自动裁剪最外层那 1 像素边框和圆角的其它部分,然后补上一条灰色的边框。这做法简单粗暴但有效。被裁剪过后自定义的 Window 成了一个无边框圆角窗口,看着还挺时髦的。
但这个简单裁剪也可能遇到问题,如果 Window 里的内容正好有个直角的元素,而且这个直角还靠着圆角,就可能被裁剪掉;或者自定义的 Window 使用了无边框的样式,那么这个贴边的边框就会被裁剪掉一像素:
所以 Window 可能不需要额外处理,但内容可能需要,这取决于以前的设计。
还有一种情况,如果这个 Window 的边框大于一个像素(像 Windows 8 那样的粗边框),那就需要修改 Window 样式了:
3. 我就是喜欢直的,不想要圆角,怎么办#
上图是 Aero2 的主题样式,这是 Windows 8 以后 WPF 程序的默认主题,再之后微软就没有更新过 WPF 的主题。即使在 Windows 11 上,WPF 的主题也没有获得更新。所以,假使现有的 WPF 程序使用了默认主题,或者自定义的主题按照微软一向的审美全使用了直角元素,那到了 Windows 11 上就会显得格格不入。
微软还是很贴心的,如果我们不想更改样式,可以使用 DwmSetWindowAttribute 和 DWM_WINDOW_CORNER_PREFERENCE 控制 Window 的圆角。
using System.Runtime.InteropServices;
using System.Windows.Interop;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
IntPtr hWnd = new WindowInteropHelper(GetWindow(this)).EnsureHandle();
var attribute = DWMWINDOWATTRIBUTE.DWMWA_WINDOW_CORNER_PREFERENCE;
var preference = DWM_WINDOW_CORNER_PREFERENCE.DWMWCP_ROUND;
DwmSetWindowAttribute(hWnd, attribute, ref preference, sizeof(uint));
// ...
// Perform any other work necessary
// ...
}
// The enum flag for DwmSetWindowAttribute's second parameter, which tells the function what attribute to set.
public enum DWMWINDOWATTRIBUTE
{
DWMWA_WINDOW_CORNER_PREFERENCE = 33
}
// The DWM_WINDOW_CORNER_PREFERENCE enum for DwmSetWindowAttribute's third parameter, which tells the function
// what value of the enum to set.
public enum DWM_WINDOW_CORNER_PREFERENCE
{
DWMWCP_DEFAULT = 0,
DWMWCP_DONOTROUND = 1,
DWMWCP_ROUND = 2,
DWMWCP_ROUNDSMALL = 3
}
// Import dwmapi.dll and define DwmSetWindowAttribute in C# corresponding to the native function.
[DllImport("dwmapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern long DwmSetWindowAttribute(IntPtr hwnd,
DWMWINDOWATTRIBUTE attribute,
ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute,
uint cbAttribute);
// ...
// Various other definitions
// ...
}
其中 DWM_WINDOW_CORNER_PREFERENCE 枚举值的含义如下:
枚举值 | 说明 |
---|---|
DWMWCP_DEFAULT | 让系统决定是否对窗口采用圆角设置。 |
DWMWCP_DONOTROUND | 绝不对窗口采用圆角设置。 |
DWMWCP_ROUND | 适当时采用圆角设置。 |
DWMWCP_ROUNDSMALL | 适当时可采用半径较小的圆角设置。 |
在 Windows 11 上,使用了上面 4 钟枚举值的窗口效果如下:
4. 最后#
关于使用 WindowChrome 自定义窗体的内容,可以参考这几篇文章:
-
Window(窗体)的UI元素及行为:这篇文章主要讨论标准 Window 的 UI 元素和行为。
-
使用WindowChrome自定义Window Style:介绍使用 WindowChrome 自定义 Window 的原理及各种细节。
-
使用WindowChrome的问题:介绍如何处理使用 WindowChrome 自定义 Window 会遇到的各种问题。
-
WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)
另外,关于圆角我要抱怨一下:
在 Windows 11 中,我们对窗口边框进行了圆角处理。 我们的用户研究团队发现,圆润的几何图形在心理上提供一种安全感,并且使应用的 UI 更易于扫描。 这使用户更少感觉威慑,也使应用更具吸引力。 圆角处理的量也是精心选择的。 我们公司对此进行了研究,努力在专业性、柔和感和吸引度之间取得平衡。
微软的文档这样声称,我是一个字都不信的,难道这么多年来区区 Windows 的直角就让我感觉到威慑和没有安全感了?微软还有比 UWP 更能让我没有安全感的东西?我倒想看看几年后又流行直角时微软要怎么解释。
5. 参考#
在 Windows 11 上,为增强应用功能而可以执行的最常见的 11 种操作
6. 源码#
我做了个小 Demo 用户看看这篇文章提到的不同边框和 DWM_WINDOW_CORNER_PREFERENCE 设定下的效果,源码可以从这里获取:
作者:Dino.C
出处:https://www.cnblogs.com/dino623/p/apply-rounded-corners-to-windowchrome.html
版权:本文采用「CC BY 4.0」知识共享许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?