• WPF DrawingVisual详解


    在WPF中,如果需要绘制大量图形元素,并且对性能要求严苛的话,最好使用DrawingVisual,当然,你也可以选用

    Path类和比Path类更轻量级的Geometry(几何形状)来实现你的需求,但是开销会比DrawingVisual来的大。


    DrawingVisual继承自ContainerVisual,该类有一个RenderOpen方法,返回一个可用于定义可视化内容的DrawingContext对象,绘制完毕后需要调用DrawingContext.Close()方法来结束绘图。


    DrawingContext中有各种绘图的方法,包括DrawLine,DrawRectangle,DrawText等等,今天我们举一个较复杂的例子DrawGeometry().


    在此之前,我们需要做一些准备工作:参考自<WPF编程宝典>第三部分--图画和动画--330页

    1.为元素调用AddVisualChild()和AddLogicalChild()方法来注册可视化元素

    2.重写VisualChildrenCount属性和重写GetVisualChild()方法,本质上是劫持了那个元素,如果使用一些能包含控件的例如Panel,Window,则这些panel,window中除了DrawingVisual,其他的控件将不再可见。


    代码如下:


     public partial class MainWindow : Window
        {
            private DrawingVisual _drawingVisual = new DrawingVisual();
            public MainWindow()
            {
                InitializeComponent();
                this.AddVisualChild(_drawingVisual);
                var dc = _drawingVisual.RenderOpen();
                PathFigure pthFigure = new PathFigure();
                pthFigure.IsClosed = false;   //是否封闭
                pthFigure.IsFilled = false;   //是否填充
                pthFigure.StartPoint = new Point(10, 100);
    
                System.Windows.Point Point1 = new System.Windows.Point(10, 100);
                System.Windows.Point Point2 = new System.Windows.Point(100, 200);
                System.Windows.Point Point3 = new System.Windows.Point(200, 30);
                System.Windows.Point Point4 = new System.Windows.Point(250, 200);
                System.Windows.Point Point5 = new System.Windows.Point(200, 150);
    
                PolyLineSegment plineSeg = new PolyLineSegment();
                plineSeg.Points.Add(Point1);
                plineSeg.Points.Add(Point2);
                plineSeg.Points.Add(Point3);
                plineSeg.Points.Add(Point4);
                plineSeg.Points.Add(Point5);
    
                PathSegmentCollection myPathSegmentCollection = new PathSegmentCollection();
                myPathSegmentCollection.Add(plineSeg);
    
                pthFigure.Segments = myPathSegmentCollection;
    
                PathFigureCollection pthFigureCollection = new PathFigureCollection();
    
                pthFigureCollection.Add(pthFigure);
    
                PathGeometry pthGeometry = new PathGeometry();
    
                pthGeometry.Figures = pthFigureCollection;
    
    
                dc.DrawGeometry(Brushes.White, new Pen(Brushes.White,1), pthGeometry);
               
                dc.Close();
            }
            //必须重载这两个方法,不然是画不出来的
            // 重载自己的VisualTree的孩子的个数,由于只有一个DrawingVisual,返回1
            protected override int VisualChildrenCount
            {
                get { return 1; }
            }
    
            // 重载当WPF框架向自己要孩子的时候,返回返回DrawingVisual
            protected override Visual GetVisualChild(int index)
            {
                if (index == 0)
                    return _drawingVisual;
    
                throw new IndexOutOfRangeException();
            }
        }


    WPF还为DrawingVisual提供了可以命中测试,用以实现点击,拖拽等功能,主要是依靠方法VisualTreeHelper.HitTest,

    我尝试着用了下,这个方法比较消耗性能,而且只适合那种面积较大的按钮,方块,一点就中的情况,如果是一条线或者一个小点,则很难点击命中。我会建议使用Path,自带了各种鼠标事件。这个在WPF编程宝典中有详解,不再赘述!


    如果既需要大量的图形,又需要能支持鼠标事件的控件,我建议的做法是,在Grid中放置Panel用于绘制DrawingVisual,然后在放置Canvas来内置各种控件。Panel和Canvas重叠起来。





    未完待续。。。。。。。。





  • 相关阅读:
    idea设置全局ignore
    win 2012 安装mysql 5.7.20 及报错 This application requires Visual Studio 2013 Redistributable. Please ins
    win 2012 安装mysql 5.7.20 及报错 This application requires Visual Studio 2013 Redistr
    kafka 删除 topic
    java编译中出现了Exception in thread “main" java.lang.UnsupportedClassVersionError
    Centos中使用yum安装java时,没有jps的问题的解决
    Spring 整合Junit
    Spring纯注解配置
    Spring 基于注解的 IOC 配置
    打印java系统的信息
  • 原文地址:https://www.cnblogs.com/kevinWu7/p/10163554.html
Copyright © 2020-2023  润新知