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

简介: 原文:在WPF中自定义你的绘制(五)                                     在WPF中自定义你的绘制(五)                                                                   周银辉将我们的绘制转变为画刷WPF中的画刷比GDI+中要强大得多,除了常用的实心画刷、渐变画刷外,还支持更多的平铺画刷,这包括DrawingBrush、ImageBrush、VisualBrush,其中DrawingBrush使得我们可以将自定义的绘制用于任何可以使用普通画刷的地方。
原文: 在WPF中自定义你的绘制(五)

                                     在WPF中自定义你的绘制(五)
                                                                   周银辉

将我们的绘制转变为画刷

WPF中的画刷比GDI+中要强大得多,除了常用的实心画刷、渐变画刷外,还支持更多的平铺画刷,这包括DrawingBrush、ImageBrush、VisualBrush,其中DrawingBrush使得我们可以将自定义的绘制用于任何可以使用普通画刷的地方。
比如下面的代码,我们将自定义一个椭圆和一个矩形,然后将它们合并成一个图形并将

改图形用作窗口的背景画刷:

img_a6339ee3e57d1d52bc7d02b338e15a60.gif public  Window1()
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif        
img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif {
img_33d02437d135341f0800e3d415312ae8.gif            InitializeComponent();
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif            
//background
img_33d02437d135341f0800e3d415312ae8.gif
            EllipseGeometry ellipse = new EllipseGeometry(new Point(5050), 5020);
img_33d02437d135341f0800e3d415312ae8.gif            RectangleGeometry rect 
= new RectangleGeometry(new Rect(50505020), 55);
img_33d02437d135341f0800e3d415312ae8.gif            PathGeometry combin 
= Geometry.Combine(ellipse, rect, GeometryCombineMode.Xor, null);
img_33d02437d135341f0800e3d415312ae8.gif            GeometryDrawing drawing 
= new GeometryDrawing(Brushes.LightBlue, new Pen(Brushes.Green, 2), combin);
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif            DrawingBrush background 
= new DrawingBrush(drawing);
img_33d02437d135341f0800e3d415312ae8.gif            
this.Background = background;
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif
img_05dd8d549cff04457a6366b0a7c9352a.gif        }
运行效果如下:
customPaint_DrawingBrush1.png


也许将整个图形填充于整个区域并不是我们想要的结果,没关系,我们可以通过设置视口(Viewport)和平铺方式(TileMode)来调整图形的平铺效果。
customPaint_DrawingBrush2.png
Viewport为我们指示了如何将图形投射到绘制表面,如果我们将绘制表面的左上角定义为(0,0),右下角定义我(1,1),那么可以设置一个相当与该值的矩形(Rect)来指示我们的图形应该被投射到哪里。比如Rect(0,0,0.5,0.5)则表示在绘制表面的左上角开始的长宽均为绘制表面1/2的矩形区域。这样的矩形Rect(0,0,0.5,0.5)就是我们所说的视口(这与3D中的视口类似)。所以要得到上图的效果,我们只需要这样设置我们的DrawingBrush就可以了:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif background.Viewport  =   new  Rect( 0 0 0.15 0.15 );
img_a6339ee3e57d1d52bc7d02b338e15a60.gifbackground.TileMode 
=  TileMode.Tile;

此外,DrawingBrush还有一个很有意思的属性ViewBox(继承于TileBrush),它指示了只取图形中的哪一部分作为观察区域(这与Clip不同),它的定义方式与Viewport类似,但它不是相对于绘制表面而是相当于我们的图形的。
SDK中是这样解释ViewBox的:
customPaint_DrawingBrush3.png
参考下面的代码,我们仅仅取了整个绘制的图形的1/4(整个图形的左下部分)并将其作为窗口的的背景画刷:
img_a6339ee3e57d1d52bc7d02b338e15a60.gif   public  Window1()
img_405b18b4b6584ae338e0f6ecaf736533.gifimg_1c53668bcee393edac0d7b3b3daff1ae.gif        
img_a76e9bb6ed00cf1c9c9f4ee2f04b558b.gif {
img_33d02437d135341f0800e3d415312ae8.gif            InitializeComponent();
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif            
//background
img_33d02437d135341f0800e3d415312ae8.gif
            EllipseGeometry ellipse = new EllipseGeometry(new Point(5050), 5020);
img_33d02437d135341f0800e3d415312ae8.gif            RectangleGeometry rect 
= new RectangleGeometry(new Rect(50505020), 55);
img_33d02437d135341f0800e3d415312ae8.gif            PathGeometry combin 
= Geometry.Combine(ellipse, rect, GeometryCombineMode.Xor, null);
img_33d02437d135341f0800e3d415312ae8.gif            GeometryDrawing drawing 
= new GeometryDrawing(Brushes.LightBlue, new Pen(Brushes.Green, 2), combin);
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif            DrawingBrush background 
= new DrawingBrush(drawing);
img_33d02437d135341f0800e3d415312ae8.gif            background.Viewbox 
= new Rect(0.50.50.50.5);
img_33d02437d135341f0800e3d415312ae8.gif            
this.Background = background;
img_33d02437d135341f0800e3d415312ae8.gif
img_33d02437d135341f0800e3d415312ae8.gif
img_05dd8d549cff04457a6366b0a7c9352a.gif        }

效果图如下:
customPaint_DrawingBrush4.png

此外,值得一提的是,Viewport和Viewbox除了使用相对值外,你也可以使用绝对坐标值,不过你需要将ViewportUnits属性和ViewboxUnit属性由BrushMappingMode.RelativeToBoundingBox修改为BrshMappingMode.Absolute。

目录
相关文章
|
C# 虚拟化 索引
【WPF】UI虚拟化之------自定义VirtualizingWrapPanel
原文:【WPF】UI虚拟化之------自定义VirtualizingWrapPanel 前言 前几天QA报了一个关于OOM的bug,在排查的过程中发现,ListBox控件中被塞入了过多的Item,而ListBox又定义了两种样式的ItemsPanelTemplate。
2547 0
|
C# 数据安全/隐私保护
【WPF】右下角弹出自定义通知样式(Notification)——简单教程
原文:【WPF】右下角弹出自定义通知样式(Notification)——简单教程 1.先看效果 2.实现 1.主界面是MainWindow 上面就只摆放一个Button即可。
3540 1
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
|
C#
WPF 自定义可拖动标题栏
WPF 自定义可拖动标题栏
185 0
|
开发框架 前端开发 C#
使用WPF开发自定义用户控件,以及实现相关自定义事件的处理
使用WPF开发自定义用户控件,以及实现相关自定义事件的处理
|
前端开发 C# 图形学
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了。用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架。依赖属性(DependencyProperty)是为用户控件提供可支持双向绑定的必备技巧之一,同样用处也非常广泛。
1361 0
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
|
C# C++ 数据可视化
WPF Calendar 日历控件 样式自定义
原文:WPF Calendar 日历控件 样式自定义 粗略的在代码上做了些注释 blend 生成出来的模版 有的时候 会生成 跟 vs ui界面不兼容的代码 会导致可视化设计界面 报错崩溃掉 但是确不影响 程序的编译运行 这个样式表 在vs 里会提示动画不兼容 Foreground属性 报错 ...
1964 1
|
C#
WPF 控件自定义背景
<!--控件要设置尺寸的话,设置的尺寸必须比下面的图形的尺寸要小,不然显示不开--> <Label Content="直角测试" Width="90" Height="90" HorizontalContentAlignment="Center" Vert...
1111 0
|
C#
WPF开发-Label自定义背景-Decorator
首先在App.xaml文件当中添加样式和模板
2148 0