Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)

WPF 制作高性能的透明背景异形窗口(使用 WindowChrome 而不要使用 AllowsTransparency=True)

作者头像
walterlv
发布于 2023-10-22 03:37:14
发布于 2023-10-22 03:37:14
1.9K0
举报

在 WPF 中,如果想做一个背景透明的异形窗口,基本上都要设置 WindowStyle="None"AllowsTransparency="True" 这两个属性。如果不想自定义窗口样式,还需要设置 Background="Transparent"。这样的设置会让窗口变成 Layered Window,WPF 在这种类型窗口上的渲染性能是非常糟糕的。

本文介绍如何使用 WindowChrome 而不设置 AllowsTransparency="True" 制作背景透明的异形窗口,这可以避免异形窗口导致的低渲染性能。

背景透明的异形窗口

如下是一个背景透明异形窗口的示例:

此窗口包含很大的圆角,还包含 DropShadowEffect 制作的阴影效果。对于非透明窗口来说,这是不可能实现的。

如何实现

要实现这种背景透明的异形窗口,需要为窗口设置以下三个属性:

  • WindowStyle="None"
  • ResizeMode="CanMinimize"ResizeMode="NoResize"
  • WindowChrome.GlassFrameThickness="-1" 或设置为其他较大的正数(可自行尝试设置之后的效果)

如下就是一个最简单的例子,最关键的三个属性我已经高亮标记出来了。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

<Window x:Class="Walterlv.Demo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ++ WindowStyle="None" ResizeMode="CanMinimize" Title="walterlv demo" Height="450" Width="800"> ++ <WindowChrome.WindowChrome> ++ <WindowChrome GlassFrameThickness="-1" /> ++ </WindowChrome.WindowChrome> <Window.Template> <ControlTemplate TargetType="Window"> <Border Padding="64" Background="Transparent"> <Border CornerRadius="16" Background="White"> <Border.Effect> <DropShadowEffect BlurRadius="64" /> </Border.Effect> <ContentPresenter ClipToBounds="True" /> </Border> </Border> </ControlTemplate> </Window.Template> <Grid> <TextBlock FontSize="20" Foreground="#0083d0" TextAlignment="Center" VerticalAlignment="Center"> <Run Text="欢迎访问吕毅的博客" /> <LineBreak /> <Run Text="blog.walterlv.com" FontSize="64" FontWeight="Light" /> </TextBlock> </Grid> </Window>

网上流传的主流方法

在网上流传的主流方法中,AllowsTransparency="True" 都是一个必不可少的步骤,另外也需要 WindowStyle="None"。但是我一般都会极力反对大家这么做,因为 AllowsTransparency="True" 会造成很严重的性能问题。

如果你有留意到我的其他博客,你会发现我定制窗口样式的时候都在极力避开设置此性能极差的属性:

性能对比

既然特别说到性能,那也是口说无凭,我们要拿出数据来说话。

以下是我用来测试渲染性能所使用的例子:

相比于上面的例子来说,主要就是加了背景动画效果,这可以用来测试帧率。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

<Window x:Class="Walterlv.Demo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowStyle="None" ResizeMode="CanMinimize" Title="walterlv demo" Height="450" Width="800"> <WindowChrome.WindowChrome> <WindowChrome GlassFrameThickness="-1" /> </WindowChrome.WindowChrome> <Window.Template> <ControlTemplate TargetType="Window"> <Border Padding="64" Background="Transparent"> <Border CornerRadius="16" Background="White"> <Border.Effect> <DropShadowEffect BlurRadius="64" /> </Border.Effect> <ContentPresenter ClipToBounds="True" /> </Border> </Border> </ControlTemplate> </Window.Template> <Grid> ++ <Rectangle x:Name="BackgroundRectangle" Margin="0 16" Fill="#d0d1d6"> ++ <Rectangle.RenderTransform> ++ <TranslateTransform /> ++ </Rectangle.RenderTransform> ++ <Rectangle.Triggers> ++ <EventTrigger RoutedEvent="FrameworkElement.Loaded"> ++ <BeginStoryboard> ++ <BeginStoryboard.Storyboard> ++ <Storyboard RepeatBehavior="Forever"> ++ <DoubleAnimation Storyboard.TargetName="BackgroundRectangle" ++ Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" ++ From="800" To="-800" /> ++ </Storyboard> ++ </BeginStoryboard.Storyboard> ++ </BeginStoryboard> ++ </EventTrigger> ++ </Rectangle.Triggers> ++ </Rectangle> <TextBlock FontSize="20" Foreground="#0083d0" TextAlignment="Center" VerticalAlignment="Center"> <Run Text="欢迎访问吕毅的博客" /> <LineBreak /> <Run Text="blog.walterlv.com" FontSize="64" FontWeight="Light" /> </TextBlock> </Grid> </Window>

那么性能数据表现如何呢?我们让这个窗口在 2560×1080 的屏幕上全屏渲染,得出以下数据:

方案

WindowChrome

AllowsTransparency

帧率(fps)数值越大越好,60 为最好

59

19

脏区刷新率(rects/s)数值越大越好

117

38

显存占用(MB)数值越小越好

83.31

193.29

帧间目标渲染数(个)数值越大越好

2

1

另外,对于显存的使用,如果我在 7680×2160 的屏幕上全屏渲染,WindowChrome 方案依然保持在 80+MB,而 AllowsTransparency 已经达到惊人的 800+MB 了。

可见,对于渲染性能,使用 WindowChrome 制作的背景透明异形窗口性能完虐使用 AllowsTransparency 制作的背景透明异形窗口,实际上跟完全没有设置透明窗口的性能保持一致。

此性能差异的原理解读,请参阅:

功能对比

既然 WindowChrome 方法在性能上完虐网上流传的设置 AllowsTransparency 方法,那么功能呢?

值得注意的是,由于在使用 WindowChrome 制作透明窗口的时候设置了 ResizeMode="None",所以你拖动窗口在屏幕顶部和左右两边的时候,Windows 不会再帮助你最大化窗口或者靠边停靠窗口,于是你需要自行处理。不过窗口的标题栏拖动功能依然保留了下来,标题栏上的右键菜单也是可以继续使用的。

方案

WindowChrome

AllowsTransparency

拖拽标题栏移动窗口

保留

自行实现

最小化最大化关闭按钮

丢失

丢失

拖拽边缘调整窗口大小

丢失

丢失

移动窗口到顶部可最大化

丢失

自行实现

拖拽最大化窗口标题栏还原窗口

保留

自行实现

移动窗口到屏幕两边可侧边停靠

丢失

自行实现

拖拽摇动窗口以最小化其他窗口

保留

自行实现

窗口打开/关闭/最小化/最大化/还原动画

丢失

丢失

表格中:

  • 保留 表示此功能无需任何处理即可继续支持
  • 自行实现 表示此功能已消失,但仅需要一两行代码即可补回功能
  • 丢失 表示此功能已消失,如需实现需要编写大量代码

另外,以上表格仅针对鼠标操作窗口。如果算上使用触摸来操作窗口,那么所有标记为 自行实现 的都将变为 丢失。因为虽然你可以一句话补回功能,但在触摸操作下各种 Bug,你解不完……

这两种实现的窗口之间还有一些功能上的区别:

方案

WindowChrome

AllowsTransparency

点击穿透

在完全透明的部分点击依然点在自己的窗口上

在完全透明的部分点击会穿透到下面的其他窗口

然而,如果你希望在使用高性能的 WindowChrome 时也依然能点击穿透,那么你需要使用到一点点的小技巧来绕过 WPF 对 WS_EX_LAYERED 窗口样式的锁定。请参见:WPF 制作支持点击穿透的高性能的透明背景异形窗口

本文会经常更新,请阅读原文: https://blog.walterlv.com/post/wpf-transparent-window-without-allows-transparency.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email protected])

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
WPF自定义一个MessageBox
WPF的MessageBox太丑了,自己定义了一个。 这是效果: image.png XAML: <Window x:Class="AgileToDo.UMessageBox"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         Title="UMessageBox" He
MJ.Zhou
2022/05/07
9100
WPF自定义一个MessageBox
WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
发布于 2018-07-12 07:57 更新于 2018-09-05 05:46
walterlv
2018/09/18
6.8K0
WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
WPF 制作 Windows 屏保
[1]GitHub: https://github.com/yanjinhuagood/ScreenSaver
独立观察员
2022/12/06
9760
WPF 制作 Windows 屏保
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景(可以做 Acrylic 亚克力效果、模糊效果、主题色效果等)
Windows 系统中有一个没什么文档的 API,SetWindowCompositionAttribute,可以允许应用的开发者将自己窗口中的内容渲染与窗口进行组合。这可以实现很多系统中预设的窗口特效,比如 Windows 7 的毛玻璃特效,Windows 8/10 的前景色特效,Windows 10 的模糊特效,以及 Windows 10 1709 的亚克力(Acrylic)特效。而且这些组合都发生在 dwm 进程中,不会额外占用应用程序的渲染性能。
walterlv
2023/10/22
1.8K0
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景(可以做 Acrylic 亚克力效果、模糊效果、主题色效果等)
[WPF]使用WindowChrome自定义Window Style
做了WPF开发多年,一直未曾自己实现一个自定义Window Style,无论是《WPF编程宝典》或是各种博客都建议使用WindowStyle="None" 和 AllowsTransparency="True",于是想当然以为这样就可以了。最近来了兴致想自己实现一个,才知道WindowStyle="None" 的方式根本不好用,原因有几点:
dino.c
2019/01/18
2.3K0
[WPF]使用WindowChrome自定义Window Style
使用 WPF 做一个可以逼真地照亮你桌面的高性能阳光
本文想要做的,可不是随便弄一点阳光的半透明形状,然后简单地放到桌面上,而是真真正正地要照亮桌面上的窗口元素!并且,全程使用 GPU 加速,而且代码超简单。
walterlv
2023/10/23
5710
使用 WPF 做一个可以逼真地照亮你桌面的高性能阳光
【愚公系列】2022年10月 基于WPF的智能制造MES系统框架-菜单栏的设计
MES系统为企业提供包括制造数据管理、计划排程管理、生产调度管理、库存管理、质量管理、人力资源管理、工作中心/设备管理、工具工装管理、采购管理、成本管理、项目看板管理、生产过程控制、底层数据集成分析、上层数据集成分解等管理模块,为企业打造一个扎实、可靠、全面、可行的制造协同管理平台。
愚公搬代码
2022/10/28
5750
修复 WPF 窗口在启动期间短暂的白底显示
2017-11-03 15:08
walterlv
2018/09/18
2.7K0
修复 WPF 窗口在启动期间短暂的白底显示
.NET CORE(C#) WPF亚克力窗体
使用 .Net Core 3.1 创建名为 “AcrylicWindow” 的WPF模板项目,添加三个Nuget库:MaterialDesignThemes、MaterialDesignColors和FluentWPF,其中亚克力效果是由FluentWPF控件库实现的。
沙漠尽头的狼
2020/01/16
2.3K0
WPF 应用完全模拟 UWP 的标题栏按钮
发布于 2018-08-04 09:35 更新于 2018-08-05 02:21
walterlv
2018/09/18
2.3K0
WPF 应用完全模拟 UWP 的标题栏按钮
Windows 10 应用创建模糊背景窗口的三种方法
发布于 2018-07-16 11:44 更新于 2018-08-31 23:59
walterlv
2018/09/18
3K0
Windows 10 应用创建模糊背景窗口的三种方法
【NEW】WPF MVVM 模式下自写自用的窗口样式
SVG是一种图形文件格式,它的英文全称为Scalable Vector Graphics,意思为可缩放的矢量图形。它是基于XML(Extensible Markup Language),由World Wide Web Consortium(W3C)联盟进行开发的。严格来说应该是一种开放标准的矢量图形语言,可让你设计激动人心的、高分辨率的Web图形页面。用户可以直接用代码来描绘图像,可以用任何文字处理工具打开SVG图像,通过改变部分代码来使图像具有交互功能,并可以随时插入到HTML中通过浏览器来观看。
Shunnet
2022/09/01
2.4K0
【NEW】WPF MVVM 模式下自写自用的窗口样式
WPF TreeGrid MVVM 模式下自定义表格带展开缩放效果,并且可以获取点击行的数据
MVVM其实就是:Model 、View、ViewModel三个的简称,就像MVC一样。 Model就是模型。View就是视图。ViewModel就是和view进行绑定的。
Shunnet
2022/05/31
6.1K0
WPF TreeGrid MVVM 模式下自定义表格带展开缩放效果,并且可以获取点击行的数据
在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)
发布于 2017-10-01 16:14 更新于 2018-02-19 22:31
walterlv
2018/09/18
5.5K1
在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)
WPF MVVM 模式下自写自用的窗口样式
废话我也就不多说,直接上菜(由于公司电脑做了加密,无法把代码压缩发布,只能以这种方式来分享)
Shunnet
2022/09/01
1.7K0
WPF MVVM 模式下自写自用的窗口样式
WPF中触发器Trigger、MultiTrigger、DataTrigger、MultiDataTrigger
WPF中有种叫做触发器的东西(记住不是数据库的trigger哦)。它的主要作用是根据trigger的不同条件来自动更改外观属性,或者执行动画等操作。
zls365
2021/01/28
3.5K0
The VisualBrush of WPF only refresh the visual but not the layout
Now we’ll talk about a behavior of WPF VisualBrush. Maybe it is a bug, but let’s view some details and determine whether it is or not.
walterlv
2023/10/22
1990
The VisualBrush of WPF only refresh the visual but not the layout
WPF怎么做新手引导界面?
这两天不忙,所以,做了一个简易的新手引导小Demo。因为,不是项目上应用,所以,做的很粗糙,也就是给需要的人,一个思路而已。
沙漠尽头的狼
2022/06/13
1.4K0
WPF怎么做新手引导界面?
WPF窗体透明控件不透明实例
最近在做一个大屏展示视频图片的项目,功能并不复杂,半天的工作量吧,一开始同事采用的Unity3D进行开发,但是里面要播放4K视频,Unity 的短板就是视频的播放了,今晚就要交付了,我一早就来公司,决定用WPF重新开发一版,各项功能都好了,唯独顶部总是显示一条白色的边,已经设置WindowStyle为None了也没用,幸得网上大神提供的资料,终于解决了这个小问题。
zls365
2020/12/15
2.3K0
2020-5-22-如何使WPF在窗口外部区域可拖动缩放
有同学马上想到了,通过WindowChrome的ResizeBorderThickness属性进行设置
黄腾霄
2020/06/10
2K0
推荐阅读
相关推荐
WPF自定义一个MessageBox
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档