浅谈WPF的Brush

 背景

  什么是WPF中的画刷,顾名思义屏幕上可见的所有内容都可见,因为它是由画笔绘制的。 例如,画笔用于描述按钮的背景、文本的前景和形状的填充效果首先我们来看看WPF中包含哪些类型的画刷,下面的一组图片中描述了我们常用的画刷类型,后面我们通过一组具体的示例来讲述每一种画刷的具体使用方法。

 

图一 常见的画刷类型

1 SolidColorBrush

SolidColorBrush使用纯色绘制区域 Color 。 可以通过多种方式指定的 Color SolidColorBrush :例如,可以指定其 alpha、红色、蓝色和绿色通道,或使用类提供的预定义颜色之一 Colors 。

下面的示例使用 SolidColorBrush 绘制 Fill 的 Rectangle 。 下图显示了绘制的矩形

 图二 SolidColorBrush

 我们来看看我们在WPF中到底该如何使用?

  1.1 通过C#代码直接进行创建

Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a SolidColorBrush and use it to
// paint the rectangle.
SolidColorBrush myBrush = new SolidColorBrush(Colors.Red);
exampleRectangle.Fill = myBrush;

  1.2 在xaml中直接进行创建

<Rectangle Width="75" Height="75">
  <Rectangle.Fill>
    <SolidColorBrush Color="Red" />
  </Rectangle.Fill>
</Rectangle>

2 GradientBrush

渐变画刷主要包括线性渐变绘制和径向渐变画刷绘制,下面分别来介绍着两种类型。

LinearGradientBrush使用线性渐变绘制区域。 线性渐变在线条(渐变轴)中混合了两种或多种颜色。 使用 GradientStop 对象可以指定渐变中的颜色及其位置。

下面的示例使用 LinearGradientBrush 绘制 Fill 的 Rectangle 。 下图显示了绘制的矩形。

  2.1 使用C#代码进行创建

Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a LinearGradientBrush and use it to
// paint the rectangle.
LinearGradientBrush myBrush = new LinearGradientBrush();
myBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));
myBrush.GradientStops.Add(new GradientStop(Colors.Orange, 0.5));
myBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0));

exampleRectangle.Fill = myBrush;

  2.2 使用xaml进行创建

<Rectangle Width="75" Height="75">
  <Rectangle.Fill>
    <LinearGradientBrush>
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="Orange" Offset="0.5" />
      <GradientStop Color="Red" Offset="1.0" />
    </LinearGradientBrush>
  </Rectangle.Fill>
</Rectangle> 

   径向渐变画刷和这个类似,这里就不在进行单独讲述。

3 ImageBrush

这个是我们经常使用到的一种类型,比如我们经常会将一副图片来填充一个Rectangle的内部

 图三 ImageBrush

 3.1 使用C#代码创建

Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create an ImageBrush and use it to
// paint the rectangle.
ImageBrush myBrush = new ImageBrush();
myBrush.ImageSource =
    new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative));

exampleRectangle.Fill = myBrush;

3.2 使用xaml代码进行创建

<Rectangle Width="75" Height="75">
  <Rectangle.Fill>
    <ImageBrush ImageSource="sampleImages\pinkcherries.jpg"  />
  </Rectangle.Fill>
</Rectangle>

4 DrawingBrush

DrawingBrush使用绘制区域 Drawing 。 Drawing可以包含形状、图像、文本和媒体。

下面的示例使用 DrawingBrush 绘制 Fill 的 Rectangle 。 下图显示了绘制的矩形,我们来看一个具体的例子。

 图四 DrawingBrush

 我们来使用DrawingBrush来创建一个黑白相间的视觉效果图,我们来看看到底该怎样实现。

4.1 使用C#代码实现

Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a DrawingBrush and use it to
// paint the rectangle.
DrawingBrush myBrush = new DrawingBrush();

GeometryDrawing backgroundSquare =
    new GeometryDrawing(
        Brushes.White,
        null,
        new RectangleGeometry(new Rect(0, 0, 100, 100)));

GeometryGroup aGeometryGroup = new GeometryGroup();
aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 50, 50)));
aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(50, 50, 50, 50)));

LinearGradientBrush checkerBrush = new LinearGradientBrush();
checkerBrush.GradientStops.Add(new GradientStop(Colors.Black, 0.0));
checkerBrush.GradientStops.Add(new GradientStop(Colors.Gray, 1.0));

GeometryDrawing checkers = new GeometryDrawing(checkerBrush, null, aGeometryGroup);

DrawingGroup checkersDrawingGroup = new DrawingGroup();
checkersDrawingGroup.Children.Add(backgroundSquare);
checkersDrawingGroup.Children.Add(checkers);

myBrush.Drawing = checkersDrawingGroup;
myBrush.Viewport = new Rect(0, 0, 0.25, 0.25);
myBrush.TileMode = TileMode.Tile;

exampleRectangle.Fill = myBrush;

4.2 使用xaml进行创建

这种方式是我们比较常用的一种方式,我们来具体看看

<Rectangle Width="75" Height="75">
  <Rectangle.Fill>
    <DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile">
      <DrawingBrush.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="White">
            <GeometryDrawing.Geometry>
              <RectangleGeometry Rect="0,0,100,100" />
            </GeometryDrawing.Geometry>
          </GeometryDrawing>

          <GeometryDrawing>
            <GeometryDrawing.Geometry>
              <GeometryGroup>
                <RectangleGeometry Rect="0,0,50,50" />
                <RectangleGeometry Rect="50,50,50,50" />
              </GeometryGroup>
            </GeometryDrawing.Geometry>
            <GeometryDrawing.Brush>
              <LinearGradientBrush>
                <GradientStop Offset="0.0" Color="Black" />
                <GradientStop Offset="1.0" Color="Gray" />
              </LinearGradientBrush>
            </GeometryDrawing.Brush>
          </GeometryDrawing>
        </DrawingGroup>
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Rectangle.Fill>
</Rectangle>

5 VisualBrush

  这个是我们可能使用不太多并且不是非常数量的例子,我们这里对这个进行重点的解释一下,首先看看VisualBrush的解释,msdn上面的解释是使用 Visual 绘制区域,那么我们再来看看什么是Visual呢?官方的解释是:获取或设置画笔的内容,Visual 是直接继承自DependencyObject,UIElement也是直接继承自Visual,我们常见的控件都是继承自Visual,Visual可以实现动态绑定,比如我们可以在代码中这样写:

 <VisualBrush Visual="{Binding TodayPeriod}" Stretch="Fill"></VisualBrush>   

这样我们就可以把一个继承自Visual的控件(此处为TodayPeriod的一个UserControl)通过绑定的方式绑定到Visual中,我们再来看看VisualBrush这个类,首先来看一段示例代码:

                         <Border Grid.Column="1">
                                <Border.Background>
                                    <VisualBrush Stretch="Uniform">
                                        <VisualBrush.Visual>
                                            <Ellipse Fill="#003769" Opacity="0.6" Stretch="Fill" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"                                                Width="100" Height="100"></Ellipse>
                                        </VisualBrush.Visual>
                                    </VisualBrush>
                                </Border.Background>
                                <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
                                    <TextBlock FontSize="120" Text="{Binding SuccessError.Total,RelativeSource={RelativeSource TemplatedParent}}" Horizont                                         alAlignment="Center" VerticalAlignment="Center" Margin="0 0 0 -10"></TextBlock>
                                    <TextBlock FontSize="40" Text="总数" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0 -10 0 0">
</TextBlock> </StackPanel> </Border>

  这段代码是设置Border的Background为一个Ellipse,然后再在这个Ellipse上面放置两个TextBlock控件,本质上Background属性属于Brush类型,而我们的VisualBrush刚好继承自这个类型,我们来看一看VisualBrush的继承关系:

System.Object

    System.Windows.Threading.DispatcherObject

        System.Windows.DependencyObject

            System.Windows.Freezable

                System.Windows.Media.Animation.Animatable

                    System.Windows.Media.Brush

                         System.Windows.Media.TileBrush
                              System.Windows.Media.VisualBrush

  所以在上面的代码中我们可以设置Border的Background为VisualBrush,我们在很多地方都是可以使用VisualBrush的,这里需要我们平时在使用的时候不断去反思去总结。

扩展应用

  另外一个常用到VisualBrush的地方就是使用DrawingContext的时候,因为DrawingContext的第一个参数就是Brush,这里我们经常可以使用VisualBrush作为对象传递进去,比如下面的例子我们需要将WPF中的MainWindow保存为一张图片保存到本地,这个时候VisualBrush就派上用场了,我们来看下面的例子。

public static void CreateBitmapFromVisual(Visual target, string fileName)
        {
            if (target == null || string.IsNullOrEmpty(fileName))
            {
                return;
            }

            Rect bounds = VisualTreeHelper.GetDescendantBounds(target);

            RenderTargetBitmap renderTarget = new RenderTargetBitmap((Int32)bounds.Width, (Int32)bounds.Height, 96, 96, PixelFormats.Pbgra32);

            DrawingVisual visual = new DrawingVisual();

            using (DrawingContext context = visual.RenderOpen())
            {
                VisualBrush visualBrush = new VisualBrush(target);
                context.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
            }

            renderTarget.Render(visual);
            PngBitmapEncoder bitmapEncoder = new PngBitmapEncoder();
            bitmapEncoder.Frames.Add(BitmapFrame.Create(renderTarget));
            using (Stream stm = File.Create(fileName))
            {
                bitmapEncoder.Save(stm);
            }
        }

  这里传入的参数是target和fileName,前者是一个Visual,通过继承关系我们知道大部分的控件都是从Visual继承下来的,在这个方法中我们首先创建DrawingVisual对象,然后用这个对象创建drawingContext,然后使用drawingContext的DrawRectangle方法来绘制对象,这里传入的第一个参数就是包含传入target对象的VisualBrush对象,通过这个过程我们就能准确地将试图对象保存成一个完整的图片了。

  我们再以前面的Rectangle为示例来进行说明从而加深对整个知识点的掌握程度,我们首先来看下面的截图。

 图五 VisualBrush

 5.1 C#代码的实现

Rectangle exampleRectangle = new Rectangle();
exampleRectangle.Width = 75;
exampleRectangle.Height = 75;

// Create a VisualBrush and use it
// to paint the rectangle.
VisualBrush myBrush = new VisualBrush();

//
// Create the brush's contents.
//
StackPanel aPanel = new StackPanel();

// Create a DrawingBrush and use it to
// paint the panel.
DrawingBrush myDrawingBrushBrush = new DrawingBrush();
GeometryGroup aGeometryGroup = new GeometryGroup();
aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 50, 50)));
aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(50, 50, 50, 50)));
RadialGradientBrush checkerBrush = new RadialGradientBrush();
checkerBrush.GradientStops.Add(new GradientStop(Colors.MediumBlue, 0.0));
checkerBrush.GradientStops.Add(new GradientStop(Colors.White, 1.0));
GeometryDrawing checkers = new GeometryDrawing(checkerBrush, null, aGeometryGroup);
myDrawingBrushBrush.Drawing = checkers;
aPanel.Background = myDrawingBrushBrush;

// Create some text.
TextBlock someText = new TextBlock();
someText.Text = "Hello, World";
FontSizeConverter fSizeConverter = new FontSizeConverter();
someText.FontSize = (double)fSizeConverter.ConvertFromString("10pt");
someText.Margin = new Thickness(10);

aPanel.Children.Add(someText);

myBrush.Visual = aPanel;
exampleRectangle.Fill = myBrush;

5.2 使用xaml实现

<Rectangle Width="75" Height="75">
  <Rectangle.Fill>
    <VisualBrush TileMode="Tile">
      <VisualBrush.Visual>
        <StackPanel>
          <StackPanel.Background>
            <DrawingBrush>
              <DrawingBrush.Drawing>
                <GeometryDrawing>
                  <GeometryDrawing.Brush>
                    <RadialGradientBrush>
                      <GradientStop Color="MediumBlue" Offset="0.0" />
                      <GradientStop Color="White" Offset="1.0" />
                    </RadialGradientBrush>
                  </GeometryDrawing.Brush>
                  <GeometryDrawing.Geometry>
                    <GeometryGroup>
                      <RectangleGeometry Rect="0,0,50,50" />
                      <RectangleGeometry Rect="50,50,50,50" />
                    </GeometryGroup>
                  </GeometryDrawing.Geometry>
                </GeometryDrawing>
              </DrawingBrush.Drawing>
            </DrawingBrush>
          </StackPanel.Background>
          <TextBlock FontSize="10pt" Margin="10">Hello, World!</TextBlock>
        </StackPanel>
      </VisualBrush.Visual>
    </VisualBrush>
  </Rectangle.Fill>
</Rectangle>

  

 

posted @ 2016-03-03 16:33  Hello——寻梦者!  阅读(7315)  评论(1编辑  收藏  举报