zoukankan      html  css  js  c++  java
  • Winform 动态 画图 不闪

      一、问题:解决winform动态画图闪的问题,网上搜的方法,大部分都是:

    1. “this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);”,甚至直接“this.DoubleBuffered = true;”。
    2. 先 new 个Bitmap,画在Bitmap上,然后再把Bitmap画在界面上。

      凡是直接这么给人解答问题的,基本都是属于道听途说,自己没试过的。或者根本就没注意要解决的是“动态”的问题。

      二、解决方法:动态画图不闪的方法如下,先上效果图(请忽略鼠标样式,是gif录制软件的效果):

      

      三、代码:简单封了个自定义控件,用Action传入画图方法:

     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” 来画。

      四、调用的方式如下:

      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 }
  • 相关阅读:
    js语言结构小记(一)
    jquery插件:fancybox
    转载(深刻地了解到了js数组是引用类型)
    sqlite 页面结构分析
    有限状态机(FSM)的设计与实现(二)
    sqlite源码中的一个潜在Bug
    一种整数数据压缩存储的算法实现
    构建自己的内存池(一)
    sqlite Btree结构分析
    构建自己的内存池(二)
  • 原文地址:https://www.cnblogs.com/David-Huang/p/6382824.html
Copyright © 2011-2022 走看看