Winform 動態 畫圖 不閃

  1、問題:解決winform動態畫圖閃的問題,網上搜的方法,大部分都是:緩存

  1. 「this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);」,甚至直接「this.DoubleBuffered = true;」。
  2. 先 new 個Bitmap,畫在Bitmap上,而後再把Bitmap畫在界面上。

  凡是直接這麼給人解答問題的,基本都是屬於道聽途說,本身沒試過的。或者根本就沒注意要解決的是「動態」的問題。ide

  2、解決方法:動態畫圖不閃的方法以下,先上效果圖(請忽略鼠標樣式,是gif錄製軟件的效果):this

  

  3、代碼:簡單封了個自定義控件,用Action傳入畫圖方法:spa

 1 // --------------------------------------------------------------------------------------------------------------------
 2 // <copyright file="PictureBoxEx.cs" company="hyl">
 3 //   hyl
 4 // </copyright>
 5 // <summary>
 6 //   用Action傳畫圖方法。不閃。
 7 // </summary>
 8 // --------------------------------------------------------------------------------------------------------------------
 9 
10 namespace HYL
11 {
12     using System;
13     using System.Drawing;
14     using System.Windows.Forms;
15 
16     public partial class PictureBoxEx : PictureBox
17     {
18         /// <summary>
19         /// 畫圖方法
20         /// </summary>
21         private Action<Graphics> draw;
22 
23         public PictureBoxEx()
24         {
26             this.InitializeComponent();
27 
28             // 開雙緩存(用這種方法,畫圖不太複雜的話,甚至不開也不閃。。。)
29             this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
30         }
31 
32         public void Rander(Action<Graphics> Draw)
33         {
34             this.Invalidate();
35             this.draw = Draw;
36         }
37 
38         protected override void OnPaint(PaintEventArgs pe)
39         {
40             base.OnPaint(pe);
41 
42             // 畫圖
43             this.draw?.Invoke(pe.Graphics);
44         }
45     }
46 }

  重點在於要在 「OnPaint」 執行畫圖代碼,也就是說要用 「OnPaint」 裏的 「pe.Graphics」 來畫。code

  4、調用的方式以下:orm

  1 namespace HYL
  2 {
  3     using System;
  4     using System.Collections.Generic;
  5     using System.Drawing;
  6     using System.Linq;
  7     using System.Windows.Forms;
  8 
  9     public partial class Form1 : Form
 10     {
 11         List<Line> lines = new List<Line>();
 12 
 13         private bool painting;
 14 
 15         public Form1()
 16         {
 17             this.InitializeComponent();
 18         }
 19 
 20         private void panel1_MouseDown(object sender, MouseEventArgs e)
 21         {
 22             if (e.Button == MouseButtons.Left)
 23             {
 24                 // 左鍵肯定點
 25                 if (this.btnLine.Checked)
 26                 {
 27                     this.lines.Last().Points.Add(new LinePoint { IsTemp = false, Point = e.Location });
 28                     this.painting = true;
 29                 }
 30             }
 31 
 32             if (e.Button == MouseButtons.Right)
 33             {
 34                 // 右鍵中止畫圖
 35                 if (this.btnLine.Checked)
 36                 {
 37                     this.ClearEmptyLines();
 38                 }
 39 
 40                 this.painting = false;
 41                 this.btnLine.Checked = false;
 42             }
 43         }
 44 
 45         private void ClearEmptyLines()
 46         {
 47             this.lines = this.lines.Where(l => l.Points.Count > 1).ToList();
 48             if (this.lines.Count > 0)
 49             {
 50                 var lastLine = this.lines.Last();
 51                 lastLine.ClearTempPoints();
 52             }
 53         }
 54 
 55         private void panel1_MouseMove(object sender, MouseEventArgs e)
 56         {
 57             if (this.painting)
 58             {
 59                 if (this.btnLine.Checked)
 60                 {
 61                     this.PaintingLine(e);
 62                 }
 63 
 64                 this.Draw();
 65             }
 66         }
 67 
 68         private void PaintingLine(MouseEventArgs e)
 69         {
 70             var lastLine = this.lines.Last();
 71             var lastPoint = lastLine.Points.Last();
 72 
 73             if (lastPoint.IsTemp)
 74             {
 75                 lastLine.Points.Remove(lastPoint);
 76             }
 77 
 78             LinePoint newPoint = new LinePoint { IsTemp = true, Point = e.Location };
 79             lastLine.Points.Add(newPoint);
 80         }
 81 
 82         /// <summary>
 83         /// 畫圖
 84         /// </summary>
 85         private void Draw()
 86         {
 87             Action<Graphics> draw = g =>
 88                 {
 89                     Pen pen = new Pen(Color.Black, 2);
 90                     g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
 91                     g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
 92 
 93                     if (this.lines != null)
 94                     {
 95                         foreach (Line line in this.lines)
 96                         {
 97                             g.DrawLines(pen, line.GetPoints().ToArray());
 98                         }
 99                     }
100                 };
101 
102             this.pictureBoxEx1.Rander(draw);
103         }
104 
105         private void btnLine_CheckedChanged(object sender, EventArgs e)
106         {
107             if (this.btnLine.Checked)
108             {
109                 this.lines.Add(new Line());
110             }
111             else
112             {
113                 this.ClearEmptyLines();
114                 this.painting = false;
115                 this.Draw();
116             }
117         }
118     }
119 
120     public class Line : ShapeElement
121     {
122         public Line()
123         {
124             this.Points = new List<LinePoint>();
125         }
126 
127         // 線裏的點
128         public IList<LinePoint> Points { get; set; }
129 
130         // 獲取Point的集合
131         public IList<Point> GetPoints()
132         {
133             return this.Points.Select(p => p.Point).ToList();
134         }
135 
136         // 清理臨時點
137         public void ClearTempPoints()
138         {
139             this.Points = this.Points.Where(p => !p.IsTemp).ToList();
140         }
141     }
142 
143     public class LinePoint
144     {
145         public Point Point { get; set; }
146 
147         // 是否臨時點
148         public bool IsTemp { get; set; }
149     }
150 }
相關文章
相關標籤/搜索