测试环境:windows 7和Microsoft Visual Studio 2017
看到一些优秀软件里的TEXTBOX文本框都有水印文字提示应该输入什么样的信息,获取光标后提示文字消失,光标离开后水印文字出现,效果杠杠的,心里琢磨着能不能在自己在软件中也弄一个这样的效果?
首先想到的是利用TEXTBOX的焦点获得(Enter)和失去(Leave)事件来实现,新建一个窗体应用程序并拉入一个文本框,然后在窗体代码框录入如下代码:
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Public Class Form1
Private _textboxHasText As Boolean = False
Private Sub TextBox1_Enter(sender As Object, e As EventArgs) Handles TextBox1.Enter
If _textboxHasText = False Then TextBox1.Text = ""
TextBox1.ForeColor = Color.Black
End Sub
Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave
If TextBox1.Text = "" Then
TextBox1.Text = "水印文字"
TextBox1.ForeColor = Color.LightGray
_textboxHasText = False
Else
_textboxHasText = True
End If
End Sub
End Class
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
这种实现方式扩展性差,所以想到之前有做过自定义控件来实现DataGridView控件的全选全不选效果及分页效果,今天继续尝试着扩展TEXTBOX,把代码封装方便调用。首先想到的是做一个复合控件,这是最容易实现的,代码跟上述基本一致,因为我还没做过直接扩展控件的经验,对于控件继承、重载、重写等概念还处于一知半解状态,所以就想着借此机会做个尝试,顺便巩固学习成果。 添加新项,类、组件或者自定义控件,如果提示 Inherits TextBox代码出错就换一个项,具体应该用那个项我也不懂,反正哪个不报错就用哪个。
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Public Class TextBoxEx
Inherits TextBox
Private _textboxHasText As Boolean = False
Public Sub New()
'MyBase.New()
InitializeComponent()
End Sub
Private _watermarkText As String = "水印文字"
<Category("设置"), Description("渐变开始颜色")>
Public Property WatermarkText As String
Get
Return _watermarkText
End Get
Set(ByVal value As String)
_watermarkText = value
End Set
End Property
Protected Overrides Sub OnEnter(ByVal e As EventArgs)
If _textboxHasText = False Then Me.Text = ""
Me.ForeColor = Color.Black
'Me.Invalidate()
MyBase.OnEnter(e)
End Sub
Protected Overrides Sub OnLeave(ByVal e As EventArgs)
If Me.Text = "" Then
Me.Text = WatermarkText
Me.ForeColor = Color.LightGray
_textboxHasText = False
Else
_textboxHasText = True
End If
'Me.Invalidate()
MyBase.OnLeave(e)
End Sub
End Class
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
在这里为新的控件增加了一个修改水印文字的属性watermarkText,重写了TEXTBOX的焦点获得(Enter)和失去(Leave)事件,生成一下就可以在工具箱里看到该新的控件了。如图: 从工具箱拉入一个TextBoxEx控件,在属性窗口里可以找到扩展的属性watermarkText,在这里设置要显示的水印文字。 注意看还发现有对该属性的说明性文字,这个是在定义属性前增加代码<Category(“设置”), Description(“渐变开始颜色”)>来实现的。当然如果你愿意,也可以再增加如水印文字的字体、颜色等其他属性。 测试发现并没有真正达到自己想要的效果,于是在csdn里翻阅,终于看到一个C#语言的,效果很好,于是把他翻译成了VB.NET。 代码写到一个新项(类、组件或自定义控件,具体用哪个自己尝试一下),按照设置属性(水印文字WaterText、水印颜色WaterColor和水印字体WaterFont——建立消息机制(重写WndProc方法)——绘制水印(DrawWaterText方法)的思路来实现。 代码如下:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Data
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Text.RegularExpressions
Imports System.Runtime.InteropServices
<ToolboxBitmap(GetType(TextBox))>
Partial Public Class TextEx
Inherits TextBox
Private _WaterText As String = "水印文本"
Private _WaterColor As Color = Color.DarkGray
Private _WaterFont As Font = New Font(("宋体"), 10.0F)
<Description("水印文本")>
Public Property WaterText As String
Get
Return Me._WaterText
End Get
Set(ByVal value As String)
Me._WaterText = value
End Set
End Property
<Description("水印颜色")>
Public Property WaterColor As Color
Get
Return Me._WaterColor
End Get
Set(ByVal value As Color)
Me._WaterColor = value
End Set
End Property
<Description("水印字体")>
Public Property WaterFont As Font
Get
Return Me._WaterFont
End Get
Set(ByVal value As Font)
Me._WaterFont = value
End Set
End Property
Protected Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
If m.Msg = 15 Then
DrawWaterText(m)
End If
End Sub
Public Sub DrawWaterText(ByRef m As Message)
Using g As Graphics = Graphics.FromHwnd(MyBase.Handle)
If Me.Text.Length = 0 AndAlso Not String.IsNullOrEmpty(Me.WaterText) AndAlso Not Me.Focused Then
Dim flags As TextFormatFlags = TextFormatFlags.EndEllipsis Or TextFormatFlags.VerticalCenter
If Me.RightToLeft = System.Windows.Forms.RightToLeft.Yes Then
flags = flags Or TextFormatFlags.RightToLeft Or TextFormatFlags.Right
End If
TextRenderer.DrawText(g, Me._WaterText, Me._WaterFont, Me.ClientRectangle, Me._WaterColor, flags)
End If
End Using
End Sub
End Class
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
重新生成一下即可在工具箱中找到TextEx控件,如图: 仔细看还发现该控件图标与上面的textboxex控件图标大不同,这个与内置的textbox控件图标一模一样,这是因为代码前端加了这样一句代码:<ToolboxBitmap(GetType(TextBox))>。 从工具箱把该控件拉入窗体,从属性窗口修改水印文字、颜色和字体属性,如图: 好了,现在可以测试比较几种实现方式的效果了,如图: 如果有兴致还可以扩展边框及增加输入验证等效果,怎么样?你也来试试! 本文参考了以下博文: