1. 程式人生 > 實用技巧 >WPF 使用DrawingVisual和DispatchFrame快速提升繪圖速度

WPF 使用DrawingVisual和DispatchFrame快速提升繪圖速度

參考資料:

https://www.jianshu.com/p/d308641498aa

https://zhuanlan.zhihu.com/p/37167062

這是一個來自很久以前的程式碼

通過DrawingVisual和DispatchFrame快速提升繪圖速度

截圖2

最主要的是繼承DrawingVisual和修改canvas。

  public class BaseCanvas : Canvas
    {
        public ObservableCollection<BaseDrawVisual> Visuals
        {
            get;
            
private set; } ScaleTransform Scale; public BaseCanvas() { Visuals = new ObservableCollection<BaseDrawVisual>(); Scale = new ScaleTransform(); this.RenderTransform = Scale; } double sc = 1; protected override
void OnMouseWheel(MouseWheelEventArgs e) { // base.OnMouseWheel(e); if(e.Delta>0) { sc += 0.5; } else { sc -= 0.5; } if (sc > 48) sc = 48;
if (sc < 0.5) sc = 0.5; Scale.CenterX = 0; Scale.CenterY = 0; Scale.ScaleX = sc; Scale.ScaleY = sc; Console.WriteLine("sc:"+sc); // base.OnMouseWheel(e); } protected override Visual GetVisualChild(int index) { return Visuals[index]; } protected override int VisualChildrenCount => Visuals.Count; public void AddVisual(BaseDrawVisual drawVisual) { Visuals.Add(drawVisual); AddVisualChild(drawVisual); AddLogicalChild(drawVisual); } public void DelAllVisual() { foreach (var item in Visuals) { RemoveVisualChild(item); RemoveLogicalChild(item); } Visuals.Clear(); } }

部分元素

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace DrawCanvas
{
    public class RectByLineDrawVisual : BaseDrawVisual //也可以直接繼承DrawingVisual
    {
        public RectByLineDrawVisual()
        {

        }


        public RectByLineDrawVisual(double X, double Y, double width, double height, double rectW, double rectH)
        {
            this.LocationX = X;
            this.LocationY = Y;
            this.DrawWidth = width;
            this.DrawHeight = height;
            this.RectWidth = rectW;
            this.RectHeight = rectH;

            MaxItems = (int)(DrawHeight / RectHeight * DrawWidth / RectWidth);
            SelectItem = new List<int[]>();
        }


        public double DrawHeight { get; set; }
        public double DrawWidth { get; set; }
        public double RectHeight { get; set; }
        public double RectWidth { get; set; }
        public double LocationX { get; set; }
        public double LocationY { get; set; }

        public Pen DrawPen = DrawSetting.Instance.DrawPen;

        public override void Draw()
        {
            DrawPen.Freeze();
            using (var BaseDrawing = this.RenderOpen())
            {
                GeometryGroup gp = new GeometryGroup();
                gp.Children.Add(new RectangleGeometry(new Rect(LocationX, LocationY, DrawWidth, DrawHeight)));

                for (double x = LocationX; x < LocationX + DrawWidth; x += RectWidth)
                {
                    gp.Children.Add(
                      new LineGeometry(new Point(x, LocationY), new Point(x, LocationY+DrawHeight)));
                   
                }
                for (double y = LocationY; y < LocationY + DrawHeight; y += RectHeight)
                {
                    gp.Children.Add(
                   new LineGeometry(new Point(LocationX, y), new Point(LocationX+DrawWidth, y)));
                }
                BaseDrawing.DrawDrawing(new GeometryDrawing(DrawColor, DrawPen, gp));
            }
        }
    }
}

主介面cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();


        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //   Draw();

            e.Handled = true;
        }
        Random GetRandom = new Random();
        int k = 0;
        private void Draw()
        {
            draw.DelAllVisual();
            for (double i = 0; i < draw.ActualWidth; i +=100)
            {
                for (double j = 0; j < draw.ActualHeight; j += 100)
                {
                    //NormColor=new SolidColorBrush(Color.FromRgb((byte)GetRandom.Next(1,255), (byte)GetRandom.Next(1, 255), (byte)GetRandom.Next(1, 255))) 
                    //draw.AddVisual(new RectByLineDrawVisual(i, j, 80, draw.ActualHeight, 5, 5));
                    draw.AddVisual(new RectDrawVisual(i, j, 100, 100, 4, 4));
                }
            }
        }

        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            // Draw();

        }
        private void ProcessMsgs()
        {

            DoEvents();
        }
        public void DoEvents()
        {
            DispatcherFrame frame = new DispatcherFrame();
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
                new DispatcherOperationCallback(ExitFrames), frame);
            Dispatcher.PushFrame(frame);
        }

        public object ExitFrames(object f)
        {
            ((DispatcherFrame)f).Continue = false;

            return null;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Draw();
            for (int i = 0; i < draw.Visuals.Count; i++)
            {

                draw.Visuals[i].Draw();
                if (i % 10 == 0)
                    ProcessMsgs();
            }
            //   this.IsEnabled = true;
        }
        DispatcherTimer Timer = new DispatcherTimer();
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (Timer.IsEnabled)
            {
                Timer.Stop();
                return;
            }
            Timer.Interval = TimeSpan.FromMilliseconds(50);
            Timer.Tick += Timer_Tick;
            Timer.Start();

        }

        private void Timer_Tick(object sender, EventArgs e)
        {
          Changed1();
            //Changed2();
        }
        void Changed1()
        {
            for (int i = 0; i < draw.Visuals.Count;)
            {
                var index = GetRandom.Next(0, draw.Visuals.Count);

                var item = draw.Visuals[index] as RectDrawVisual;
                //  item.SelectItem.Clear();
                var k = new[] { GetRandom.Next(0, 20), GetRandom.Next(0, 20) };
                if (!item.SelectItem.Contains(k))
                    item.SelectItem.Add(k);
                else
                    item.SelectItem.Remove(k);
                item.SelectItemBackGround = new SolidColorBrush(Colors.Red);//new SolidColorBrush(Color.FromRgb((byte)GetRandom.Next(1, 255), (byte)GetRandom.Next(1, 255), (byte)GetRandom.Next(1, 255)));
                item.Draw();
                ProcessMsgs();
                Console.WriteLine(index);
                if (i == draw.Visuals.Count - 1)
                {
                    i = 0;
                    ProcessMsgs();
                    continue;

                }
                else
                    i++;
            }
        }
        void Changed2()
        {
            var index = GetRandom.Next(0, draw.Visuals.Count - 1);
            var item = draw.Visuals[index];
            item.DrawColor = new SolidColorBrush(Color.FromRgb((byte)GetRandom.Next(1, 255), (byte)GetRandom.Next(1, 255), (byte)GetRandom.Next(1, 255)));
            item.Draw();
           // ProcessMsgs();
        }
    }

下載程式碼