前言
通过创建客制化组件(继承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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。