前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 開源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果覺得寫的還行,請點個 star 支持一下吧 歡迎前來交流探討: 企鵝群568015492 目錄 ...
前提
入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。
開源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
如果覺得寫的還行,請點個 star 支持一下吧
目錄
https://www.cnblogs.com/bfyx/p/11364884.html
準備工作
終於到文本框了,文本框將包含原文本框擴展,透明文本框,數字輸入文本框,帶邊框文本框
本文將講解透明文本框
開始
這個用到的很少,直接看代碼吧
1 // 版權所有 黃正輝 交流群:568015492 QQ:623128629 2 // 文件名稱:TextBoxTransparent.cs 3 // 創建日期:2019-08-15 16:03:49 4 // 功能描述:TextBox 5 // 項目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 6 using System; 7 using System.Collections; 8 using System.ComponentModel; 9 using System.Drawing; 10 using System.Data; 11 using System.Windows.Forms; 12 13 using System.Drawing.Imaging; 14 15 namespace HZH_Controls.Controls 16 { 17 public class TextBoxTransparent : TextBoxEx 18 { 19 #region private variables 20 21 private uPictureBox myPictureBox; 22 private bool myUpToDate = false; 23 private bool myCaretUpToDate = false; 24 private Bitmap myBitmap; 25 private Bitmap myAlphaBitmap; 26 27 private int myFontHeight = 10; 28 29 private System.Windows.Forms.Timer myTimer1; 30 31 private bool myCaretState = true; 32 33 private bool myPaintedFirstTime = false; 34 35 private Color myBackColor = Color.White; 36 private int myBackAlpha = 10; 37 38 /// <summary> 39 /// Required designer variable. 40 /// </summary> 41 private System.ComponentModel.Container components = null; 42 43 #endregion // end private variables 44 45 46 #region public methods and overrides 47 48 public TextBoxTransparent() 49 { 50 // This call is required by the Windows.Forms Form Designer. 51 InitializeComponent(); 52 // TODO: Add any initialization after the InitializeComponent call 53 54 this.BackColor = myBackColor; 55 56 this.SetStyle(ControlStyles.UserPaint, false); 57 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 58 this.SetStyle(ControlStyles.DoubleBuffer, true); 59 60 61 myPictureBox = new uPictureBox(); 62 this.Controls.Add(myPictureBox); 63 myPictureBox.Dock = DockStyle.Fill; 64 } 65 66 67 protected override void OnResize(EventArgs e) 68 { 69 70 base.OnResize(e); 71 this.myBitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);//(this.Width,this.Height); 72 this.myAlphaBitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);//(this.Width,this.Height); 73 myUpToDate = false; 74 this.Invalidate(); 75 } 76 77 78 //Some of these should be moved to the WndProc later 79 80 protected override void OnKeyDown(KeyEventArgs e) 81 { 82 base.OnKeyDown(e); 83 myUpToDate = false; 84 this.Invalidate(); 85 } 86 87 protected override void OnKeyUp(KeyEventArgs e) 88 { 89 base.OnKeyUp(e); 90 myUpToDate = false; 91 this.Invalidate(); 92 93 } 94 95 protected override void OnKeyPress(KeyPressEventArgs e) 96 { 97 base.OnKeyPress(e); 98 myUpToDate = false; 99 this.Invalidate(); 100 } 101 102 protected override void OnMouseUp(MouseEventArgs e) 103 { 104 base.OnMouseUp(e); 105 this.Invalidate(); 106 } 107 108 protected override void OnGiveFeedback(GiveFeedbackEventArgs gfbevent) 109 { 110 base.OnGiveFeedback(gfbevent); 111 myUpToDate = false; 112 this.Invalidate(); 113 } 114 115 116 protected override void OnMouseLeave(EventArgs e) 117 { 118 //found this code to find the current cursor location 119 //at http://www.syncfusion.com/FAQ/WinForms/FAQ_c50c.asp#q597q 120 121 Point ptCursor = Cursor.Position; 122 123 Form f = this.FindForm(); 124 ptCursor = f.PointToClient(ptCursor); 125 if (!this.Bounds.Contains(ptCursor)) 126 base.OnMouseLeave(e); 127 } 128 129 130 protected override void OnChangeUICues(UICuesEventArgs e) 131 { 132 base.OnChangeUICues(e); 133 myUpToDate = false; 134 this.Invalidate(); 135 } 136 137 138 //-- 139 protected override void OnGotFocus(EventArgs e) 140 { 141 base.OnGotFocus(e); 142 myCaretUpToDate = false; 143 myUpToDate = false; 144 this.Invalidate(); 145 146 147 myTimer1 = new System.Windows.Forms.Timer(this.components); 148 myTimer1.Interval = (int)win32.GetCaretBlinkTime(); // usually around 500; 149 150 myTimer1.Tick += new EventHandler(myTimer1_Tick); 151 myTimer1.Enabled = true; 152 153 } 154 155 protected override void OnLostFocus(EventArgs e) 156 { 157 base.OnLostFocus(e); 158 myCaretUpToDate = false; 159 myUpToDate = false; 160 this.Invalidate(); 161 162 myTimer1.Dispose(); 163 } 164 165 //-- 166 167 protected override void OnFontChanged(EventArgs e) 168 { 169 if (this.myPaintedFirstTime) 170 this.SetStyle(ControlStyles.UserPaint, false); 171 172 base.OnFontChanged(e); 173 174 if (this.myPaintedFirstTime) 175 this.SetStyle(ControlStyles.UserPaint, true); 176 177 178 myFontHeight = GetFontHeight(); 179 180 181 myUpToDate = false; 182 this.Invalidate(); 183 } 184 185 protected override void OnTextChanged(EventArgs e) 186 { 187 base.OnTextChanged(e); 188 myUpToDate = false; 189 this.Invalidate(); 190 } 191 192 193 protected override void WndProc(ref Message m) 194 { 195 196 base.WndProc(ref m); 197 198 // need to rewrite as a big switch 199 200 if (m.Msg == win32.WM_PAINT) 201 { 202 203 myPaintedFirstTime = true; 204 205 if (!myUpToDate || !myCaretUpToDate) 206 GetBitmaps(); 207 myUpToDate = true; 208 myCaretUpToDate = true; 209 210 if (myPictureBox.Image != null) myPictureBox.Image.Dispose(); 211 212 213 if (string.IsNullOrEmpty(this.Text) && !string.IsNullOrEmpty(this.PromptText)) 214 { 215 Bitmap bit = (Bitmap)myAlphaBitmap.Clone(); 216 Graphics g = Graphics.FromImage(bit); 217 SizeF sizet1 = g.MeasureString(this.PromptText, this.PromptFont); 218 g.DrawString(this.PromptText, this.PromptFont, new SolidBrush(PromptColor), new PointF(3, (bit.Height - sizet1.Height) / 2)); 219 g.Dispose(); 220 myPictureBox.Image = bit; 221 } 222 else 223 { 224 myPictureBox.Image = (Image)myAlphaBitmap.Clone(); 225 } 226 } 227 228 else if (m.Msg == win32.WM_HSCROLL || m.Msg == win32.WM_VSCROLL) 229 { 230 myUpToDate = false; 231 this.Invalidate(); 232 } 233 234 else if (m.Msg == win32.WM_LBUTTONDOWN 235 || m.Msg == win32.WM_RBUTTONDOWN 236 || m.Msg == win32.WM_LBUTTONDBLCLK 237 // || m.Msg == win32.WM_MOUSELEAVE ///**** 238 ) 239 { 240 myUpToDate = false; 241 this.Invalidate(); 242 } 243 244 else if (m.Msg == win32.WM_MOUSEMOVE) 245 { 246 if (m.WParam.ToInt32() != 0) //shift key or other buttons 247 { 248 myUpToDate = false; 249 this.Invalidate(); 250 } 251 } 252 253 if (m.Msg == 15 || m.Msg == 7 || m.Msg == 8) 254 { 255 base.OnPaint(null); 256 } 257 258 //System.Diagnostics.Debug.WriteLine("Pro: " + m.Msg.ToString("X")); 259 260 } 261 262 263 /// <summary> 264 /// Clean up any resources being used. 265 /// </summary> 266 protected override void Dispose(bool disposing) 267 { 268 if (disposing) 269 { 270 //this.BackColor = Color.Pink; 271 if (components != null) 272 { 273 components.Dispose(); 274 } 275 } 276 base.Dispose(disposing); 277 } 278 279 #endregion //end public method and overrides 280 281 282 #region public property overrides 283 284 public new BorderStyle BorderStyle 285 { 286 get { return base.BorderStyle; } 287 set 288 { 289 if (this.myPaintedFirstTime) 290 this.SetStyle(ControlStyles.UserPaint, false); 291 292 base.BorderStyle = value; 293 294 if (this.myPaintedFirstTime) 295 this.SetStyle(ControlStyles.UserPaint, true); 296 297 this.myBitmap = null; 298 this.myAlphaBitmap = null; 299 myUpToDate = false; 300 this.Invalidate(); 301 } 302 } 303 304 public new Color BackColor 305 { 306 get 307 { 308 return Color.FromArgb(base.BackColor.R, base.BackColor.G, base.BackColor.B); 309 } 310 set 311 { 312 myBackColor = value; 313 base.BackColor = value; 314 myUpToDate = false; 315 } 316 } 317 public override bool Multiline 318 { 319 get { return base.Multiline; } 320 set 321 { 322 if (this.myPaintedFirstTime) 323 this.SetStyle(ControlStyles.UserPaint, false); 324 325 base.Multiline = value; 326 327 if (this.myPaintedFirstTime) 328 this.SetStyle(ControlStyles.UserPaint, true); 329 330 this.myBitmap = null; 331 this.myAlphaBitmap = null; 332 myUpToDate = false; 333 this.Invalidate(); 334 } 335 } 336 337 338 #endregion //end public property overrides 339 340 341 #region private functions and classes 342 343 private int GetFontHeight() 344 { 345 Graphics g = this.CreateGraphics(); 346 SizeF sf_font = g.MeasureString("X", this.Font); 347 g.Dispose(); 348 return (int)sf_font.Height; 349 } 350 351 352 private void GetBitmaps() 353 { 354 355 if (myBitmap == null 356 || myAlphaBitmap == null 357 || myBitmap.Width != Width 358 || myBitmap.Height != Height 359 || myAlphaBitmap.Width != Width 360 || myAlphaBitmap.Height != Height) 361 { 362 myBitmap = null; 363 myAlphaBitmap = null; 364 } 365 366 367 368 if (myBitmap == null) 369 { 370 myBitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);//(Width,Height); 371 myUpToDate = false; 372 } 373 374 375 if (!myUpToDate) 376 { 377 //Capture the TextBox control window 378 379 this.SetStyle(ControlStyles.UserPaint, false); 380 381 win32.CaptureWindow(this, ref myBitmap); 382 383 this.SetStyle(ControlStyles.UserPaint, true); 384 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); 385 this.BackColor = Color.FromArgb(myBackAlpha, myBackColor); 386 387 } 388 //-- 389 390 391 392 Rectangle r2 = new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height); 393 ImageAttributes tempImageAttr = new ImageAttributes(); 394 395 396 //Found the color map code in the MS Help 397 398 ColorMap[] tempColorMap = new ColorMap[1]; 399 tempColorMap[0] = new ColorMap(); 400 tempColorMap[0].OldColor = Color.FromArgb(255, myBackColor); 401 tempColorMap[0].NewColor = Color.FromArgb(myBackAlpha, myBackColor); 402 403 tempImageAttr.SetRemapTable(tempColorMap); 404 405 if (myAlphaBitmap != null) 406 myAlphaBitmap.Dispose(); 407 408 409 myAlphaBitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);//(Width,Height); 410 411 Graphics tempGraphics1 = Graphics.FromImage(myAlphaBitmap); 412 413 tempGraphics1.DrawImage(myBitmap, r2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, GraphicsUnit.Pixel, tempImageAttr); 414 415 tempGraphics1.Dispose(); 416 417 //---- 418 419 if (this.Focused && (this.SelectionLength == 0)) 420 { 421 Graphics tempGraphics2 = Graphics.FromImage(myAlphaBitmap); 422 if (myCaretState) 423 { 424 //Draw the caret 425 Point caret = this.findCaret(); 426 Pen p = new Pen(this.ForeColor, 3); 427 tempGraphics2.DrawLine(p, caret.X + 2, caret.Y + 0, caret.X + 2, caret.Y + myFontHeight); 428 tempGraphics2.Dispose(); 429 } 430 431 } 432 433 434 435 } 436 437 438 439 private Point findCaret() 440 { 441 /* Find the caret translated from code at 442 * http://www.vb-helper.com/howto_track_textbox_caret.html 443 * 444 * and 445 * 446 * http://www.microbion.co.uk/developers/csharp/textpos2.htm 447 * 448 * Changed to EM_POSFROMCHAR 449 * 450 * This code still needs to be cleaned up and debugged 451 * */ 452 453 Point pointCaret = new Point(0); 454 int i_char_loc = this.SelectionStart; 455 IntPtr pi_char_loc = new IntPtr(i_char_loc); 456 457 int i_point = win32.SendMessage(this.Handle, win32.EM_POSFROMCHAR, pi_char_loc, IntPtr.Zero); 458 pointCaret = new Point(i_point); 459 460 if (i_char_loc == 0) 461 { 462 pointCaret = new Point(0); 463 } 464 else if (i_char_loc >= this.Text.Length) 465 { 466 pi_char_loc = new IntPtr(i_char_loc - 1); 467 i_point = win32.SendMessage(this.Handle, win32.EM_POSFROMCHAR, pi_char_loc, IntPtr.Zero); 468 pointCaret = new Point(i_point); 469 470 Graphics g = this.CreateGraphics(); 471 String t1 = this.Text.Substring(this.Text.Length - 1, 1) + "X"; 472 SizeF sizet1 = g.MeasureString(t1, this.Font); 473 SizeF sizex = g.MeasureString("X", this.Font); 474 g.Dispose(); 475 int xoffset = (int)(sizet1.Width - sizex.Width); 476 pointCaret.X = pointCaret.X + xoffset; 477 478 if (i_char_loc == this.Text.Length) 479 { 480 String slast = this.Text.Substring(Text.Length - 1, 1); 481 if (slast == "\n") 482 { 483 pointCaret.X = 1; 484 pointCaret.Y = pointCaret.Y + myFontHeight; 485 } 486 } 487 488 } 489 490 491 492 return pointCaret; 493 } 494 495 496 private void myTimer1_Tick(