在WPF界面开发中,有时候不想用系统的死板的窗口,想要来点新花样,常会自定义窗口。

那么,先抛出问题,想搞出下面这样的窗口,该咋整 ?

a

下面看一个啥也没设置过的普通窗口,这样的窗口,我们只能控制客户区,也就是白色部分,标题的棕色部分长啥样,我们控制不了。

所以我们要做的就是把窗口的棕色部分,也整成我们想写啥就写啥。下面放上我实现的效果,源码  https://files.cnblogs.com/files/CSSZBB/CustomWndow.rar

下面娓娓道来,一个窗口大概需要实现的功能如下

太久远的年代的做法我们就不讨论了,

现在随便一搜,应该有文章都会说用WindowChrome,如果没有windowchrome,上述的所有功能都需要自己实现,光是拖动边框改变大小这么一个,就够写半天的啦。

先说坑把,

1 主要就是最大化的逻辑,使用WindowChrome后最大化有点问题需要特殊处理,且受windowstyle="None"  ResizeMode="NoResize"  这些参数的影响,最大化的效果也不同,需要注意。

2 在 captionHeight 的范围内的控件,需设置WindowChrome.IsHitTestVisibleInChrome="True" 这个附加属性,

另外说一下windowstyle="None" 这个参数,按我目前试过的经验来说,除非需要制作能透明的窗口,否则是不需要设置windowstyle="None" 的 ,windowstyle="None" 时,系统自带的最大化,最小化,关闭 三个按钮,都是没有的,需要自己去实现。

当你给窗口设置了WindowChrome后,

    <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>

  

先不改window的style的其他参数。看到棕色的部分没有了,就是说设置了WindowChrome后,我们可控制的区域,扩展了本来不能控制的棕色头部

那么,是否系统给我们生成的棕色部分,没有了那?其他它还是在的,只是被我们的白色部分覆盖了。这里修改一下window的Template 。可以看到它又露出来了

            <Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Content_Panel" Grid.Row="1" Background="{TemplateBinding Background}">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>

 上面的代码中,我们给Window的模板,定义了一个32高度的行,这个行里啥也不放,也就是透明的。可以看到,系统给生成的最大化,最小化等按钮它又出来了,但是标题,ICO等就没有了。说明标题和ICON ,需要在Template中定义,它不是系统生成的。

那么,上面指出观察到的这个情况,有何意义那?

意义可能就是,有时候,我们只是想在标题栏(棕色部分) 添加几个控件,比如加个公司图标啊啥的,而不想改变其它时,可以这样做。这样,可以给我们省下自己去重写最大化,最小化,关闭按钮的时间

这里面忘记说了窗口重写Style的一个不算坑的坑,在编码阶段,不管你怎么设置Style,标题部分都是不变的,我一度以为是自己写的Style无效,一运行才发现是有效的

更多的时候,我们希望完全重写棕色部分。如下是一个框架的Window给我们提供的所有功能(包括边框拖动改变大小,按住标题区拖动改变位置),那么我们重写Style Template后,需要自己实现哪些部分那?

据我的经验,需要自己实现图标,标题,最小化,最大化,关闭这5个部分,

在没有WindowChrome的年代,重写window是需要自己实现所有功能的,所以说windowchrome还是提供了一些方便的。

来看下它的属性, 1 CaptionHeight 这个属性,是控制标题区(棕色部分,设置windowchrome后它不显示),接收鼠标响应的高度。  本来它现实的时候,这个部分右键,会弹出系统菜单,按住拖动,双击等都有响应的逻辑

现在棕色部分虽然不显示了,但是设置了CaptionHeight 后,相应高度的部分,仍然会对支持上述操作。

它也导致了一个问题,就是当你放上你自己写的最大化,最小化,关闭按钮时,你会发现点击无效,点这些按钮还是触发的 点击标题栏的事件。

这就牵扯出另外一个属性

WindowChrome.IsHitTestVisibleInChrome="True"。给你自己写的最大化,最小化,关闭按钮时,加上这个附加属性,他们就能响应鼠标了

到此,自定义标题栏,应该没啥问题了,你想加啥控件就加啥,完全自由。

其他属性影响不大

那么该说说里面的坑了,当你点击最大化窗口时,你会发现它的最大化是有问题的。如下图对比,最大化前,可以看到窗口里的3层的绿色边框,最大化后,发现左右下都只能看到一层边框了。且最大化等按钮,也超出了屏幕导致没显示全。

如果你设置了windows 的属性ResizeMode="NoResize",或者WindowStyle="None" 你会发现最大化后,它把任务栏也给占了,就想真正的全屏游戏一样!!

这里的原因想想也不难理解,最大化窗口,你自己实现最大化按钮一般只用设置WindowState = WindowState.Maximized;(不管是直接设置属性还是用系统命令)

而系统去做最大化这一步,其实是要很多步骤的,包括获取屏幕大小,计算窗口边框,调整窗口大小到屏幕大小(这里要去掉任务栏高度,去掉边框宽度)等等,

那么当你通过windowchrome重写了windowstyle改变了客户区的大小,系统默认给你的窗口边框边框也变了,它如果还是按原来的处理方式最大化,应该是有问题的。

这里的更精确的原理我们猜也猜不明白,也不是我们能控制的。只要能根据现在的现象调整出对的结果就行了

我直接说结果就是最大化时,系统把整个界面多最大化了8。上下左右都是。所以我们设置一个触发器,在最大化的时候,把我们自己定义的区域,缩小8就行了

完美!!

剩下的,就是把窗口做的漂亮点啦。开搞把!

WPF 实现完全可控制的漂亮自定义窗口的更多相关文章

  1. WPF界面设计技巧(2)—自定义漂亮的按钮样式

    原文:WPF界面设计技巧(2)-自定义漂亮的按钮样式 上次做了个很酷的不规则窗体,这次我们来弄点好看的按钮出来,此次将采用纯代码来设计按钮样式,不需要 Microsoft Expression Des ...

  2. WPF.UIShell UIFramework之自定义窗口的深度技术 - 模态闪动(Blink)、窗口四边拖拽支持(WmNCHitTest)、自定义最大化位置和大小(WmGetMinMaxInfo)

    无论是在工作和学习中使用WPF时,我们通常都会接触到CustomControl,今天我们就CustomWindow之后的一些边角技术进行探讨和剖析. 窗口(对话框)模态闪动(Blink) 自定义窗口的 ...

  3. 《Programming WPF》翻译 第9章 3.自定义功能

    原文:<Programming WPF>翻译 第9章 3.自定义功能 一旦你挑选好一个基类,你将要为你的控件设计一个API.大部分WPF元素提供属性暴露了多数功能,事件,命令,因为他们从框 ...

  4. WPF界面设计技巧(5)—自定义列表项呈现内容

    原文:WPF界面设计技巧(5)-自定义列表项呈现内容 接续上次的程序,稍微改动一下原有样式,并添加一个数据模板,我们就可以达成下面这样的显示功能: 鼠标悬停于文件列表项上,会在工具提示中显示图像缩略图 ...

  5. WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...

  6. WPF自定义窗口基类

    WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...

  7. [WPF疑难] 继承自定义窗口

    原文 [WPF疑难] 继承自定义窗口 [WPF疑难] 继承自定义窗口 周银辉 项目中有不少的弹出窗口,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于Window自身的,但每个弹出框 ...

  8. WPF界面设计技巧(4)—自定义列表项样式

    原文:WPF界面设计技巧(4)-自定义列表项样式 有前面修改按钮样式的基础,我们可以尝试来定制一个即好看又好用的 ListBox ,今天先来讲“好看”部分. 打开 Microsoft Visual S ...

  9. WPF换肤之五:创建漂亮的窗体

    原文:WPF换肤之五:创建漂亮的窗体 换肤效果 经过了前面四章的讲解,我们终于知道了如何拖拉窗体使之改变大小,也知道了如何处理鼠标事件,同时,也知道了如何利用更好的编写方式来编写一个方便实用和维护的换 ...

随机推荐

  1. 「AGC029C」Lexicographic constraints

    「AGC029C」Lexicographic constraints 传送门 好像这个题非常 easy. 首先这个答案显然具有可二分性,所以问题转化为如何判定给定的 \(k\) 是否可行. 如果 \( ...

  2. kali之Metasploit入门

    前言 不得不说Metasploit 目前是世界领先的黑客框架.它在某种程度上被几乎每个黑客/渗透者使用.因此,如果您想进入网络安全/渗透测试行业并有所成就,您就必须要需要熟悉它. Metasploit ...

  3. EasyUI学后总结第一集

    1,创建Easyui组件-使用html还是使用js方式? 如果在创建Easyui组件的时候,组件再被更改,那么属于静态组件,对于静态组件不要使用js方式创建--会增加js代码量. 如果创建的Easyu ...

  4. [c++] 面向对象课程(二)-- 带指针类的设计

    class with pointer menbers string_test.cpp 1 #include "string.h" 2 #include <iostream&g ...

  5. Vmware 虚拟机网络通讯

    VMware Workstation(中文名"威睿工作站")是一款功能强大的桌面虚拟计算机软件,提供用户可在单一的桌面上同时运行不同的操作系统,和进行开发.测试 .部署新的应用程序 ...

  6. linux安装虚拟环境的步骤

    1.创建名为env_wcs,python版本为3.6的虚拟环境conda create -n env_wcs python=3.6conda create -n my_ env numpy matpl ...

  7. DNS投毒学习分析总结

    [一]背景 今晚看一份日志,数据很奇怪.大佬说是DNS投毒,盲点就来了,学习一下~ [二]内容 https://zhuanlan.zhihu.com/p/92899876 看完内容发现属于之前写的DN ...

  8. Vulhub-Mysql 身份认证绕过漏洞(CVE-2012-2122)

    前言 当连接MariaDB/MySQL时,输入的密码会与期望的正确密码比较,由于不正确的处理,会导致即便是memcmp()返回一个非零值,也会使MySQL认为两个密码是相同的.也就是说只要知道用户名, ...

  9. 37岁Android程序员被裁员,面试大厂被拒,降薪去小公司,心更凉了

    在职场论坛看到这样一个帖子,程序员小A被前公司裁员了,裁员之后也并没有特别气馁,打算重头再来,结果却被现实打击到了. 他大学毕业的时候进入到一家知名互联网公司上班,工作期间,也是不断学习,提升自己的能 ...

  10. 谷歌内部流出Jetpack Compose最全上手指南,含项目实战演练!

    简介 Jetpack Compose是在2019Google i/O大会上发布的新的库.Compose库是用响应式编程的方式对View进行构建,可以用更少更直观的代码,更强大的功能,能提高开发速度. ...