原文:简述WPF中的画刷(Brush)

--------------------------------------------------------------------------------
引用或转载时请保留以下信息:
大可山 [MSN:a3news(AT)hotmail.com]
http://www.zpxp.com http://www.brawdraw.com
萝卜鼠在线图形图像处理
--------------------------------------------------------------------------------

我们知道,在GDI+中,画刷用于填充图形形状,如矩形、椭圆、扇形、多边形和封闭路径。在GDI+中,画刷分为以下几种:SolidBrush,TextureBrush,HatchBrush,LinearGradientBrush和PathGradientBrush。在层次关系上,它们都位于System.Drawing空间下,继承自System.Drawing.Brush类。

其中SolidBrush定义单色画刷;TextureBrush定义纹理画刷,HatchBrush使用预定义的50余种图案做画刷,LinearGradientBrush是线性渐变画刷,PathGradientBrush是通过渐变填充GraphicsPath对象的内部。

它们的继承关系如下图:
System.Object
  System.MarshalByRefObject
    System.Drawing.Brush
      System.Drawing.SolidBrush
      System.Drawing.TextureBrush
      System.Drawing.Drawing2D.HatchBrush
      System.Drawing.Drawing2D.LinearGradientBrush
      System.Drawing.Drawing2D.PathGradientBrush

那么,在WPF中,是如何定义画刷的呢?它们与GDI+中的画刷相比,又有些什么独特之处呢?

首先,我们来看看WPF中有哪些画刷?

从大分类来讲,WPF中的画刷分为三大类:单色画刷SolidColorBrush,可平铺的画刷TileBrush和渐变画刷GradientBrush

不妨先看看它们的继承关系:


从上图可以看出,WPF中的画刷都位于System.Windows.Media命名空间下。
继承自TileBrush的有三种:DrawingBrush,ImageBrush,VisualBrush; 继承自GradientBrush的有两种画刷:LinearGradientBrushRadialGradientBrush
加上SolidColorBrush,WPF中实际共有六种画刷(上图中已用画“勾”的方式标明)。
其中,SolidColorBrush使用单色填充指定区域,DrawingBrush是图画绘制画刷(包括矢量图和位图),ImageBrush是使用图像做画刷,而VisualBrush是以可视化的控件作为画刷,比如:可使用矩形Rect,文本TextBlock,甚至按钮Button、动画、视频等等作为画刷;与GDI+类似,WPF中使用LinearGradientBrush作为线性渐变画刷;但WPF新增了一个镭射渐变画刷RadialGradientBrush。

让我们来看看它们都“长”成什么样子吧。还是以实例来走马观花式地看看它们。

下面是一个空的“容器”,我们将用它来“装”各种东西。

XAML代码:
<Ellipse x:Name="ellipseWithNothing" Width="113.56" Height="113.56" Fill="{x:Null}" Stroke="#FF000000" />
这里的Fill填充为空。

接着我们给它填充点单一的颜色(SolidColorBrush):

XAML代码:
<Ellipse x:Name="ellipseWithSolidColorBrush" Width="113.56" Fill="#FFA21212" Stroke="#FF000000" />
注意这里的Fill属性,由于XAML最终被转化为.Net代码,这里的Fill也将转换为颜色为“#FFA21212”的SolidColorBrush。
如你对于WPF颜色方面有疑问,你可以参见我的这篇文章:GDI+与WPF中的颜色简析

接下来我们改用线性渐变颜色填充它:(使用LinearGradientBrush)

XAML代码:
  <Ellipse x:Name="ellipseWithLinearGradientBrush" Height="113.56" Stroke="#FF000000" Width="113.56">
   <Ellipse.Fill>
    <LinearGradientBrush EndPoint="0.851,0.838" StartPoint="0.115,0.169">
     <GradientStop Color="#FFA21212" Offset="0"/>
     <GradientStop Color="#FFF8C906" Offset="1"/>
    </LinearGradientBrush>
   </Ellipse.Fill>
  </Ellipse>
(注意:这里使用了GradientStop来定义渐变颜色的关键色及对应的位置参数设置)

变多点花样,我们就可以做成一个带立体感的圆形按钮了:

XAML代码:
<Ellipse x:Name="ellipseWithLinearGradientBrushButtonOuter" Stroke="#FF000000" HorizontalAlignment="Left" Margin="130.015,156.959,0,175.481" Width="113.559">
   <Ellipse.Fill>
    <LinearGradientBrush EndPoint="0.851,0.838" StartPoint="0.115,0.169">
     <GradientStop Color="#FFA21212" Offset="0"/>
     <GradientStop Color="#FFF8C906" Offset="1"/>
    </LinearGradientBrush>
   </Ellipse.Fill>
  </Ellipse>
  <Ellipse x:Name="ellipseWithLinearGradientBrushButtonInner" Stroke="#FF000000" Width="89.006" HorizontalAlignment="Left" Margin="142.264,169.263,0,187.731">
   <Ellipse.Fill>
    <LinearGradientBrush EndPoint="0.129,0.129" StartPoint="0.879,0.845">
     <GradientStop Color="#FFA21212" Offset="0"/>
     <GradientStop Color="#FFF8C906" Offset="1"/>
    </LinearGradientBrush>
   </Ellipse.Fill>
  </Ellipse>
(注:这里只是将起始颜色的起始、终止点进行了反向,这样就产生了立体的效果)

接着,我们使用RadialGradientBrush:

XAML代码:
  <Ellipse x:Name="ellipseWithRadialGradientBrush" Height="113.56" Stroke="#FF000000">
   <Ellipse.Fill>
    <RadialGradientBrush>
     <GradientStop Color="#FFA21212" Offset="1"/>
     <GradientStop Color="#FFF8C906" Offset="0"/>
    </RadialGradientBrush>
   </Ellipse.Fill>
  </Ellipse>

再变变花样,将中心点移一移,看看是什么样子的:

XAML代码:
  <Ellipse x:Name="ellipseWithRadialGradientBrushCenterOffset" Stroke="#FF000000">
   <Ellipse.Fill>
    <RadialGradientBrush GradientOrigin="0.399,0.149">
     <GradientStop Color="#FFA21212" Offset="1"/>
     <GradientStop Color="#FFF8C906" Offset="0"/>
    </RadialGradientBrush>
   </Ellipse.Fill>
  </Ellipse>

下面来看看使用ImageBrush填充的效果(这里使用了我的一个好友的图片,美女哟!):

XAML代码:
<Ellipse x:Name="ellipseWithImageBrush" Stroke="#FF000000" Width="113" Height="113">
   <Ellipse.Fill>
    <ImageBrush ImageSource="xian.png"/>
   </Ellipse.Fill>
  </Ellipse>

再来看看使用VisualBrush填充的效果:

XAML代码:
<Ellipse x:Name="ellipseWithVisualBrush" Width="113" Stroke="#FF000000" Height="113">
  <Ellipse.Fill>
<VisualBrush>
      <VisualBrush.Visual>
        <StackPanel Background="White">
          <Rectangle Width="25" Height="25" Fill="Orange" Margin="6" />
          <TextBlock FontSize="10pt" Margin="2">BrawDraw</TextBlock>
          <Button Margin="10">Button</Button>
        </StackPanel>
      </VisualBrush.Visual>
    </VisualBrush>
</Ellipse.Fill>
  </Ellipse>
看到没?这里使用了Rectangle,TextBlock,Button几种可视化的控件作为画刷,填充到了Ellipse中。

轮到DrawingBrush出场了:

XAML代码:
<Ellipse x:Name="ellipseWithDrawingBrush" Stroke="#FF000000" Width="113" Height="113">
  <Ellipse.Fill>
  <DrawingBrush Viewport="0,0,0.5,0.5" TileMode="Tile">
          <DrawingBrush.Drawing>
            <GeometryDrawing Brush="Red">
              <GeometryDrawing.Geometry>
                <GeometryGroup>
                  <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
                  <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
                </GeometryGroup>
              </GeometryDrawing.Geometry>
              <GeometryDrawing.Pen>
                <Pen Thickness="10">
                  <Pen.Brush>
                    <LinearGradientBrush>
                      <GradientStop Offset="0.0" Color="Black" />
                      <GradientStop Offset="1.0" Color="Gray" />
                    </LinearGradientBrush>
                  </Pen.Brush>
                </Pen>
              </GeometryDrawing.Pen>
            </GeometryDrawing>
          </DrawingBrush.Drawing>
        </DrawingBrush>
</Ellipse.Fill>
  </Ellipse>
这里使用了GeometryDrawing 作为内部填充的图案,还使用了作为LinearGradientBrush画笔来绘制内部图案的。

总结一下:
WPF的画刷与GDI+中的画刷相比,有很大的进步,功能更强大了。WPF新增了DrawingBrush图画绘制画刷(包括矢量图和位图),而VisualBrush是以可视化的控件作为画刷,WPF新增了一个镭射渐变画刷RadialGradientBrush。需要指出的是,WPF中多数显示效果都使用硬件(显示)的运算能力而不是软件来展现,这都得益于DirectX 9/10的相关技术。

相关文章:
深入WPF中的图像画刷(ImageBrush)之1——ImageBrush使用举例
深入WPF中的图像画刷(ImageBrush)之2——ImageBrush的铺设方式
简述WPF中的画刷(Brush)〔本篇〕

简述WPF中的画刷(Brush)的更多相关文章

  1. 简述WPF中的图像像素格式(PixelFormats)

    原文:简述WPF中的图像像素格式(PixelFormats) --------------------------------------------------------------------- ...

  2. WPF样式之画刷结合样式

    第一种画刷,渐变画刷GradientBrush (拿线性渐变画刷LinearGradientBrush(其实它涵盖在GradientBrush画刷内.现在拿他来说事.),还有一个圆心渐变画刷Radia ...

  3. Direct2D 学习笔记(2)画刷 Brush

    画刷的使用方法 需要包含的文件:<wincodec.h> 需要包含的库: "windowscodecs.lib" 资源网址:    https://docs.micro ...

  4. WPF中线性渐变画刷的一个小窍门

    最近被项目里面控件的设计搞的死去活来的,大部分的设计都会需要使用进度条的功能,因为UI形状的变态,使用ProgressBar不能满足需求,没办法就自己想办法实现进度显示.折腾的多了发现一个很不错的方法 ...

  5. WPF线性渐变画刷应用之——炫彩线条

    效果图: Xaml代码: <Rectangle Width="800" Height="10"> <Rectangle.Fill> &l ...

  6. 深入WPF中的图像画刷(ImageBrush)之2——ImageBrush的铺设方式

    原文:深入WPF中的图像画刷(ImageBrush)之2--ImageBrush的铺设方式 ------------------------------------------------------ ...

  7. 深入WPF中的图像画刷(ImageBrush)之1——ImageBrush使用举例

    原文:深入WPF中的图像画刷(ImageBrush)之1--ImageBrush使用举例 昨天我在<简述WPF中的画刷(Brush)  >中简要介绍了WPF中的画刷的使用.现在接着深入研究 ...

  8. 在WPF中自定义你的绘制(五)

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

  9. Unity3D-terrain brush地形画刷无法出现在Scene中,无法刷地图2

    原因大概是 画刷brush 太小了,地图也太小了,没出出现. 如图,非正常状态: 解决方法: tag: terrain brush not working unity

随机推荐

  1. C++ 宏、范型和RTTI 浅析

    [摘要]        RTTI(Run-Time Type Identification)是面向对象程序设计中一种重要的技术. 现行的C++标准对RTTI已经有了明白的支持. 只是在某些情况下出于特 ...

  2. Compmgmtlauncher.exe问题解决方法

    修改注册表:HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\shell\Manage\command   原来的默认键值为 ...

  3. mysql 5.7 innodb count count(*) count(1) 大数据 查询慢 耗时多 优化

    原文:mysql 5.7 innodb count count(*) count(1) 大数据 查询慢 耗时多 优化 问题描述 mysql 5.7 innodb 引擎 使用以下几种方法进行统计效率差不 ...

  4. linux 安装完mysql 密码重置

    If you have forgot the MySQL root password, can’t remember or want to break in….. you can reset them ...

  5. [PReact] Use Link State to Automatically Handle State Changes

    Storing and updating values inside a component’s local state (known as controlled components) is suc ...

  6. [RxJS] Implement pause and resume feature correctly through RxJS

    Eventually you will feel the need for pausing the observation of an Observable and resuming it later ...

  7. Activity生命周期的回调,你应该知道得很多其它!--Android源代码剖析(下)

            转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/46910811[yalinfendou的博客]          ...

  8. 解决maven项目找不到maven依赖的解决办法

    不同的IDE对应的.classpath中的maven声明也不一样,这样就会导致项目找不到maven依赖. 即Java Build Path--->Libraries中找不到Maven Depen ...

  9. Fragment之一:Fragment入门 分类: H1_ANDROID 2013-11-15 18:16 2799人阅读 评论(2) 收藏

    参考自张泽华视频 Fragment是自Android3.0后引入的特性,主要用于在不同的屏幕尺寸中展现不同的内容. Fragment必须被嵌入Activity中使用,总是作为Activity的组成部分 ...

  10. python implementation for Qt's QDataStream(看一下QDataStream的结构)

    #!/usr/bin/env python # -*- coding: utf- -*- from __future__ import print_function from __future__ i ...