WPF 使用DrawingVisual和DispatchFrame快速提升繪圖速度
阿新 • • 發佈:2020-08-19
參考資料:
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 overridevoid 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(); } }