前言
通過建立客制化元件(繼承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/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。