[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 的圆角。

Copy
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 自定义窗体的内容,可以参考这几篇文章:

另外,关于圆角我要抱怨一下:

在 Windows 11 中,我们对窗口边框进行了圆角处理。 我们的用户研究团队发现,圆润的几何图形在心理上提供一种安全感,并且使应用的 UI 更易于扫描。 这使用户更少感觉威慑,也使应用更具吸引力。 圆角处理的量也是精心选择的。 我们公司对此进行了研究,努力在专业性、柔和感和吸引度之间取得平衡。

微软的文档这样声称,我是一个字都不信的,难道这么多年来区区 Windows 的直角就让我感觉到威慑和没有安全感了?微软还有比 UWP 更能让我没有安全感的东西?我倒想看看几年后又流行直角时微软要怎么解释。

5. 参考#

在 Windows 11 的桌面应用中应用圆角

在 Windows 11 上,为增强应用功能而可以执行的最常见的 11 种操作

Windows 11 中的几何图形

6. 源码#

我做了个小 Demo 用户看看这篇文章提到的不同边框和 DWM_WINDOW_CORNER_PREFERENCE 设定下的效果,源码可以从这里获取:

posted @   dino.c  阅读(2536)  评论(9编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示
CONTENTS