C# - VS2019通過重寫pictureBox實現簡單的桌面截圖功能


前言

通過創建客制化組件(繼承pictureBox),新增屬性和構造方法,實現屏幕截圖時需要用到的功能點。再通過監控鼠標按下、移動和釋放,來獲取起始點區域。最后通過操作BMP圖像,實現截圖的新增、修改和保存功能。

核心點

  • 組件的創建(重寫)
  • 鼠標監控事件
  • BMP圖像重繪

核心代碼

  1     /// <summary>
  2     /// 重寫圖片控件
  3     /// </summary>
  4     [Serializable]
  5     public partial class HexPictureBox : PictureBox
  6     {
  7         #region 屬性和構造函數
  8 
  9         public HexPictureBox()
 10         {
 11             InitializeComponent();
 12         }
 13 
 14         private bool startDraw = false;
 15 
 16         public bool StartDraw
 17         {
 18             get { return startDraw; }
 19 
 20             set { startDraw = value; }
 21         }
 22 
 23         private List<HLine> lineHistory = new List<HLine>();
 24 
 25         public List<HLine> LineHistory
 26         {
 27             get { return lineHistory; }
 28 
 29             private set { lineHistory = value; }
 30         }
 31 
 32         private HLine curLine = new HLine() { LineColor = Color.White, LineWidth = 2, PointList = new List<Point>() };
 33 
 34         /// <summary>
 35         /// 當前繪制線
 36         /// </summary>
 37         public HLine CurLine
 38         {
 39             get { return curLine; }
 40 
 41             private set { curLine = value; }
 42         }
 43 
 44         private HRectangle curRect = new HRectangle() { LineColor = Color.White, LineWidth = 2, Start = new Point(0, 0), End = new Point(0, 0) };
 45 
 46         /// <summary>
 47         /// 當前需要繪制的矩形
 48         /// </summary>
 49         public HRectangle CurRect
 50         {
 51             get { return curRect; }
 52 
 53             set { curRect = value; }
 54         }
 55 
 56         private List<HRectangle> rectHistory = new List<HRectangle>();
 57 
 58         public List<HRectangle> RectHistory
 59         {
 60             get { return rectHistory; }
 61 
 62             private set { rectHistory = value; }
 63         }
 64 
 65         private DrawType drawTypes = DrawType.None;
 66 
 67         public DrawType DrawTypes
 68         {
 69             get { return drawTypes; }
 70 
 71             set { drawTypes = value; }
 72         }
 73 
 74         #endregion
 75 
 76         #region 繪制功能
 77 
 78         protected override void OnPaint(PaintEventArgs pe)
 79         {
 80             base.OnPaint(pe);
 81             Graphics g = pe.Graphics;
 82             DrawHistory(g);
 83             //繪制當前線
 84             if (startDraw && this.curLine.PointList != null && this.curLine.PointList.Count > 0)
 85             {
 86                 DrawLine(g, this.curLine);
 87             }
 88             if (startDraw && this.curRect.Start != null && this.curRect.End != null && this.curRect.Start != this.curRect.End)
 89             {
 90                 DrawRectangle(g, this.curRect);
 91             }
 92         }
 93 
 94         public void DrawHistory(Graphics g)
 95         {
 96             //繪制線歷史記錄
 97             if (LineHistory != null)
 98             {
 99                 foreach (HLine lh in LineHistory)
100                 {
101                     if (lh.PointList.Count > 10)
102                     {
103                         DrawLine(g, lh);
104                     }
105                 }
106             }
107             //繪制矩形歷史記錄
108             if (RectHistory != null)
109             {
110                 foreach (HRectangle lh in RectHistory)
111                 {
112                     if (lh.Start != null && lh.End != null && lh.Start != lh.End)
113                     {
114                         DrawRectangle(g, lh);
115                     }
116                 }
117             }
118         }
119 
120         /// <summary>
121         /// 繪制線
122         /// </summary>
123         /// <param name="g"></param>
124         /// <param name="line"></param>
125         private void DrawLine(Graphics g, HLine line)
126         {
127             g.SmoothingMode = SmoothingMode.AntiAlias;
128             using (Pen p = new Pen(line.LineColor, line.LineWidth))
129             {
130                 //設置起止點線帽  
131                 p.StartCap = LineCap.Round;
132                 p.EndCap = LineCap.Round;
133 
134                 //設置連續兩段的聯接樣式  
135                 p.LineJoin = LineJoin.Round;
136                 g.DrawCurve(p, line.PointList.ToArray()); //畫平滑曲線  
137             }
138         }
139 
140         /// <summary>
141         /// 繪制矩形
142         /// </summary>
143         /// <param name="g"></param>
144         /// <param name="rect"></param>
145         private void DrawRectangle(Graphics g, HRectangle rect)
146         {
147             g.SmoothingMode = SmoothingMode.AntiAlias;
148             using (Pen p = new Pen(rect.LineColor, rect.LineWidth))
149             {
150                 //設置起止點線帽  
151                 p.StartCap = LineCap.Round;
152                 p.EndCap = LineCap.Round;
153 
154                 //設置連續兩段的聯接樣式  
155                 p.LineJoin = LineJoin.Round;
156                 g.DrawRectangle(p, rect.Start.X, rect.Start.Y, rect.End.X - rect.Start.X, rect.End.Y - rect.Start.Y); //畫平滑曲線  
157             }
158         }
159 
160         public void Earser(Point p0)
161         {
162             for (int i = lineHistory.Count - 1; i >= 0; i--)
163             {
164                 HLine line = lineHistory[i];
165                 bool flag = false;
166                 foreach (Point p1 in line.PointList)
167                 {
168                     double distance = GetDistance(p0, p1);
169                     if (Math.Abs(distance) < 6)
170                     {
171                         //需要刪除
172                         flag = true;
173                         break;
174                     }
175 
176                 }
177                 if (flag)
178                 {
179                     lineHistory.RemoveAt(i);
180                 }
181             }
182             //擦除矩形
183             for (int i = rectHistory.Count - 1; i >= 0; i--)
184             {
185                 HRectangle rect = rectHistory[i];
186 
187                 if (p0.X > rect.Start.X && p0.X < rect.End.X && p0.Y > rect.Start.Y && p0.Y < rect.End.Y)
188                 {
189 
190                     rectHistory.RemoveAt(i);
191                 }
192             }
193         }
194 
195         /// <summary>
196         /// 獲取兩點之間的距離
197         /// </summary>
198         /// <param name="p0"></param>
199         /// <param name="p1"></param>
200         /// <returns></returns>
201         private double GetDistance(Point p0, Point p1)
202         {
203             return Math.Sqrt(Math.Pow((p0.X - p1.X), 2) + Math.Pow((p0.Y - p1.Y), 2));
204         }
205 
206         #endregion
207 
208         #region 鼠標事件響應
209 
210         /// <summary>
211         /// 鼠標移動時設置點
212         /// </summary>
213         /// <param name="p"></param>
214         public void SetPointAndRefresh(Point p)
215         {
216             if (this.drawTypes == DrawType.Line)
217             {
218                 this.curLine.PointList.Add(p);
219             }
220             if (this.drawTypes == DrawType.Rect)
221             {
222                 this.curRect.End = p;
223             }
224             this.Refresh();
225 
226         }
227 
228         public void OnMouseDown(Point p)
229         {
230             if (this.DrawTypes == DrawType.Line)
231             {
232                 this.CurLine.PointList.Clear();
233                 this.CurLine.PointList.Add(p);
234             }
235             if (this.DrawTypes == DrawType.Rect)
236             {
237                 this.CurRect.Start = p;
238             }
239         }
240 
241         public void OnMouseUp(Point p)
242         {
243             if (this.DrawTypes == DrawType.Line)
244             {
245                 //右鍵起來時,停止繪圖,並寫入歷史記錄
246                 Point[] pCopy = this.CurLine.PointList.ToArray();
247                 List<Point> lstPoint = new List<Point>();
248                 lstPoint.AddRange(pCopy);
249                 this.LineHistory.Add(new HLine() { LineColor = this.CurLine.LineColor, LineWidth = this.CurLine.LineWidth, PointList = lstPoint });
250                 this.CurLine.PointList.Clear();
251             }
252             if (this.DrawTypes == DrawType.Rect)
253             {
254                 this.RectHistory.Add(new HRectangle() { LineColor = this.CurRect.LineColor, LineWidth = this.CurRect.LineWidth, Start = this.CurRect.Start, End = this.CurRect.End });
255                 this.CurRect.Start = new Point(0, 0);
256                 this.CurRect.End = new Point(0, 0);
257             }
258             if (this.DrawTypes == DrawType.Earser)
259             {
260                 //如果是橡皮擦功能
261                 this.Earser(p);
262                 this.Refresh();
263             }
264         }
265 
266         #endregion
267 
268         #region 初始設置
269 
270         public void SetPen(Color c)
271         {
272             this.DrawTypes = DrawType.Line;
273             this.CurLine.LineWidth = 2;
274             this.CurLine.LineColor = c;
275             //通過圖片的句柄獲取指針
276             this.Cursor = new Cursor(global::ScreenShot.Properties.Resources.pen.GetHicon());
277             this.StartDraw = true;
278         }
279 
280         public void SetLightPen()
281         {
282             this.StartDraw = true;
283             this.CurLine.LineWidth = 6;
284             this.DrawTypes = DrawType.Line;
285             this.Cursor = new Cursor(global::ScreenShot.Properties.Resources.lightpen.GetHicon());
286             this.CurLine.LineColor = Color.FromArgb(100, Color.Yellow);
287         }
288 
289         public void SetRectangle()
290         {
291             this.StartDraw = true;
292             this.CurRect.LineWidth = 3;
293             this.DrawTypes = DrawType.Rect;
294             this.CurRect.LineColor = Color.Red;
295             this.Cursor = Cursors.Cross;
296         }
297 
298         public void SetEarser()
299         {
300             this.DrawTypes = DrawType.Earser;//橡皮檫
301             this.Cursor = new Cursor(global::ScreenShot.Properties.Resources.easer1.GetHicon());
302         }
303 
304         public void SetDefault()
305         {
306             this.Cursor = Cursors.Default;
307             this.StartDraw = false;
308         }
309 
310         #endregion
311     }
View Code

實現效果

 

  作者:Jeremy.Wu
  出處:https://www.cnblogs.com/jeremywucnblog/
  本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM