我的编程空间,编程开发者的网络收藏夹
学习永远不晚

WPF利用WindowChrome实现自定义窗口

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

WPF利用WindowChrome实现自定义窗口

简介

Microsoft官网关于 WindowChome 的介绍

截取Microsoft文章的一段话:

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

效果图

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

最小化按钮

<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 到这一点很多问题就迎刃而解了。

到此这篇关于WPF利用WindowChrome实现自定义窗口的文章就介绍到这了,更多相关WPF WindowChrome自定义窗口内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

WPF利用WindowChrome实现自定义窗口

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

WPF利用WindowChrome实现自定义窗口

这篇文章主要为大家详细介绍了WPF如何利用WindowChrome实现自定义窗口,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
2023-02-16

WPF自定义控件的实现

本文主要介绍了WPF自定义控件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-03-03

WPF自定义控件如何实现

今天小编给大家分享一下WPF自定义控件如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。方式一:基于现有控件进行扩展,如
2023-07-05

win10系统如何实现窗口自定义调整

这篇文章主要为大家展示了“win10系统如何实现窗口自定义调整”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“win10系统如何实现窗口自定义调整”这篇文章吧。1、按win+r打开运行窗口,输入r
2023-06-28

Flask如何利用自定义接口实现mock应用

这篇文章主要介绍了Flask如何利用自定义接口实现mock应用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Flask如何利用自定义接口实现mock应用文章都会有所收获,下面我们一起来看看吧。问题:后端接口已提
2023-07-05

Flask利用自定义接口实现mock应用详解

后端接口已提供,前端需要依赖后端接口返回的数据进行前端页面的开发,如何配合前端?这篇就来介绍一下Flask如何利用自定义接口实现mock应用,需要的可以参考一下
2023-03-06

QT中如何实现自定义quick-Popup弹出窗口

小编给大家分享一下QT中如何实现自定义quick-Popup弹出窗口,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.Popup介绍Popup是一个弹出窗口的控件
2023-06-20

怎么在Android中利用marker自定义一个弹框窗口

怎么在Android中利用marker自定义一个弹框窗口?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Android是什么Android是一种基于Linux内核的自由及开放源代
2023-06-14

android实现百度地图自定义弹出窗口功能

我们使用百度地图的时候,点击地图上的Marker,会弹出一个该地点详细信息的窗口,如下左图所示,有时候,我们希望自己定义这个弹出窗口的内容,或者,干脆用自己的数据来构造这样的弹出窗口,但是,在百度地图最新的Android SDK中,没有方便
2022-06-06

Electron 自定义窗口桌面时钟实现示例详解

这篇文章主要为大家介绍了Electron 自定义窗口桌面时钟实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-03-09

WPF实现自定义一个自删除的多功能ListBox

这篇文章主要为大家详细介绍了如何利用WPF实现自定义一个自删除的多功能ListBox,文中示例代码讲解详细,感兴趣的小伙伴可以了解一下
2022-12-28

Android自定义弹出窗口PopupWindow使用技巧

PopupWindow是Android上自定义弹出窗口,使用起来很方便。 PopupWindow的构造函数为代码如下:public PopupWindow(View contentView, int width, int height, b
2022-06-06

C# wpf利用附加属性实现界面上定义装饰器

装饰器是wpf中可以浮在控件上面的一种组件,我们通常可以用来实现一些诸如控件拖动点、提示框、自定义鼠标等界面功能。本文主要是利用附加属性实现界面上定义装饰器,需要的可以参考下
2022-12-16

Android上利用gpio keys实现自定义键盘

1.驱动支撑 gpio keys子系统就是为了实现GPIO+按键实现键盘功能。在一些不支持USB键盘的应用场景非常有用。 实现DTS的修改:这里说明一下键值,如上图中的linux,code对应的值,这个可以在内核原码相关头文件中查到: in
2022-06-06

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录