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 }
实现效果
作者:Jeremy.Wu
出处:https://www.cnblogs.com/jeremywucnblog/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。