【WPF】WindowChrome的功能详解

参考:https://blog.csdn.net/WPwalter/article/details/81121829

测试环境:.net6.0+wpf+vs2022

Windows结构

标准窗口由两个重叠的矩形组成。 外部矩形(灰色)是 非工作区WindowChrome,内部矩形(白色)是 工作区(client area )

WindowChrome定义了Window non-client area(即chrome)的外观和行为, 在Window上应用WindowChrome的WindowChrome附加属性即可将Window的non-client area替换为WindowChrome(绕口)

WindowChrome 重新Window non-client area(即chrome)的外观和行为。允许将工作区的扩展至整个窗口。但是在WindowChrome的区域不能交互。如果要交互 就必须设置WindowChrome区域元素的

命中测试。给在WindowChrome区域的元素添加【WindowChrome.IsHitTestVisibleInChrome="True"】附加属性。这样WindowChrome区域的元素就可以交互了。

 

 

标题栏:提供 双击最大化、双击最小化、标题、logo、拖、系统菜单

窗体边框:标题按钮 (最小化、最大化和关闭)、阴影效果、调整窗体大小、边框大小。

工作区:提供 应用程序的内容,并由应用程序绘制和管理

GlassFrame

从Vista到Windows10,都有AERO毛玻璃的特效。
这种效果是由DWM(Desktop Window Manager)来控制的。对于一般的程序,默认将在窗口边框应用这种效果。但如果我们想要更多的控制,比如让客户区的一部分也呈现这种效果,那也非常的简单。不需要我们在程序里做任何复杂的算法,我们只需要调API(在dwmapi.dll中),交给DWM去做就可以了。
C# WPF中可通过设置WindowChrome的WindowChrome.GlassFrameThickness=“任意负数”来实现工作区有AERo特效。
运行后效果。
 

 

 

WindowChrome结构

WindowChrome定义了Window non-client area(即chrome)的外观和行为, 在Window上应用WindowChrome的WindowChrome附加属性即可将Window的non-client area替换为WindowChrome(绕口)

 

 

 【结构解析】

非工作区(no-client-area)=标题栏+窗体边框

标题栏:双击最大化、双击最小化、拖拽、系统菜单.默认情况下,窗口标题区域中的任何视觉元素部分不交互。 若要在标题区域中启用交互式元素,请将 IsHitTestVisibleInChrome 附加属性附加到元素并将其设置为 true

窗体边框:阴影效果、调整窗体大小、边框大小。默认使用GlassFrame(毛玻璃边框)作为窗体边框,如果不想使用GlassFrame,就将设置WindowChrome.GlassFrameThickness=“0”,此举也会将禁用标准标题按钮 (最大化、最小化、关闭) 和交互。

工作区域:呈现窗体布局。

当给窗体控件添加WindowChrome.WindowChrome附加属性时候, 标题处于窗体控件的最顶层,工作区处于中间层,GlassFrame处于最底层。

 依赖属性

  • CaptionHeightCaptionHeight指定WindowChrome的标题栏高度,处于窗体图层的最顶层。它不影响外观,因为WindowChrome的标题栏范围实际是不可见的,它包括可以拖动窗体、双击最大化窗体、右键打开SystemMenu等行为。默认情况下,窗口标题区域中的任何视觉元素部分不交互。 若要在标题区域中启用交互式元素,请将 IsHitTestVisibleInChrome 附加属性附加到元素并将其设置为 true
  • UseAeroCaptionButtonsUseAeroCaptionButtons表示标题栏上的那三个默认按钮是否可以命中,因为我们想要自己管理这三个按钮的样式、显示或隐藏,所以设置为False。
  • CornerRadius:工作区 边角的度数
  • GlassFrameCompleteThickness
  • GlassFrameThickness:控制非工作区域四边的宽度,默认情况下,玻璃框架(GlassFrame)将使用系统值来模拟标准窗口的外观。 如果已启用 Windows Aero,则启用标准标题按钮 (最大化、最小化、关闭) 和交互。 若要使没有玻璃框架的自定义窗口,请将此厚度设置为统一值 0。 这将禁用标准标题按钮。若要扩展玻璃框架以覆盖整个窗口,请将 GlassFrameThickness 属性设置为任意一端的负值。例如:GlassFrameThickness="0 64 0 0"或者GlassFrameThickness="0"、GlassFrameThickness="-1"
  • NonClientFrameEdges:表示窗口框架边缘是否归工作区域所有、“Left, Right, Top, Bottom”不是有效的值。 至少一个边缘必须属于非工作区域。。例如:NonClientFrameEdges="Left,Bottom,Right" 表示只显示顶部 边框 。特别注意:可定制区域中顶部是包含那 1 像素的边距的,但其他三边不包含。
  • ResizeBorderThickness:向窗口内部扩展拖动缩放 区域

附加属性

  • IsHitTestVisibleInChrome:GlassFrameThickness和CaptionHeight定义了Chrome的范围,默认情况下任何在Chrome的范围内的元素都不可以交互,如果需要在标题栏放自己的按钮(或其它交互元素)需要将这个按钮的WindowsChrome.IsHitTestVisibleInChrome附加属性设置为True。

 一、标题栏设置

标题栏(Caption):标题栏处于窗体图层的最顶层。它不影响外观,因为WindowChrome的标题栏范围实际是不可见的,它包括可以拖动窗体、双击最大化窗体、右键打开SystemMenu等行为。默认情况下,窗口标题区域中的任何视觉元素部分不交互。 若要在标题区域中启用交互式元素,请将 IsHitTestVisibleInChrome 附加属性附加到元素并将其设置为 true

 非工作区=标题栏+边框

CaptionHeight属性

CaptionHeightCaptionHeight指定WindowChrome的标题栏高度

Caption标题栏放置在 GlassFrameThickness.top 边框上,当GlassFrameThickness.top=“0” 标题栏就被隐藏了。 下面案例 设置不同的GlassFrameThickness.top宽度和标题栏的高度CaptionHeight,通过拖拽就可以看出不同。

  <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="50" CaptionHeight="30" NonClientFrameEdges="Left,Bottom,Right"    CornerRadius="20" />
    </WindowChrome.WindowChrome>

 

 UseAeroCaptionButtons属性

UseAeroCaptionButtons表示标题栏上的那三个默认按钮是否可以命中,因为我们想要自己管理这三个按钮的样式、显示或隐藏,所以设置为False。

案例:UseAeroCaptionButtons="False",最大,最小,关闭按钮将不会命中。

    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="0,50,0,0" CaptionHeight="30" NonClientFrameEdges="None"     UseAeroCaptionButtons="False" />
    </WindowChrome.WindowChrome>

 

 

 

二 、工作区设置

工作区(client area):处于窗体图层的中间层,显示窗体布局。

CornerRadius 属性

控制工作区 边角弧度。

实例如下:

    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="0" CaptionHeight="30" NonClientFrameEdges="None"    CornerRadius="20" />
    </WindowChrome.WindowChrome>

效果如下:

GlassFrameThickness="0"因此窗体边框被隐藏,剩下全部都是透明的,黑色代表透明。虽然边框隐藏了,但是标题栏和工作区依然存在。

 

三、边框设置(frame)

边框(frame):处于窗体图层的最底层,控制边框、阴影

 非工作区=标题栏+边框

GlassFrameThickness 属性

控制WindowChrome的四边边框 宽度。 0表示不使用系统按钮【后面介绍】,-1表示用的系统默认值。例如:GlassFrameThickness="0 64 0 0"或者GlassFrameThickness="0"、GlassFrameThickness="-1"

//其他样式省略    
<WindowChrome.WindowChrome> <WindowChrome GlassFrameThickness="50" /> </WindowChrome.WindowChrome>

效果如下

黑色代表透明。此时窗体没有任何内容,所有只显示了WindowChrome的外观。

 

GlassFrameThickness 值为 -1 效果如下:

在官方文档 WindowChrome.GlassFrameCompleteThickness Property (System.Windows.Shell) 中有说,如果指定 GlassFrameThickness 值为 -1,那么可以做到整个窗口都遮挡,但实际上全遮挡的效果也是不对劲的,就像下面这样:

 

GlassFrameThickness 为 -1

不止边框颜色不见了,连右上角的三个按钮的位置都跟原生不同,这个窗口的位置不贴边。

显然,GlassFrameThickness 属性我们不能指定为 -1。也不能指定为 0,你可以试试,会发现连阴影都不见了,这更不是我们想要的效果。

GlassFrameThickness 值为0 效果如下

 

那我们指定为其他正数呢?

 

显然,没有一个符合我们的要求。但好在我们还有一个属性可以尝试 —— NonClientFrameEdges。官方文档 WindowChrome.NonClientFrameEdges Property (System.Windows.Shell) 对此的解释是:即指定哪一边不属于客户区。

 

NonClientFrameEdge属性

 即指定哪一边不属于客户区。

 

 

可以NonClientFrameEdges设置取消 边框。如下代码:

<WindowChrome.WindowChrome>
    <WindowChrome NonClientFrameEdges="Left,Bottom,Right" />
</WindowChrome.WindowChrome>

效果如下:

 

 

ResizeBorderThickness属性

向窗口内部扩展拖动缩放 区域

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <WindowChrome.WindowChrome>
        <WindowChrome ResizeBorderThickness="100"></WindowChrome>
    </WindowChrome.WindowChrome>
    <Grid Background="Transparent" MouseDown="UIElement_OnMouseDown">
        <Grid Margin="100" Background="White" />
        <Button Width="100" Height="100" Command="Undo" />
    </Grid>
</Window>

效果如下:

 


 

 WindowChrome.IsHitTestVisibleInChrome 附加属性

WindowChrome 重新Window non-client area(即chrome)的外观和行为。允许将工作区的扩展至整个窗口。但是在WindowChrome的区域不能交互。如果要交互 就必须设置WindowChrome区域元素的

命中测试。给在WindowChrome区域的元素添加【WindowChrome.IsHitTestVisibleInChrome="True"】附加属性。这样WindowChrome区域的元素就可以交互了。

 

 
 

 

 


 

posted @ 2022-11-10 03:13  小林野夫  阅读(8479)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/