C# WPF通过WindowChrome自定义窗体

概述

在WPF界面开发中,系统默认的窗口比较丑,有时候想自定义窗体,比如微信的客户端窗口这样:使得左边的一块顶到最上端,如下图所示:.

C# WPF通过WindowChrome自定义窗体

这时候我们可以 WindowStyle="None",AllowsTransparency="True"去掉默认的窗体边框,然后添加最小最大和关闭的按钮,然后重写相关的功能实现

<TextBlock x:Name="lblTitle" Text="自定义窗体" Foreground="White" FontSize="14" Margin="10 0 0 0" VerticalAlignment="Center"/>            <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">                <Button WindowChrome.IsHitTestVisibleInChrome="True" Name="button_MiniSize" Content="─" Style="{StaticResource btn_nap}" HorizontalAlignment="Right" Foreground="White" Margin="0 0 5 0" Height="30" Width="30"/>                <Button WindowChrome.IsHitTestVisibleInChrome="True" Name="button_MaxSize" Content="☐" Style="{StaticResource btn_nap}" HorizontalAlignment="Right" Foreground="White" Margin="0 0 5 0" Height="30" Width="30"/>                <Button WindowChrome.IsHitTestVisibleInChrome="True" x:Name="btn_Close" Content="✕" Style="{StaticResource btn_nap}" HorizontalAlignment="Right" Foreground="White" Margin="0 0 5 0" Height="30" Width="30"/>            </StackPanel>

但是这样做的话,这就不贴近原生窗口体验了,

-. 需要写大量代码实现Window本来的拖动、改变大小、最大化最小化等行为;

-. 各种其它细节的修改,比如:最大化会覆盖任务栏等;

为了保持最大的原生的同时以少量代码实现自定义窗体,我们使用WindowChrome去实现会更加便捷和优雅.

WindowChrome用法举例

<Window x:Class="WpfApp13.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"        xmlns:local="clr-namespace:WpfApp13"        mc:Ignorable="d"        Title="MainWindow" Height="450" Width="800" Background="{x:Null}"         FontWeight="ExtraLight" ResizeMode="CanResize" WindowStartupLocation="CenterScreen">   <Window.Style>        <Style TargetType="Window">            <Setter Property="WindowChrome.WindowChrome">                <Setter.Value>                    <WindowChrome                     CornerRadius="0"                        CaptionHeight="30"                  GlassFrameThickness="-1"                  UseAeroCaptionButtons="True"                  NonClientFrameEdges="None"/>                </Setter.Value>            </Setter></Style>    </Window.Style>
    <Grid>        <Grid.ColumnDefinitions>            <ColumnDefinition Width="Auto"/>            <ColumnDefinition Width="*"/>        </Grid.ColumnDefinitions>        <Image Source="left1.png"   Stretch="Fill"/>        <Grid  Grid.Column="1" >            <Grid.RowDefinitions>                <RowDefinition Height="40"/>                <RowDefinition Height="32"/>                <RowDefinition Height="*"/>            </Grid.RowDefinitions>            <Grid  Grid.Row="0" >                <Menu Margin="2,8,200,0"  VerticalAlignment="Center" WindowChrome.IsHitTestVisibleInChrome="True" Background="Transparent">                    <MenuItem Header="C#技术交流⑥群(111)" FontSize="15" />                </Menu>            </Grid>            <Grid Grid.Row="2">                <TextBlock            HorizontalAlignment="Center"            VerticalAlignment="Center"            FontSize="50"            FontWeight="Bold"            Foreground="blue"            Text="呆萌气质小可爱" />            </Grid>        </Grid>    </Grid></Window>

运行结果:

C# WPF通过WindowChrome自定义窗体

WindowChrome用法说明

UseAeroCaptionButtons:表示标题栏上的那三个默认按钮是否可以命中,这里设置为true,如果要自己管理则设置为false。

GlassFrameThickness和ResizeBorderThickness:这两个属性用于控制边框,及用户可以单击并拖动以调整窗口大小的区域的宽度;其中GlassFrameThickness用来设置距离区域的厚度,设置为-1,可以使得区域覆盖整个界面;ResizeBorderThickness可以设置窗口缩放的边框厚度,不宜设置过大。

CaptionHeight:指定WindowChrome的标题栏高度;我这里设置的是30。设置为0表示界面无法响应鼠标的任何操作(拖动窗口, 双击标题栏的最大化最小化。。。仅仅是行为区域,并不影响外观)。

NonClientFrameEdges:即指定哪一边不属于客户区。用法举例:

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

要使用WindowChrome,最简洁语法如下:

 <WindowChrome.WindowChrome>        <WindowChrome />    </WindowChrome.WindowChrome>

然后得到的窗体拥有默认窗口的所有窗口行为,

此外需要注意的是,如果元素在CaptionHeight的高度内,是无法响应鼠标事件的,此时需要给元素设置属性WindowChrome.IsHitTestVisibleInChrome="True",很常见的问题,在自定义标题按钮的时候,会发现自己点击不了标题按钮!

源码下载

链接:https://pan.baidu.com/s/1ilUXW3JzrCLQX2xFINmByw

提取码:6666