[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 模块.通过这个模 ...
随机推荐
- Win8 iis 环境搭建
http://www.cnblogs.com/Joans/archive/2012/07/16/2593828.html 系统:win8 环境:vs2012 一:安装IIS 比较win7的安装来说,多 ...
- java版gRPC实战之五:双向流
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- select后给字段起别名,where和group后不能用,但having后可以
为什么mysql having的条件表达式可以直接使用select后的别名? SQL语句的语法顺序: FROM -> WHERE -> GROUP BY -> HAVING -> ...
- Docker系列(1) - Centos8.X安装Docker
环境准备 需要会Linux的基础 Centos8.x 使用Xshell连接远程服务器 环境查看 #系统内核是4.18以上 [root@localhost ~]# uname -r 4.18.0-305 ...
- 华为云计算IE面试笔记-FusionCompute虚拟机热迁移定义,应用场景,迁移要求,迁移过程
*热迁移传送了什么数据?保存在哪? 虚拟机的内存.虚拟机描述信息(配置和设备信息).虚拟机的状态 虚拟机的配置和设备信息:操作系统(类别.版本号).引导方式(VM通过硬盘.光盘.U盘.网络启动)和引导 ...
- javascript 面向对象 模块
* module 完成函数 createModule,调用之后满足如下要求:1.返回一个对象2.对象的 greeting 属性值等于 str1, name 属性值等于 str23.对象存在一个 say ...
- navicat导出DDL语句
工作中有的时候需要将某个库中的表.视图.函数.存储过程等创建语句导出,又不需要表中的数据. 方法一:需要拷贝的创建语句条数不多,可以选择直接拷贝DDL语句 方法二:使用Navicat的备份功能
- 启动springboot出现错误 Caused by: java.net.BindException: Address already in use: bind
如果运行过程中出现端口被占用 抛出了这个异常 首先可以在cmd中调出命令窗口然后 执行命令 netstat -ano 可以查看所有活动的连接 找到你被占用的端口 可以看到我被占用的端口的进程是 4 ...
- 配置Nginx和php-fpm用Sock套接字连接时,找不到php-fpm.sock的原因
php5.3之后的版本,php-fpm.conf里的listen的默认配置是127.0.0.1:9000,就不会生成php-fpm.sock,因此如果需要Nginx里的配置有链接tmp/php-fpm ...
- 三分钟图解 MVCC,看一遍就懂
前文我们介绍了 InnoDB 存储引擎在事务隔离级别 READ COMMITTED 和 REPEATABLE READ(默认)下会开启一致性非锁定读,简单回顾下:所谓一致性非锁定读就是每行记录可能存在 ...