[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 设定下的效果,源码可以从这里获取:

[WPF] 在 Windows 11 中处理 WindowChrome 的圆角的更多相关文章
- 如何在windows 11中安装WSLG(WSL2)
什么是 WSL WSL(Windows Subsystem for Linux):Windows 系统中的一个子系统,在这个子系统上可以运行 Linux 操作系统. 可以让开发人员直接在 Window ...
- 乘风破浪,遇见下一代操作系统Windows 11,迄今为止最美版本,原生支持安卓应用
遇见下一代操作系统Windows 11 全新Windows体验,让您与热爱的人和事物离得更近. Windows一直是世界创新的舞台.它是全球企业的基石,助力众多蓬勃发展的初创公司变得家喻户晓.网络在W ...
- 在Windows 8.1及IE 11中如何使用HttpWatch
提示:HttpWatch现已更新至v9.1.8,HttpWatch v9.1及以上的版本现都已支持Windows 7,8,8.1和IE 11. 如果你的HttpWatch专业版授权秘钥允许进入vers ...
- WPF中使用WindowChrome美化窗口过程中的一个小问题
WPF中使用WindowChrome美化窗口,在园子里有几篇不错的文章,我也是参考练习过程中发现的问题,并记录下来. 在看过几篇教程后,给出的窗口很多出现这样一个问题,如果设置了窗口标题栏的高度大于默 ...
- WPF老矣,尚能饭否——且说说WPF今生未来(中):策略
本文接上文<WPF老矣,尚能饭否——且说说WPF今生未来(上):担心>继续. “上篇”中部分精彩的点评: 虽然WPF不再更新了,但是基于WPF的技术还是在发展着,就比如现在的WinRT,只 ...
- UEFI+GPT模式下的Windows系统中分区结构和默认分区大小及硬盘整数分区研究
内容摘要:本文主要讨论和分析在UEFI+GPT模式下的Windows系统(主要是最新的Win10X64)中默认的分区结构和默认的分区大小,硬盘整数分区.4K对齐.起始扇区.恢复分区.ESP分区.MSR ...
- WPF、Windows Forms和Silverlight间的联系和区别(转)
WPF.Windows Forms和Silverlight间的联系和区别http://blog.csdn.net/bitfan/article/details/6128391 .NET Windows ...
- mysql绿色版在windows系统中的启动
mysql绿色版在windows系统中的启动 1.下载mysql免安装版 例如:mysql-5.7.11-winx64 2.修改配置文件,my-default.ini名称改为:my.ini,文件里面的 ...
- 使用 Puppet 在 Windows Azure 中配备 Linux 和 Windows 环境
发布于 2013-12-11 作者 Ross Gardler 微软开放技术有限公司 (MS Open Tech) 很高兴地宣布发行新的 Windows Azure Puppet 模块.通过这个模 ...
随机推荐
- Python程序调用摄像头实现人脸识别
使用简单代码实现摄像头进行在线人脸识别 import cv2 import sys import logging as log import datetime as dt from time impo ...
- Pycharm 使用问题一览
1. I'm not sure if it is the problem of Pycharm or any other IDE. 需要从本地文件中导入文件,但总是出现波浪线,按ctril点进去发现是 ...
- php设计模式--生成器模式
生成器模式 require "D:\\xxx\bild.php"; require "D:\\xxx\cx_bild.php"; require "D ...
- python 正则表达式findall
re.findall("匹配规则", "要匹配的字符串") 以列表形式返回匹配到的字符串 https://www.cnblogs.com/gufengchen/ ...
- Appium和Selenium的区别和联系
https://www.cnblogs.com/lv-lxz/p/11118862.html https://blog.csdn.net/weixin_42139375/article/details ...
- web自动化:IE11运行Python+selenium程序
from selenium import webdriver # 运行此脚本前必须按要求修改注册表'''[HKEY_CURRENT_USER\Software\Microsoft\Internet E ...
- [转载]php连接postgreSQL数据库及其操作(php5,postgreSQL9)
数据库连接:dbconn.php<?php$conn = pg_connect("host=localhost port=5432 dbname=myd user=postgres p ...
- P4717-[模板]快速莫比乌斯/沃尔什变换(FMT/FWT)
正题 题目链接:https://www.luogu.com.cn/problem/P4717 题目大意 给出两个长度为\(2^n\)的数列\(A,B\)求 \[C_{n}=\sum_{i\ or\ j ...
- P4929-[模板]舞蹈链(DLX)
正题 题目链接:https://www.luogu.com.cn/problem/P4929 题目大意 \(n*m\)的矩形有\(0/1\),要求选出若干行使得每一列有且仅有一个\(1\). 解题思路 ...
- serialVersionUID序列化版本号与ObjectOutputStream对象输入输出流
1. 观察ObjectOutputStream 我们观察ObjectOutputStream就可以发现该类没有无参构造,只有有参构造,所以他是一个包装流 2. 具体使用: public static ...