Custom WaterMark TextBox for Windows Forms - VB.Net

Published:
Updated:
This article explains how to create and use a custom WaterMark textbox class.  The custom WaterMark textbox class allows you to set the WaterMark Background Color and WaterMark text at design time.  

IMAGE OF WATERMARKS

Form with textboxes and watermarks
STEPS

1. Create VB class


Create a new VB class in your solution and name it WaterMarkTextBox.vb

2. Copy VB code to new class


Copy the code from the snippet below to your new class
Option Strict On
                      Imports System
                      Imports System.Windows.Forms
                      Imports System.Drawing
                      Public Class WaterMarkTextBox
                          Inherits TextBox
                       
                          Private oldFont As Font = Nothing
                          Private waterMarkTextEnabled As Boolean = False
                       
                      #Region "Attributes"
                          Private _waterMarkColor As Color = Drawing.Color.Gray
                       
                          Public Property WaterMarkColor() As Color
                              Get
                                  Return _waterMarkColor
                              End Get
                              Set(ByVal value As Color)
                                  _waterMarkColor = value
                                  Me.Invalidate()
                              End Set
                          End Property
                       
                          Private _waterMarkText As String = "Water Mark"
                       
                          Public Property WaterMarkText() As String
                              Get
                                  Return _waterMarkText
                              End Get
                              Set(ByVal value As String)
                                  _waterMarkText = value
                                  Me.Invalidate()
                              End Set
                          End Property
                      #End Region
                       
                          ' Default constructor
                          Public Sub New()
                              JoinEvents(True)
                          End Sub
                       
                          Private Sub JoinEvents(ByVal join As Boolean)
                              If join Then
                                  AddHandler (TextChanged), AddressOf WaterMark_Toggle
                                  AddHandler (LostFocus), AddressOf WaterMark_Toggle
                                  AddHandler (FontChanged), AddressOf WaterMark_FontChanged
                                  'No one of the above events will start immeddiatlly 
                                  'TextBox control still in constructing, so,
                                  'Font object (for example) couldn't be catched from within WaterMark_Toggle
                                  'So, call WaterMark_Toggel through OnCreateControl after TextBox is totally created
                                  'No doupt, it will be only one time call
                       
                                  'Old solution uses Timer.Tick event to check Create property
                              End If
                          End Sub
                       
                          Private Sub WaterMark_Toggle(ByVal sender As Object, ByVal args As EventArgs)
                              If Me.Text.Length <= 0 Then
                                  EnableWaterMark()
                              Else
                                  DisableWaterMark()
                              End If
                          End Sub
                       
                          Private Sub WaterMark_FontChanged(ByVal sender As Object, ByVal args As EventArgs)
                              If waterMarkTextEnabled Then
                                  oldFont = New Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit)
                                  Refresh()
                              End If
                          End Sub
                       
                          Private Sub EnableWaterMark()
                              'Save current font until returning the UserPaint style to false (NOTE: It is a try and error advice)
                              oldFont = New Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit)
                       
                              'Enable OnPaint Event Handler
                              Me.SetStyle(ControlStyles.UserPaint, True)
                              Me.waterMarkTextEnabled = True
                       
                              'Trigger OnPaint immediatly
                              Refresh()
                       
                          End Sub
                       
                          Private Sub DisableWaterMark()
                              'Disbale OnPaint event handler
                              Me.waterMarkTextEnabled = False
                              Me.SetStyle(ControlStyles.UserPaint, False)
                       
                              'Return oldFont if existed
                              If Not oldFont Is Nothing Then
                                  Me.Font = New Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit)
                              End If
                          End Sub
                       
                          ' Override OnCreateControl 
                          Protected Overrides Sub OnCreateControl()
                              MyBase.OnCreateControl()
                              WaterMark_Toggle(Nothing, Nothing)
                          End Sub
                       
                          ' Override OnPaint
                          Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
                              ' Use the same font that was defined in base class
                              Dim drawFont As Font = New Font(Font.FontFamily, Font.Size, Font.Style, Font.Unit)
                              ' Create new brush with gray color or 
                              Dim drawBrush As SolidBrush = New SolidBrush(Me.WaterMarkColor) 'use WaterMarkColor
                              ' Draw Test or WaterMark
                              e.Graphics.DrawString(IIf(waterMarkTextEnabled, WaterMarkText, Text).ToString(), drawFont, drawBrush, New Point(0, 0))
                              MyBase.OnPaint(e)
                          End Sub
                       
                      End Class
                      

Open in new window


3. Compile application to use new WaterMarkTextBox control


Compile the application.  You should now see a "<Your Project Name> Components" section on your toolbox with a tool called WaterMarkTextBox

4. Use the new WaterMarkTextBox control


Drag the new control from your toolbox onto your form and you can set the properties in the properties window (WaterMarkColor, WaterMarkText)

3
23,089 Views

Comments (7)

Nice!  I tried other solutions that all had drawbacks.  This works really well.  Thanks!
CERTIFIED EXPERT

Commented:
Thanks for this article. It works well.

I have a quetion regarding this.

I have changed the fonts of form, but when i create new WaterMarkTextBox it remains in default font.

How can i change it to take default fonts of the form?

- Deepak Lakkad
Dear Rhino 1272
how do you obtain the shadow effect in your textbox as in your IMAGE OF WATERMARKS
It really works well.
Great Stuff.
Thanks

View More

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.