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