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