在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. CTF-wtc_rsa_bbq-writeup

    wtc_rsa_bbq 题目信息: 附件: cry200 解题思路: 1.观察cry200文件,发现该文件是一个二进制文件,用二进制模式查看,发现开头为50 4B 03 04,判断该文件是一个zip文 ...

  2. 成功解决1406, “Data too long for column ‘txt‘ at row 1“

    这是因为数据库里该字段的数据类型所给的数据空间太小.MySQL将截断超过指定列宽度的任何插入值.为了让这个不报错,可以尝试切换MySQL模式不使用严格模式. SET @@global.sql_mode ...

  3. 12、Java——异常

    ​  1.异常处理方案: 异常抛出 : throws 把异常抛出到上一层,谁调用谁解决 异常捕获 : try..catch try{ 有可能出现异常的代码; }catch(FileNotFoundEx ...

  4. maven手动添加库文件

    项目应用到了ojdbc,dubbo等私有库,maven无法直接下载,需要手动下载后添加到maven本地库里面. 以下以ojdbc为例: 1.下载jar后,cmd添加到本地库: mvn install: ...

  5. linux相关的常用站点

    1  http://cdimage.ubuntu.com/ ubuntu各个发行版的总集服务器 2 http://www.rpmfind.net/ 各种RPM包

  6. 《PHP 实现 Base64 编码/解码》笔记

    前言 早在去年 11 月底就已经看过<PHP 实现 Base64 编码/解码>这篇文章了,由于当时所掌握的位运算知识过于薄弱,所以就算是看过几遍也是囫囵吞枣一般,不出几日便忘记了其滋味. ...

  7. [POI2008]PER

    很有思维的一道题 这个题的题面非常简单,出题人很友好,没有搞什么奇怪的背景,(卡农(P3214)的作者看看人家),所以理解题面就是: 一句话题意: 给定一个长度为 \(n\) 的数列,求这个数列是在其 ...

  8. (Opencv02)图片展示

    (Opencv02)图片展示 在程序里我们怎么把图片显示出来呢? 这里需要记一个自定义函数就好啦!  def cv_show(name, img):     cv2.imshow(name, img) ...

  9. Tomcat 性能监控与优化

    JMX JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架.JMX是一套标准的 代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现 ...

  10. php中英文字符串转字母转大小写

    <?php //转小写 function lowercase($a){ $b = str_split($a, 1); $r = ''; foreach($b as $v){ $v = ord($ ...