自定义WPF 窗口样式

自定义 Window

在客户端程序中,经常需要用到自定义一个 Window ,大部分是为了好看吧。做了很多研究和实践之后,觉得需要把这个过程写下来,以供查阅。

WPF 提供的丰富的功能使得自定义 Window 变得简单,但是也不是一个简单的 Style 就能做到的事情。虽然 WPF 中的控件是 Lookless 的,但是 Window 类有他自己的特殊之处,做个简单的实验就能看出,对于普通的 WPF 控件,用 XamlWriter.Write 方法就能将某个类型对象的模板输出出来,这样就可以看到该控件的内部构造。但是如果输出 Window 对象的默认模板,就会发现模板非常简单,其中并没有包含标题栏以及最大化最小化按钮的定义,具体的实现不得而知,但是至少说明 Window 的默认 Style 不是按照 WPF 的规范来实现的。

 

为了实现任意风格的 Window 就需要重写 Window 的默认模板,第一步要做的就是创建 Window 的一个派生类,并创建自定义 Style ,然后重写 DefaultStyleKey 属性让 WPF 引擎来将样式和 Window 的派生类装载到一起。具体做法如下:

1.         创建一个 WPF Application 项目

2.         在项目中添加 Themes 文件夹,并在该文件夹下添加名称为 Generic.xaml ResourceDictionary 。该文件夹和文件的名称和位置都是固定的,也就是说必须这么做才能让 WPF 引擎让自定义控件和默认 Style 协同工作,因为微软对此进行了硬编码。

3.         创建自定义窗口类为 HeaderedWindow ,为什么定义为 HeaderedWindow 呢?因为我觉得 Window 对象更像是一个 HeaderedContentControl 而不是一个 ContentControl ,因为它的标题栏更像是一个 Header ,而不仅仅是为了显示图标和标题! HeaderedWindow 类的定义如下:

 

public class HeaderedWindow : Window

{

static HeaderedWindow()

    {

      DefaultStyleKeyProperty.OverrideMetadata(typeof (HeaderedWindow ), new FrameworkPropertyMetadata (typeof (HeaderedWindow )));     

    }

}

 

4.         Generic.xaml 文件中添加 HeaderedWindow 的默认样式,如下:

< Style TargetType ="{ x : Type l : HeaderedWindow }">

    < Setter Property ="WindowStyle" Value ="None"/>

    < Setter Property ="ResizeMode" Value ="NoResize"/>

    < Setter Property ="Background" Value ="Gray"/>

    < Setter Property ="BorderBrush" Value ="#FF5A3D1C"/>

    < Setter Property ="BorderThickness" Value ="1"/>

    < Setter Property ="MinWidth" Value ="90"/>

    < Setter Property ="MinHeight" Value ="33"/>

    < Setter Property ="VerticalContentAlignment" Value ="Stretch"/>

    < Setter Property ="HorizontalContentAlignment" Value ="Stretch"/>

  </ Style >

最重要的两个属性是 WindowStyle ResizeMode ,将 WindowStyle 属性设置为 None 将会去除默认的标题栏,将 ResizeMode 设置为 NoResize 将会去除 Window 边框,该边框在 Window 7 比较难看,不过却有他的作用, 就是用来调整窗口大小,我们把它去掉了,就意味着我们需要自己来编写调整窗口大小的代码了。

5.         测试一下这个 HeaderedWindow 吧,编写如下测试代码:

 

< local : HeaderedWindow x : Class ="CustomWindowDemo.MainWindow"

         xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

         xmlns : x ="http://schemas.microsoft.com/winfx/2006/xaml"

         xmlns : local ="clr-namespace:CustomWindowDemo"

         Title ="MainWindow" Height ="350" Width ="525">

    < Grid >

       

    </ Grid >

</ local : HeaderedWindow >

后置代码类必须要从 HeaderedWindow 继承才行。运行程序发现窗口黑乎乎一片。这是因为我们还没有重写 Window ControlTemplate 的缘故。

6.         一个窗口应该有如下基本要素

a)         图标,就是 Icon 属性,自定义窗口应该有将其显示出来的能力

b)         标题,就是 Title 属性,自定窗口应该将其显示在标题栏中

c)         最大化,最小化,关闭按钮

d)         为了美观, Window 的边框应该定义出来。但是当窗口最大化的时候应该隐藏边框,扩大窗口的使用面积,这也是 Windows 下窗口的标准行为。

e)         八个方向的 Resizer 应该定义出来,这些 Resize 其实就是一些透明的 Thumb 控件,用来支持拖动事件,并改变窗口的定位和高宽。

对于 HeaderedWindow 还有几个扩展要素需要提供:

a)         自定义 Header 属性,用户可以重新定义 Window Header ,在这里我们将 Window Icon Title 定义为他的默认 Header ,所以有一个 ShowDefaultHeader 属性用来控制默认 Header 的可见性。 Header 属性是一个 Object 对象,其用法和 HeaderedContentControl 控件的 Header 几乎一模一样。

b)         ShowResizeGrip 属性,用来控制是否在右下角显示一个抓手模样的图形,用来指示用此处可以拖动,当然不显示也可以调整窗口大小,不过显示这个抓手增加了易用性。

c)         CanResize 属性,由于我们在样式中将窗口设置 ResizeMode NoResize ,所以需要提供一个额外的属性用来设置当前窗口是否可以调整大小。当 CanResize False 的时候,所有可以调整窗口大小的控件将被隐藏。

d)         最后一个比较有意思的属性就是 IsFullScreenMaximize ,当该属性设置为 True 的时候,那么当最大化的时候,窗口将把任务栏覆盖住。是真正意义上的“最大化”了。

7.           如果想制作不规则形状的窗口,需要将 AllowTransparency 属性设置为 true ,不过当此属性为 true 的时候,该 WPF 窗口将不能作为 WinForm 控件或者 ActiveX 控件的宿主了。所以需要慎重考虑。

最后附上全部代码以及使用方式,以供查阅!

Generic.xaml 的内容:

< ResourceDictionary xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

     xmlns : x ="http://schemas.microsoft.com/winfx/2006/xaml"

     xmlns : sys ="clr-namespace:System;assembly=mscorlib"

     xmlns : l ="clr-namespace:CustomWindowDemo">

 

    < l : BoolToVisibilityConverter x : Key ="BoolToVisibilityConverter"></ l : BoolToVisibilityConverter >

 

    < Style x : Key ="styleWindowButtonMinimize" BasedOn ="{ x : Null }" TargetType ="{ x : Type Button }">

        < Setter Property ="Template">

            < Setter.Value >

                < ControlTemplate TargetType ="{ x : Type Button }">

                    < Grid x : Name ="buttonClose">

                        < Ellipse Stroke ="{ x : Null }" StrokeThickness ="1" x : Name ="btnEllipse" >

                            < Ellipse.Fill >

                                < RadialGradientBrush >

                                    < GradientStop Color ="#BFABA7A4" Offset ="0.777"/>

                                     < GradientStop Color ="#FF897F77" Offset ="1"/>

                                </ RadialGradientBrush >

                            </ Ellipse.Fill >

                        </ Ellipse >

 

                        < Path x : Name ="iconMin" Width ="11.1641" Height ="2.06641" Canvas.Left ="3.97266" Canvas.Top ="8.51962" Stretch ="Fill" Fill ="#FFFFFFFF" Data ="F1 M 5.00659,8.51962C 4.43613,8.51831 3.97266,8.98184 3.97266,9.55347C 3.97266,10.1238 4.435,10.586 5.00659,10.586L 14.1028,10.586C 14.6733,10.586 15.1353,10.1238 15.1367,9.55215C 15.1367,8.98056 14.6733,8.51962 14.1028,8.51962L 5.00659,8.51962 Z "/>

                         < ContentPresenter SnapsToDevicePixels ="{ TemplateBinding SnapsToDevicePixels }" HorizontalAlignment ="{ TemplateBinding HorizontalContentAlignment }" VerticalAlignment ="{ TemplateBinding VerticalContentAlignment }" RecognizesAccessKey ="True"/>

                    </ Grid >

                    < ControlTemplate.Triggers >

                        < Trigger Property ="IsFocused" Value ="True"/>

                        < Trigger Property ="IsDefaulted" Value ="True"/>

                        < Trigger Property ="IsMouseOver" Value ="True">

                            < Setter Property ="Fill" Value ="#FF5D4E3E" TargetName ="btnEllipse"/>

                        </ Trigger >

                        < Trigger Property ="IsPressed" Value ="True"/>

                        < Trigger Property ="IsEnabled" Value ="False"/>

                    </ ControlTemplate.Triggers >

                </ ControlTemplate >

            </ Setter.Value >

        </ Setter >

    </ Style >

 

    < Style x : Key ="styleWindowButtonMaximize" BasedOn ="{ x : Null }" TargetType ="{ x : Type ToggleButton }">

        < Setter Property ="Template">

           

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 42
    评论
WPF是一种用于开发Windows应用程序的技术框架。迅雷窗口样式是指在WPF应用程序中使用类似于迅雷软件的窗口样式。 迅雷窗口样式通常包括以下几个特点: 1. 边框和标题栏:迅雷窗口样式通常具有特殊的边框和标题栏设计,可以给用户带来独特的视觉体验。边框和标题栏可以进行自定义,例如可以设置不规则的边框样式,或者给标题栏添加自定义的图标和按钮。 2. 透明效果:迅雷窗口样式通常采用透明效果,可以显示出背后的桌面或其他窗口内容。这样可以增加应用程序的时尚感和科技感。 3. 强调视图:迅雷窗口样式通常会对某些重要的视图元素进行强调,例如下载进度、操作按钮等。这样可以提升用户对这些重要信息的注意力,使其更易于操作。 4. 动画效果:迅雷窗口样式通常会使用各种动画效果来增加交互的流畅性和美观性,例如弹出菜单、窗口缩放等。这样可以提升用户体验,使应用程序更加生动有趣。 开发WPF应用程序时,可以使用XAML语言来定义窗口样式。通过设置窗口样式属性和使用自定义的控件模板,可以实现类似迅雷窗口样式的效果。同时,WPF还提供了丰富的视觉效果和动画功能,可以进一步增强迅雷窗口样式的效果。 总之,迅雷窗口样式是一种在WPF应用程序中使用类似于迅雷软件的窗口外观和交互效果的设计风格。通过合理运用WPF技术,可以实现这种样式,并提升用户体验和应用程序的吸引力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值