前提

入行已经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> 点个星 星吧