原文:WPF绘制自定义窗口

WPF是制作界面的一大利器,下面就用WPF模拟一下360的软件管理界面,360软件管理界面如下:

界面不难,主要有如下几个要素:

  1. 窗体的圆角
  2. 自定义标题栏及按钮
  3. 自定义状态栏
  4. 窗体的半透明效果
  5. 窗体4周有一圈半透明阴影(抓的图上看不出来)

实现思路很简单,首先隐藏默认窗口的标题栏和边框,然后用WPF的Border或Canvas等元素模拟定义窗体的标题栏、内容区和状态栏。

具体实现如下:

第一步:定义义个窗口基类,继承自Window,在构造函数中加载自定义窗口的样式文件,代码如下:

View Code

public partial class WindowBase:Window{InitializeTheme();}private void InitializeTheme(){string themeName = ConfigManage.CurrentTheme;//样式所在的文件夹

App.Current.Resources.MergedDictionaries.Add(Application.LoadComponent(new Uri(string.Format("../Theme/{0}/WindowBaseStyle.xaml", themeName), UriKind.Relative)) as ResourceDictionary);}

  接下来,就可以在WindowBaseStyle.xaml样式文件中定义窗口元素及样式了。

  第二步:重写窗口模板

  因为Window和Button等控件一样,实际是继承自System.Windows.Controls.Control类,所以可以通过使用 ControlTemplate 自定义控件的外观 ,代码如下:

View Code

<!--基窗口样式--><Style x:Key="BaseWindowStyle" TargetType="{x:Type Window}"><Setter Property="Template" Value="{StaticResource BaseWindowControlTemplate}"/><Setter Property="Background"Value="Transparent" /><Setter Property="WindowStyle"Value="None" /><Setter Property="AllowsTransparency"Value="True" /></Style><!--基窗口模板--><ControlTemplate x:Key="BaseWindowControlTemplate" TargetType="{x:Type Window}"><Grid Width="{Binding ElementName=w, Path=Width}" Height="{Binding ElementName=w, Path=Height}"><!—第四步介绍如下Border元素的作用—><Border BorderThickness="5" CornerRadius="6" BorderBrush="#000000" Opacity=".08"></Border><!—第三步介绍borderBg元素的作用—><Border x:Name="borderBg" Margin="5" Background="#000000" BorderBrush="#ffffff" Opacity=".8" BorderThickness="2" CornerRadius="{StaticResource winCorner}" Style="{StaticResource winStyle}"><!—定义窗口的元素,Grid的四行分别为标题栏、内容、状态栏上的横线、状态栏--><Grid><Grid.RowDefinitions><RowDefinition Height="auto"></RowDefinition><RowDefinition Height="*"></RowDefinition><RowDefinition Height="1"></RowDefinition><RowDefinition Height="30"></RowDefinition></Grid.RowDefinitions><Border Grid.Row="0" Background="#4f535d" CornerRadius="{StaticResource winTitleCorner}" Style="{StaticResource titleStyle}"></Border><Canvas Grid.Row="2" Background="#42464d"></Canvas><Border Grid.Row="3" CornerRadius="{StaticResource winStatusCorner}"></Border></Grid></Border><Grid Margin="7"><Grid.RowDefinitions><RowDefinition Height="auto"></RowDefinition><RowDefinition Height="*"></RowDefinition><RowDefinition Height="1"></RowDefinition><RowDefinition Height="30"></RowDefinition></Grid.RowDefinitions><!--标题栏框--><Border x:Name="borderTitle" Grid.Row="0" CornerRadius="{StaticResource winTitleCorner}" Style="{StaticResource titleStyle}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"><Grid Background="Transparent"><TextBlock Text="{Binding ElementName=w, Path=Title}" Foreground="White" Opacity=".75" HorizontalAlignment="Left"></TextBlock><StackPanel HorizontalAlignment="Right" VerticalAlignment="Top" Visibility="Hidden"Orientation="Horizontal"><!--关闭按钮--><Button x:Name="btnMin" Style="{StaticResource minBtnStyle}"></Button><Button x:Name="btnClose" Style="{StaticResource closeBtnStyle}"></Button></StackPanel></Grid></Border><!--内容--><Grid x:Name="gridContent" Grid.Row="1"><ContentPresenter /></Grid><Border Grid.Row="3" CornerRadius="{StaticResource winStatusCorner}"><StackPanel Orientation="Horizontal" HorizontalAlignment="Right" ><Button x:Name="btnYes" Style="{StaticResource btnStyle}"></Button><Button x:Name="btnNo" Style="{StaticResource btnStyle}"></Button></StackPanel></Border></Grid></Grid></ControlTemplate>

  需要注意的是,实际代码中应该将BaseWindowControlTemplate的定义放到BaseWindowStyle的前边,否则会抛出异常。

  第三步:实现半透明

  用Js实现过遮罩型的模态窗口的同学都知道,如果将元素如按钮直接放到一个半透明的Div中,会发现按钮本身也半透明了,这显然不是我们所希望的,我们只需要背景半透明,元素本身透明度不受影响,实现的思路应该是这样,将按钮和div平级,利用定位属性将按钮和半透明的div保持相对位置,而不是将按钮放入Div中。

  WPF中,实现方式和其一样,请看第二步中的x:Name="borderBg"的Border元素的定义。它和后面的Grid元素定义的实际窗口是同级的。

  第四步:实现窗体四周半透明的环绕

  这个先简单用一个半透明具有一定宽度的Border来模拟,代码如步骤二中所示,后续考虑做成类似外发光的效果。

  第五步:实现最小化、关闭、拖动等事件

  在WindowBase的构造函数中,添加如下代码:

  

View Code

this.Loaded += delegate
{InitializeEvent();
};
private void InitializeEvent()
{ControlTemplate baseWindowTemplate = (ControlTemplate)App.Current.Resources["BaseWindowControlTemplate"];Border borderTitle = (Border)baseWindowTemplate.FindName("borderTitle", this);Button closeBtn = (Button)baseWindowTemplate.FindName("btnClose", this);Button minBtn = (Button)baseWindowTemplate.FindName("btnMin", this);YesButton = (Button)baseWindowTemplate.FindName("btnYes", this);NoButton = (Button)baseWindowTemplate.FindName("btnNo", this);minBtn.Click += delegate{MinWin();};closeBtn.Click += delegate{this.Close();};borderTitle.MouseMove += delegate(object sender, MouseEventArgs e){if (e.LeftButton == MouseButtonState.Pressed){this.DragMove();}};
}

  注意, InitializeEvent方法必须放到Loaded事件处理函数中,否者会找不到按钮。

  第六步: 定义最小化,关闭按钮的样式

  实际上也是定义Template属性,定义方法类似于窗口模板的定义,详细见附件中完整代码。

  到此,自定义窗口的基类就打造完成,完整代码见附件。

  使用方法很简单,新建一个WPF窗口后将窗体的基类改成上面定义的WindowBase,同时注意将Xmal文件的根元素改成如下形式:

  

<my:WindowBase xmlns:my="clr-namespace:Ezhu.WPFWin"…

  运行效果如下图所示:

  附件:自定义窗口代码

WPF绘制自定义窗口相关推荐

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

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

  2. qt自定义窗口,其绘制的窗口边框线显示不全

    引言 自定义窗口,该窗口包含标题栏,默认整个窗口的边框线为蓝色,当点击该窗口的时候,窗口的边框线便为红色.程序在运行的时候,窗口的边框线只显示了左右两边的线,没有显示上下边的线. 示例 效果: 解决方 ...

  3. wpf 自定义窗口,最大化时覆盖任务栏解决方案

    原文:wpf 自定义窗口,最大化时覆盖任务栏解决方案 相信很多人使用wpf时会选择自定义美观的窗口,因此会设置WindowStyle="None" 取消自带的标题栏.但这样使用 W ...

  4. 在WPF中自定义你的绘制(二)

    在WPF中自定义你的绘制(二) 原文:在WPF中自定义你的绘制(二)   在WPF中自定义你的绘制(二)                                                 ...

  5. WPF.UIShell UIFramework之自定义窗口的深度技术

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

  6. WPF 绘制对齐像素的清晰显示的线条

    WPF 绘制对齐像素的清晰显示的线条 原文:WPF 绘制对齐像素的清晰显示的线条 版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可.欢迎转载.使用.重新发布, ...

  7. WPF设计の自定义窗体

    原文:WPF设计の自定义窗体 效果图如下: 实现思路: 1.继承Window类 2.为自定义的CustomWindow类设计窗体样式(使用Blend很方便!) 3.为窗体增加最大最小化和关闭按钮,并实 ...

  8. WPF如何给窗口设置透明png的图片背景

    在 WPF 中,如果想做一个背景透明的异形窗口,基本上都要设置 WindowStyle="None".AllowsTransparency="True" 这两个 ...

  9. 【原创】Qt自定义窗口部件

    QtDesigner自定义窗口部件有两种方法:改进法(promotion)和插件法(plugin) 改进法 1.改进法之前,要先写好子类化QSpinBox后的HexspinBox.h和HexspinB ...

最新文章

  1. win10突然只剩下c盘和d盘了_电脑C盘爆满飘红?系统卡?试试这两种解决办法
  2. 几种开源分词工具的比較
  3. Sql server 2005系统表详细说明
  4. 面对重重问题 光伏扶贫路在何方?
  5. header中Content-Disposition的作用与使用方法
  6. 外媒炒作中国黑客入侵美保险公司 并无相关证据
  7. 外挂学习之路(3)--- 内存遍历工具
  8. spark和hadoop升级记录(持续更新中)
  9. Spring Data:企业级Java的现代数据访问技术(影印版)
  10. SAP Spartacus Translation (翻译) 相关话题
  11. linux下安装win xp 进pe出错,PE安装原版XP系统(含高版本PE安装选项灰色处理办法)...
  12. Mysql高级考试题_MySQL高级应用答案试题题目及答案,期末考试题库,章节测验答案...
  13. oracle如何自定义类型,Oracle 自定义类型
  14. C语言方向键识别和字母识别,c语言中怎样输入和读取方向键
  15. STL_set/vector/deque
  16. python3.5安装教程linux_安装Python 3.6在Ubuntu 16.04上
  17. ubuntu14.04中安装opencv2.4.11
  18. Hadoop权威指南
  19. 数据库原理与应用学习笔记(一)
  20. 攻防世界----confusion1

热门文章

  1. Libgdx New 3D API 教程之 -- 使用Libgdx加载模型
  2. 2.easyui 控件取值方式
  3. JS-undefined与null的区别
  4. CDays–2 完成核心功能 CMD模块 Python基础教程 cmd cli
  5. wifi无线破解(BT4)
  6. 只让输入数字的输入框(javascript)
  7. 好系统U盘启动来说一说win10系统有必要更新到最新版本吗?
  8. StringBuilder与 StringBuffer
  9. IO系统性能之一:衡量性能的几个指标
  10. Switch入门第一讲