1 using System; 2 using System.Collections; 3 using System.ComponentModel; 4 using System.Drawing; 5 using System.Data; 6 using System.Windows.Forms; 7 8 using System.Drawing.Imaging; 9 10 namespace ZBobb 11 { 12 /// <summary> 13 /// AlphaBlendTextBox: A .Net textbox that can be translucent to the background. 14 /// (C) 2003 Bob Bradley / ZBobb@hotmail.com 15 /// </summary> 16 /// 17 18 19 20 public class AlphaBlendTextBox : System.Windows.Forms.TextBox 21 { 22 #region private variables 23 24 private uPictureBox myPictureBox; 25 private bool myUpToDate = false; 26 private bool myCaretUpToDate = false; 27 private Bitmap myBitmap; 28 private Bitmap myAlphaBitmap; 29 30 private int myFontHeight = 10; 31 32 private System.Windows.Forms.Timer myTimer1; 33 34 private bool myCaretState = true; 35 36 private bool myPaintedFirstTime = false; 37 38 private Color myBackColor = Color.White; 39 private int myBackAlpha = 10; 40 41 /// <summary> 42 /// Required designer variable. 43 /// </summary> 44 private System.ComponentModel.Container components = null; 45 46 #endregion // end private variables 47 48 49 #region public methods and overrides 50 51 public AlphaBlendTextBox() 52 { 53 // This call is required by the Windows.Forms Form Designer. 54 InitializeComponent(); 55 // TODO: Add any initialization after the InitializeComponent call 56 57 this.BackColor = myBackColor; 58 59 this.SetStyle(ControlStyles.UserPaint,false); 60 this.SetStyle(ControlStyles.AllPaintingInWmPaint,true); 61 this.SetStyle(ControlStyles.DoubleBuffer,true); 62 63 64 myPictureBox = new uPictureBox(); 65 this.Controls.Add(myPictureBox); 66 myPictureBox.Dock = DockStyle.Fill; 67 } 68 69 70 protected override void OnResize(EventArgs e) 71 { 72 73 base.OnResize (e); 74 this.myBitmap = new Bitmap(this.ClientRectangle.Width,this.ClientRectangle.Height);//(this.Width,this.Height); 75 this.myAlphaBitmap = new Bitmap(this.ClientRectangle.Width,this.ClientRectangle.Height);//(this.Width,this.Height); 76 myUpToDate = false; 77 this.Invalidate(); 78 } 79 80 81 //Some of these should be moved to the WndProc later 82 83 protected override void OnKeyDown(KeyEventArgs e) 84 { 85 base.OnKeyDown (e); 86 myUpToDate = false; 87 this.Invalidate(); 88 } 89 90 protected override void OnKeyUp(KeyEventArgs e) 91 { 92 base.OnKeyUp (e); 93 myUpToDate = false; 94 this.Invalidate(); 95 96 } 97 98 protected override void OnKeyPress(KeyPressEventArgs e) 99 { 100 base.OnKeyPress (e); 101 myUpToDate = false; 102 this.Invalidate(); 103 } 104 105 protected override void OnMouseUp(MouseEventArgs e) 106 { 107 base.OnMouseUp (e); 108 this.Invalidate(); 109 } 110 111 protected override void OnGiveFeedback(GiveFeedbackEventArgs gfbevent) 112 { 113 base.OnGiveFeedback (gfbevent); 114 myUpToDate = false; 115 this.Invalidate(); 116 } 117 118 119 protected override void OnMouseLeave(EventArgs e) 120 { 121 //found this code to find the current cursor location 122 //at http://www.syncfusion.com/FAQ/WinForms/FAQ_c50c.asp#q597q 123 124 Point ptCursor = Cursor.Position; 125 126 Form f = this.FindForm(); 127 ptCursor = f.PointToClient(ptCursor); 128 if( !this.Bounds.Contains(ptCursor) ) 129 base.OnMouseLeave (e); 130 } 131 132 133 protected override void OnChangeUICues(UICuesEventArgs e) 134 { 135 base.OnChangeUICues (e); 136 myUpToDate = false; 137 this.Invalidate(); 138 } 139 140 141 //-- 142 protected override void OnGotFocus(EventArgs e) 143 { 144 base.OnGotFocus (e); 145 myCaretUpToDate = false; 146 myUpToDate = false; 147 this.Invalidate(); 148 149 150 myTimer1 = new System.Windows.Forms.Timer(this.components); 151 myTimer1.Interval = (int) win32.GetCaretBlinkTime(); // usually around 500; 152 153 myTimer1.Tick +=new EventHandler(myTimer1_Tick); 154 myTimer1.Enabled = true; 155 156 } 157 158 protected override void OnLostFocus(EventArgs e) 159 { 160 base.OnLostFocus (e); 161 myCaretUpToDate = false; 162 myUpToDate = false; 163 this.Invalidate(); 164 165 myTimer1.Dispose(); 166 } 167 168 //-- 169 170 protected override void OnFontChanged(EventArgs e) 171 { 172 if (this.myPaintedFirstTime) 173 this.SetStyle(ControlStyles.UserPaint,false); 174 175 base.OnFontChanged (e); 176 177 if (this.myPaintedFirstTime) 178 this.SetStyle(ControlStyles.UserPaint,true); 179 180 181 myFontHeight = GetFontHeight(); 182 183 184 myUpToDate = false; 185 this.Invalidate(); 186 } 187 188 protected override void OnTextChanged(EventArgs e) 189 { 190 base.OnTextChanged (e); 191 myUpToDate = false; 192 this.Invalidate(); 193 } 194 195 196 protected override void WndProc(ref Message m) 197 { 198 199 base.WndProc (ref m); 200 201 // need to rewrite as a big switch 202 203 if (m.Msg == win32.WM_PAINT) 204 { 205 myPaintedFirstTime = true; 206 207 if (!myUpToDate || !myCaretUpToDate) 208 GetBitmaps(); 209 myUpToDate = true; 210 myCaretUpToDate = true; 211 212 if (myPictureBox.Image != null) myPictureBox.Image.Dispose(); 213 myPictureBox.Image = (Image)myAlphaBitmap.Clone(); 214 215 } 216 217 else if (m.Msg == win32.WM_HSCROLL || m.Msg == win32.WM_VSCROLL) 218 { 219 myUpToDate = false; 220 this.Invalidate(); 221 } 222 223 else if (m.Msg == win32.WM_LBUTTONDOWN 224 || m.Msg == win32.WM_RBUTTONDOWN 225 || m.Msg == win32.WM_LBUTTONDBLCLK 226 // || m.Msg == win32.WM_MOUSELEAVE ///**** 227 ) 228 { 229 myUpToDate = false; 230 this.Invalidate(); 231 } 232 233 else if (m.Msg == win32.WM_MOUSEMOVE ) 234 { 235 if (m.WParam.ToInt32() != 0) //shift key or other buttons 236 { 237 myUpToDate = false; 238 this.Invalidate(); 239 } 240 } 241 242 243 244 //System.Diagnostics.Debug.WriteLine("Pro: " + m.Msg.ToString("X")); 245 246 } 247 248 249 /// <summary> 250 /// Clean up any resources being used. 251 /// </summary> 252 protected override void Dispose( bool disposing ) 253 { 254 if( disposing ) 255 { 256 //this.BackColor = Color.Pink; 257 if(components != null) 258 { 259 components.Dispose(); 260 } 261 } 262 base.Dispose( disposing ); 263 } 264 265 #endregion //end public method and overrides 266 267 268 #region public property overrides 269 270 public new BorderStyle BorderStyle 271 { 272 get {return base.BorderStyle;} 273 set 274 { 275 if (this.myPaintedFirstTime) 276 this.SetStyle(ControlStyles.UserPaint,false); 277 278 base.BorderStyle = value; 279 280 if (this.myPaintedFirstTime) 281 this.SetStyle(ControlStyles.UserPaint,true); 282 283 this.myBitmap = null; 284 this.myAlphaBitmap = null; 285 myUpToDate = false; 286 this.Invalidate(); 287 } 288 } 289 290 public new Color BackColor 291 { 292 get 293 { 294 return Color.FromArgb(base.BackColor.R, base.BackColor.G, base.BackColor.B); 295 } 296 set 297 { 298 myBackColor = value; 299 base.BackColor = value; 300 myUpToDate = false; 301 } 302 } 303 public override bool Multiline 304 { 305 get{return base.Multiline;} 306 set 307 { 308 if (this.myPaintedFirstTime) 309 this.SetStyle(ControlStyles.UserPaint,false); 310 311 base.Multiline = value; 312 313 if (this.myPaintedFirstTime) 314 this.SetStyle(ControlStyles.UserPaint,true); 315 316 this.myBitmap = null; 317 this.myAlphaBitmap = null; 318 myUpToDate = false; 319 this.Invalidate(); 320 } 321 } 322 323 324 #endregion //end public property overrides 325 326 327 #region private functions and classes 328 329 private int GetFontHeight() 330 { 331 Graphics g = this.CreateGraphics(); 332 SizeF sf_font = g.MeasureString("X",this.Font); 333 g.Dispose(); 334 return (int) sf_font.Height; 335 } 336 337 338 private void GetBitmaps() 339 { 340 341 if (myBitmap == null 342 || myAlphaBitmap == null 343 || myBitmap.Width != Width 344 || myBitmap.Height != Height 345 || myAlphaBitmap.Width != Width 346 || myAlphaBitmap.Height != Height) 347 { 348 myBitmap = null; 349 myAlphaBitmap = null; 350 } 351 352 353 354 if (myBitmap == null) 355 { 356 myBitmap = new Bitmap(this.ClientRectangle.Width,this.ClientRectangle.Height);//(Width,Height); 357 myUpToDate = false; 358 } 359 360 361 if (!myUpToDate) 362 { 363 //Capture the TextBox control window 364 365 this.SetStyle(ControlStyles.UserPaint,false); 366 367 win32.CaptureWindow(this,ref myBitmap); 368 369 this.SetStyle(ControlStyles.UserPaint,true); 370 this.SetStyle(ControlStyles.SupportsTransparentBackColor,true); 371 this.BackColor = Color.FromArgb(myBackAlpha,myBackColor); 372 373 } 374 //-- 375 376 377 378 Rectangle r2 = new Rectangle(0,0,this.ClientRectangle.Width,this.ClientRectangle.Height); 379 ImageAttributes tempImageAttr = new ImageAttributes(); 380 381 382 //Found the color map code in the MS Help 383 384 ColorMap[] tempColorMap = new ColorMap[1]; 385 tempColorMap[0] = new ColorMap(); 386 tempColorMap[0].OldColor = Color.FromArgb(255,myBackColor); 387 tempColorMap[0].NewColor = Color.FromArgb(myBackAlpha,myBackColor); 388 389 tempImageAttr.SetRemapTable(tempColorMap); 390 391 if (myAlphaBitmap != null) 392 myAlphaBitmap.Dispose(); 393 394 395 myAlphaBitmap = new Bitmap(this.ClientRectangle.Width,this.ClientRectangle.Height);//(Width,Height); 396 397 Graphics tempGraphics1 = Graphics.FromImage(myAlphaBitmap); 398 399 tempGraphics1.DrawImage(myBitmap,r2,0,0,this.ClientRectangle.Width,this.ClientRectangle.Height,GraphicsUnit.Pixel,tempImageAttr); 400 401 tempGraphics1.Dispose(); 402 403 //---- 404 405 if (this.Focused && (this.SelectionLength == 0)) 406 { 407 Graphics tempGraphics2 = Graphics.FromImage(myAlphaBitmap); 408 if (myCaretState) 409 { 410 //Draw the caret 411 Point caret = this.findCaret(); 412 Pen p = new Pen(this.ForeColor,3); 413 tempGraphics2.DrawLine(p,caret.X,caret.Y + 0,caret.X,caret.Y + myFontHeight); 414 tempGraphics2.Dispose(); 415 } 416 417 } 418 419 420 421 } 422 423 424 425 private Point findCaret() 426 { 427 /* Find the caret translated from code at 428 * http://www.vb-helper.com/howto_track_textbox_caret.html 429 * 430 * and 431 * 432 * http://www.microbion.co.uk/developers/csharp/textpos2.htm 433 * 434 * Changed to EM_POSFROMCHAR 435 * 436 * This code still needs to be cleaned up and debugged 437 * */ 438 439 Point pointCaret = new Point(0); 440 int i_char_loc = this.SelectionStart; 441 IntPtr pi_char_loc = new IntPtr(i_char_loc); 442 443 int i_point = win32.SendMessage(this.Handle,win32.EM_POSFROMCHAR,pi_char_loc,IntPtr.Zero); 444 pointCaret = new Point(i_point); 445 446 if (i_char_loc == 0) 447 { 448 pointCaret = new Point(0); 449 } 450 else if (i_char_loc >= this.Text.Length) 451 { 452 pi_char_loc = new IntPtr(i_char_loc - 1); 453 i_point = win32.SendMessage(this.Handle,win32.EM_POSFROMCHAR,pi_char_loc,IntPtr.Zero); 454 pointCaret = new Point(i_point); 455 456 Graphics g = this.CreateGraphics(); 457 String t1 = this.Text.Substring(this.Text.Length-1,1) + "X"; 458 SizeF sizet1 = g.MeasureString(t1,this.Font); 459 SizeF sizex = g.MeasureString("X",this.Font); 460 g.Dispose(); 461 int xoffset = (int)(sizet1.Width - sizex.Width); 462 pointCaret.X = pointCaret.X + xoffset; 463 464 if (i_char_loc == this.Text.Length) 465 { 466 String slast = this.Text.Substring(Text.Length-1,1); 467 if (slast == " ") 468 { 469 pointCaret.X = 1; 470 pointCaret.Y = pointCaret.Y + myFontHeight; 471 } 472 } 473 474 } 475 476 477 478 return pointCaret; 479 } 480 481 482 private void myTimer1_Tick(object sender, EventArgs e) 483 { 484 //Timer used to turn caret on and off for focused control 485 486 myCaretState = !myCaretState; 487 myCaretUpToDate = false; 488 this.Invalidate(); 489 } 490 491 492 private class uPictureBox : PictureBox 493 { 494 public uPictureBox() 495 { 496 this.SetStyle(ControlStyles.Selectable,false); 497 this.SetStyle(ControlStyles.UserPaint,true); 498 this.SetStyle(ControlStyles.AllPaintingInWmPaint,true); 499 this.SetStyle(ControlStyles.DoubleBuffer,true); 500 501 this.Cursor = null; 502 this.Enabled = true; 503 this.SizeMode = PictureBoxSizeMode.Normal; 504 505 } 506 507 508 509 510 //uPictureBox 511 protected override void WndProc(ref Message m) 512 { 513 if (m.Msg == win32.WM_LBUTTONDOWN 514 || m.Msg == win32.WM_RBUTTONDOWN 515 || m.Msg == win32.WM_LBUTTONDBLCLK 516 || m.Msg == win32.WM_MOUSELEAVE 517 || m.Msg == win32.WM_MOUSEMOVE ) 518 { 519 //Send the above messages back to the parent control 520 win32.PostMessage(this.Parent.Handle,(uint) m.Msg,m.WParam,m.LParam); 521 } 522 523 else if (m.Msg == win32.WM_LBUTTONUP) 524 { 525 //?? for selects and such 526 this.Parent.Invalidate(); 527 } 528 529 530 base.WndProc (ref m); 531 } 532 533 534 } // End uPictureBox Class 535 536 537 #endregion // end private functions and classes 538 539 540 #region Component Designer generated code 541 /// <summary> 542 /// Required method for Designer support - do not modify 543 /// the contents of this method with the code editor. 544 /// </summary> 545 private void InitializeComponent() 546 { 547 components = new System.ComponentModel.Container(); 548 } 549 #endregion 550 551 552 #region New Public Properties 553 554 [ 555 Category("Appearance"), 556 Description("The alpha value used to blend the control's background. Valid values are 0 through 255."), 557 Browsable(true), 558 DesignerSerializationVisibility(DesignerSerializationVisibility.Visible) 559 560 ] 561 public int BackAlpha 562 { 563 get { return myBackAlpha; } 564 set 565 { 566 int v = value; 567 if (v > 255) 568 v = 255; 569 myBackAlpha = v; 570 myUpToDate = false; 571 Invalidate(); 572 } 573 } 574 575 #endregion 576 577 578 579 } // End AlphaTextBox Class 580 581 582 } // End namespace ZBobb 583 584 585 //---- 586