(二十九)c#Winform自定义控件-文本框(二)
程序员文章站
2024-02-01 17:32:10
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492 目录 ......
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
开源地址:
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492
目录
准备工作
终于到文本框了,文本框将包含原文本框扩展,透明文本框,数字输入文本框,带边框文本框
本文将讲解透明文本框
开始
这个用到的很少,直接看代码吧
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(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_rbuttondown 529 || m.msg == win32.wm_lbuttondblclk 530 || m.msg == win32.wm_mouseleave 531 || 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 properties 567 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 }
用处及效果
用到的比较少,你高兴就用,哈哈
最后的话
如果你喜欢的话,请到 点个星 星吧
上一篇: 递归的理解与应用