前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 
<https://gitee.com/kwwwvagaa/net_winform_custom_control>
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492  <https://shang.qq.com/wpa/qunwpa? 
idkey=6e08741ef16fe53bf0314c1c9e336c4f626047943a8b76bac062361bab6b4f8d>
目录
https://www.cnblogs.com/bfyx/p/11364884.html 
<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 location119 //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 overrides283 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 at442  * 
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_POSFROMCHAR449  * 450  * This code still needs to be cleaned up 
and debugged451  * */ 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(object sender, 
EventArgs e)497  { 498 //Timer used to turn caret on and off for focused control
499 500 myCaretState = !myCaretState; 501 myCaretUpToDate = false; 502 this
.Invalidate();503  } 504 505 506 private class uPictureBox : PictureBox 507  { 
508 public uPictureBox() 509  { 510 this.SetStyle(ControlStyles.Selectable, 
false); 511 this.SetStyle(ControlStyles.UserPaint, true); 512 this
.SetStyle(ControlStyles.AllPaintingInWmPaint,true); 513 this
.SetStyle(ControlStyles.DoubleBuffer,true); 514 515 this.Cursor = null; 516 this
.Enabled =true; 517 this.SizeMode = PictureBoxSizeMode.Normal; 518 519  } 520 
521 522 523 524 //uPictureBox 525 protected override void WndProc(ref Message m)
526  { 527 if (m.Msg == win32.WM_LBUTTONDOWN 528 || m.Msg == 
win32.WM_RBUTTONDOWN529 || m.Msg == win32.WM_LBUTTONDBLCLK 530 || m.Msg == 
win32.WM_MOUSELEAVE531 || m.Msg == win32.WM_MOUSEMOVE) 532  { 533 //Send the 
above messages back to the parent control 534 win32.PostMessage(this
.Parent.Handle, (uint)m.Msg, m.WParam, m.LParam); 535  } 536 537 else if (m.Msg 
== win32.WM_LBUTTONUP) 538  { 539 //?? for selects and such 540 this
.Parent.Invalidate();541  } 542 543 544 base.WndProc(ref m); 545  } 546 547 548 
}// End uPictureBox Class 549 550 551 #endregion // end private functions and 
classes 552 553 554 #region Component Designer generated code 555 /// <summary> 
556 /// Required method for Designer support - do not modify 557 /// the 
contents of this method with the code editor.558 /// </summary> 559 private void
 InitializeComponent()560  { 561 components = new 
System.ComponentModel.Container();562  } 563 #endregion 564 565 566 #region New 
Public Properties567 568  [ 569 Category("Appearance"), 570 Description("The 
alpha value used to blend the control's background. Valid values are 0 through 
255."), 571 Browsable(true), 572  
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)573 574 
 ]575 public int BackAlpha 576  { 577 get { return myBackAlpha; } 578 set 579  {
580 int v = value; 581 if (v > 255) 582 v = 255; 583 myBackAlpha = v; 584 
myUpToDate =false; 585  Invalidate(); 586  } 587  } 588 589 #endregion 590 591 
592 593 } // End AlphaTextBox Class 594 } View Code 
 
用处及效果
用到的比较少,你高兴就用,哈哈
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 
<https://gitee.com/kwwwvagaa/net_winform_custom_control> 点个星 星吧
热门工具 换一换