【WPF】WindowChrome 自定义窗口完美实现

这篇具有很好参考价值的文章主要介绍了【WPF】WindowChrome 自定义窗口完美实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

Microsoft官网关于 WindowChome 的介绍

截取Microsoft文章的一段话:
  若要在保留其标准功能时自定义窗口,可以使用该 WindowChrome 类。 该 WindowChrome 类将窗口框架的功能与视觉对象分开,并允许你控制应用程序窗口的客户端和非客户端区域之间的边界。 通过 WindowChrome 该类,可以通过扩展工作区来覆盖非工作区,将 WPF 内容置于窗口框架中。 同时,它通过两个不可见区域保留系统行为: 调整边框 和 标题 区域的大小

效果图

【WPF】WindowChrome 自定义窗口完美实现
【WPF】WindowChrome 自定义窗口完美实现

自定义最小化、最大化、关闭按钮

  • 最小化按钮
<Style
    x:Key="SystemCloseButtonStyle"
    BasedOn="{StaticResource SystemButtonStyleBase}"
    TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Background="{TemplateBinding Background}">
                    <Viewbox Width="12" Height="12">
                        <Path Data="M550.848 502.496l308.64-308.896a31.968 31.968 0 1 0-45.248-45.248l-308.608 308.896-308.64-308.928a31.968 31.968 0 1 0-45.248 45.248l308.64 308.896-308.64 308.896a31.968 31.968 0 1 0 45.248 45.248l308.64-308.896 308.608 308.896a31.968 31.968 0 1 0 45.248-45.248l-308.64-308.864z" Fill="{TemplateBinding BorderBrush}" />
                    </Viewbox>
                    <ContentPresenter
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Content="{TemplateBinding Content}" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource CloseColor}" />
                        <Setter Property="BorderBrush" Value="{StaticResource DominantColor}" />
                    </Trigger>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
  • 最大化按钮
<Style
    x:Key="SystemMaxButtonStyle"
    BasedOn="{StaticResource SystemButtonStyleBase}"
    TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Background="{TemplateBinding Background}">
                    <Viewbox Width="12" Height="12">
                        <Path Data="M959.72 0H294.216a63.96 63.96 0 0 0-63.96 63.96v127.92H64.28A63.96 63.96 0 0 0 0.32 255.84V959.4a63.96 63.96 0 0 0 63.96 63.96h703.56a63.96 63.96 0 0 0 63.96-63.96V792.465h127.92a63.96 63.96 0 0 0 63.96-63.96V63.96A63.96 63.96 0 0 0 959.72 0zM767.84 728.505V959.4H64.28V255.84h703.56z m189.322 0H831.8V255.84a63.96 63.96 0 0 0-63.96-63.96H294.216V63.96H959.72z" Fill="{TemplateBinding BorderBrush}" />
                    </Viewbox>
                    <ContentPresenter
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Content="{TemplateBinding Content}" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource SuspensionColor}" />
                    </Trigger>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
  • 关闭按钮
<Style
    x:Key="SystemMinButtonStyle"
    BasedOn="{StaticResource SystemButtonStyleBase}"
    TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Background="{TemplateBinding Background}">
                    <Viewbox Width="12" Height="10">
                        <Path Data="M928.2 548h-832c-17.7 0-32-14.3-32-32s14.3-32 32-32h832c17.7 0 32 14.3 32 32s-14.3 32-32 32z" Fill="{TemplateBinding BorderBrush}" />
                    </Viewbox>
                    <ContentPresenter
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Content="{TemplateBinding Content}" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource SuspensionColor}" />
                    </Trigger>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter Property="FocusVisualStyle" Value="{x:Null}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
/// <summary>
/// 窗口移动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Move_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) => this.DragMove();

/// <summary>
/// 最小化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnMin_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized;

/// <summary>
/// 最大化/还原
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnMax_Click(object sender, RoutedEventArgs e) => WindowState = WindowState is WindowState.Normal ? WindowState.Maximized : WindowState.Normal;

/// <summary>
/// 关闭
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnClose_Click(object sender, RoutedEventArgs e) => Application.Current.Shutdown();

布局实现

首先我们需要在 MainWindow 也就是我们的主窗口中的 Window.Resources 中实现 WindowChrome 的基本样式:
WindowChrome.ResizeBorderThickness 设置不可见边框宽度
WindowChrome.CaptionHeight> 设置属于标题栏的范围——高度
WindowChrome.UseAeroCaptionButtons 是否启用默认系统按钮功能——三大金刚键
WindowChrome.NonClientFrameEdges 设置客户区域,使用 bottom 可以实现加载时空白窗口而不显示默认窗口,提升用户体验

<Window
    x:Class="SignalRClient.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:local="clr-namespace:SignalRClient"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title=""
    Width="880"
    Height="620"
    MinWidth="700"
    MinHeight="500"
    Style="{StaticResource mainWindow}"
    WindowChrome.WindowChrome="{DynamicResource WindowChromeKey}"
    WindowStartupLocation="CenterScreen"
    mc:Ignorable="d">

    <Window.Resources>
        <WindowChrome x:Key="WindowChromeKey">
            <WindowChrome.ResizeBorderThickness>
                <Thickness>5</Thickness>
            </WindowChrome.ResizeBorderThickness>
            <WindowChrome.CaptionHeight>60</WindowChrome.CaptionHeight>
            <WindowChrome.UseAeroCaptionButtons>false</WindowChrome.UseAeroCaptionButtons>
            <WindowChrome.NonClientFrameEdges>bottom</WindowChrome.NonClientFrameEdges>
        </WindowChrome>
    </Window.Resources>
</Window>

重写窗口,实现最大化窗口下,标题栏及客户区域偏移问题的修正。
通过代码获取当前窗口的工作区域,及任务栏以外的其他区域
System.Windows.SystemParameters.WorkArea.Width 获取工作区域的宽
System.Windows.SystemParameters.WorkArea.Height 获取工作区域的高
为什么要使用 ValueConverter 主要是因为 WorkArea 返回的类型无法直接 binding xaml

<ValueConverters:WorkAreaWidth x:Key="workAreaWidth" />
<ValueConverters:WorkAreaHeight x:Key="workAreaHeight" />

<Style x:Key="mainWindow" TargetType="{x:Type Window}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Window">

                <ContentControl x:Name="window" Content="{TemplateBinding Content}" />

                <ControlTemplate.Triggers>
                    <Trigger Property="WindowState" Value="Maximized">
                        <Setter TargetName="window" Property="MaxHeight" Value="{Binding Converter={StaticResource workAreaHeight}}" />
                        <Setter TargetName="window" Property="MaxWidth" Value="{Binding Converter={StaticResource workAreaWidth}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
using System;
using System.Globalization;
using System.Windows.Data;

namespace SignalRClient.ValueConverters
{
    internal class WorkAreaWidth : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return System.Windows.SystemParameters.WorkArea.Width;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
using System;
using System.Globalization;
using System.Windows.Data;

namespace SignalRClient.ValueConverters
{
    internal class WorkAreaHeight : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return System.Windows.SystemParameters.WorkArea.Height;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

结语

一开始,确实很难搞,Microsoft 的文档,里面也并没有,详细介绍窗口内容溢出的问题,但是只要仔细研究过 WPF 的同学都知道,很多东西是可以通过 Trigger 来实现的。Get 到这一点很多问题就迎刃而解了。欢迎大家留言通过探讨 😃😃😃文章来源地址https://www.toymoban.com/news/detail-457965.html

到了这里,关于【WPF】WindowChrome 自定义窗口完美实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于WPF Opencv实现一个图像可移动、缩放和可交互的显示窗口

    学习Halcon的HSmartWindowControl窗口控件,用WPF和Opencv仿照了一个。 显示控件的主体是两个Canvas: Root Canvas是背景,刷上了网格; 把要显示的图像作为Image Canvas的图像背景, 后面图像的移动,缩放,实质都是Image Canvas。 可交互,学习的是Halcon的绘图对象,WPF的Path来实现的,Path类

    2023年04月09日
    浏览(41)
  • wpf 在MVVM中使用IOC思想通过注册窗体的方法实现在ViewModel里面打开其他窗口的方法

    理论:在MVVM中,View通过添加ViewModel的引用来指定DataContext,也就是View可以引用ViewModel,但ViewModel不可以引用View,而ViewModel在实现逻辑过程中如果需要访问其他的窗体该怎么办呢,比如打开一个对话框,这里通过IOC思想来解决该问题。 1 新建wpf应用 2 新建Views,Models,ViewModel

    2024年02月12日
    浏览(39)
  • 使用WPF开发自定义用户控件,以及实现相关自定义事件的处理

    在前面随笔《使用Winform开发自定义用户控件,以及实现相关自定义事件的处理》中介绍了Winform用户自定义控件的处理,对于Winform自定义的用户控件来说,它的呈现方式主要就是基于GDI+进行渲染的,对于数量不多的控件呈现,一般不会觉察性能有太多的问题,随着控件的数量

    2024年02月02日
    浏览(52)
  • WPF --- 非Button自定义控件实现点击功能

    今天在做一个设置文件夹路径的功能,就是一个文本框,加个按钮,点击按钮,弹出 FolderBrowserDialog 再选择文件夹路径,简单做法,可以直接 StackPanel 横向放置一个 TextBox 和一个 Image Button ,然后点击按钮在 后台代码中给 ViewModel 的 FilePath 赋值。但是这样属实不够优雅,UI 不

    2024年02月12日
    浏览(38)
  • vue前端实现图片下载,实现点击按钮弹出本地窗口,选择自定义保存路径

    直接上代码,废话不多说,点关注,不迷路 一、下载代码 二、别找代码了,不用代码就可以实现 以下按照步骤一步一步来 按照红色箭头所指,用鼠标戳它 恭喜你,功能完成了

    2024年02月13日
    浏览(56)
  • 【WPF.NET开发】WPF中的窗口

    目录 1、窗口类 2、实现窗口 2.1 为 MSBuild 配置窗口 3、窗口生存期 3.1 打开窗口 3.2 窗口激活 3.3 关闭窗口 3.4 窗口生存期事件 4、窗口位置 4.1 最顶层窗口和 z 顺序 5、窗口大小 6、大小调整属性的优先级顺序 7、窗口状态 8、窗口外观 8.1 重设大小模式 8.2 Window style 8.3 任务栏显示

    2024年02月04日
    浏览(42)
  • Qt自定义窗口部件/控件(实现一个十六进制微调框SpinBox)

    在某些情况下,我们发现Qt窗口控件需要更多的自定义定制,这些定制可能要比它在Qt设计师里可设置的属性或者对它调用的那些函数更多一些。一个简单而直接的解决方法就是对相关的窗口部件类进行子类化并且使它能够满足我们的需要。 本文主要是通过实现一个十六进制微调

    2024年02月11日
    浏览(42)
  • Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化

    Qt 自定义窗口的标题栏,重写鼠标事件实现,关闭隐藏,最大化/最小化,重写窗口事件函数,实现鼠标选中边框拉大拉小,双击标题栏切换窗口最大化和最小化 1、main.cpp 2、widget.h 3、widget.cpp 4、效果展示 5、完成

    2024年02月16日
    浏览(64)
  • 在WPF窗口中增加水印效果

    ** ** 以Canvas作为水印显示载体,在Canvas中创建若干个TextBlock控件用来显示水印文案,如下图所示 然后以每一个TextBlock的左上角为中心旋转-30°,最终效果会是如图红线所示: 为了达到第一行旋转后刚好与窗口上边沿齐平,需要计算第一行其实位置的Top坐标,由于旋转角度为

    2024年02月04日
    浏览(36)
  • 界面控件DevExpress WPF流程图组件,完美复制Visio UI!(一)

    DevExpress WPF Diagram(流程图)控件帮助用户完美复制Microsoft Visio UI,并将信息丰富且组织良好的图表、流程图和组织图轻松合并到您的下一个WPF项目中。 P.S :DevExpress WPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有

    2024年02月04日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包