Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GhostText using VB.Net

Tags:

vb.net

Ghost Text

Hello guys, I tried to create a ghost text using Labels over the Textboxes. I am using VB.Net2005. I accomplished this with this code:

Public Class frmDataEntry

    Private Sub PhantomTextLastName()
        If txtLastName.Text = "" Then
            lblLastName.Visible = True
        Else
            lblLastName.Visible = False
        End If
    End Sub

    Private Sub PhantomTextFirstName()
        If txtFirstName.Text = "" Then
            lblFirstName.Visible = True
        Else
            lblFirstName.Visible = False
        End If
    End Sub

    Private Sub PhantomTextMiddleInitial()
        If txtMiddleInitial.Text = "" Then
            lblMiddleInitial.Visible = True
        Else
            lblMiddleInitial.Visible = False
        End If
    End Sub

    Private Sub txtLastName_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtLastName.Click
        lblLastName.Text = "Last Name"
    End Sub

    Private Sub txtLastName_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtLastName.KeyDown
        PhantomTextLastName()
    End Sub

    Private Sub txtLastName_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtLastName.TextChanged
        PhantomTextLastName()
    End Sub

    Private Sub lblLastName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lblLastName.Click
        txtLastName.Focus()
    End Sub

    Private Sub txtFirstName_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtFirstName.Click
        lblFirstName.Text = "First Name"
    End Sub

    Private Sub txtFirstName_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtFirstName.KeyDown
        PhantomTextFirstName()
    End Sub

    Private Sub txtFirstName_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtFirstName.TextChanged
        PhantomTextFirstName()
    End Sub

    Private Sub lblFirstName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lblFirstName.Click
        txtFirstName.Focus()
    End Sub

    Private Sub lblMiddleInitial_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lblMiddleInitial.Click
        txtMiddleInitial.Focus()
    End Sub

    Private Sub txtMiddleInitial_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtMiddleInitial.Click
        lblMiddleInitial.Text = "Middle I."
    End Sub

    Private Sub txtMiddleInitial_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtMiddleInitial.KeyDown
        PhantomTextMiddleInitial()
    End Sub

    Private Sub txtMiddleInitial_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtMiddleInitial.TextChanged
        PhantomTextMiddleInitial()
    End Sub
End Class

Is there any way to reduce this code, so that when I try to add another Textboxes I'll never have to retype a bunch of codes. I have basic knowledge n using Module and Class but I really don't have any idea on how to apply this with this project. I am a newbie, and if you have any tutorial that could help me solve this problem, kindly give me d link. Thanks in advance & God bless.

like image 792
Aaron Avatar asked Sep 21 '11 11:09

Aaron


3 Answers

Create a usercontrol. The code behind your usercontrol might be something like:

 Public Class GhostTextbox

    Private _ghostText As String
    Public Property GhostText As String
        Get
            Return _ghostText
        End Get
        Set(ByVal Value As String)
            _ghostText = Value
        End Set
    End Property

    Public Property ActualText As String
        Get
            Return Me.TextBox1.Text
        End Get
        Set(ByVal Value As String)
            Me.TextBox1.Text = Value
        End Set
    End Property

    Private Sub PhantomText()
        If TextBox1.Text = "" Then
            Label1.Visible = True
        Else
            Label1.Visible = False
        End If
    End Sub

    Private Sub TextBox1_Click(sender As Object, e As System.EventArgs) Handles TextBox1.Click
        Label1.Text = GhostText
    End Sub

    Private Sub TextBox1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
        PhantomText()
    End Sub

    Private Sub TextBox1_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBox1.TextChanged
        PhantomText()
    End Sub

    Private Sub GhostTextbox_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Label1.Text = GhostText
    End Sub
End Class

Then, use this custom control instead of just a TextBox. All you need to do is set the GhostText property for each new control you add instead of redoing the same logic over again.

like image 145
Geoff Appleford Avatar answered Oct 11 '22 01:10

Geoff Appleford


You can put more than 1 Handler in 1 Sub, just separate them by a ,

For example:

Private Sub txtMiddleInitial_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtMiddleInitial.TextChanged
    PhantomTextMiddleInitial()
End Sub

Private Sub txtFirstName_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtFirstName.TextChanged
    PhantomTextFirstName()
End Sub

Private Sub txtLastName_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtLastName.TextChanged
    PhantomTextLastName()
End Sub

To:

Private Sub txtControl_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtLastName.TextChanged, txtFirstName.TextChanged, txtMiddleInitial.TextChanged
    PhantomTextLastName()
End Sub

and so on

MSDN: Connect Multiple Events to a Single Event Handler in Windows Forms

like image 21
SwissGuy Avatar answered Oct 11 '22 02:10

SwissGuy


I've used a NativeWindow class to do this:

Public Class WaterMark
  Inherits NativeWindow

  <DllImport("User32.dll")> _
  Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
  End Function

  <DllImport("user32.dll")> _
  Private Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean
  End Function

  Private _TextBox As TextBox
  Private _EmptyMessage As String

  Private Const WM_PAINT As Integer = &HF

  Public Sub New(ByVal textBox As TextBox, ByVal emptyMessage As String)
    _TextBox = TextBox
    AddHandler _TextBox.TextChanged, AddressOf OnTextChanged
    _EmptyMessage = emptyMessage
    MyBase.AssignHandle(textBox.Handle)
  End Sub

  Private Sub OnTextChanged(ByVal sender As Object, ByVal e As EventArgs)
    If _TextBox.Text = String.Empty Then
      _TextBox.Invalidate()
    End If
  End Sub

  Public Overrides Sub ReleaseHandle()
    RemoveHandler _TextBox.TextChanged, AddressOf OnTextChanged
    MyBase.ReleaseHandle()
  End Sub

  Protected Overrides Sub WndProc(ByRef m As Message)
    MyBase.WndProc(m)
    If m.Msg = WM_PAINT AndAlso _TextBox.Text = String.Empty Then
      Dim dc As IntPtr = GetWindowDC(m.HWnd)
      Using g As Graphics = Graphics.FromHdc(dc)
        TextRenderer.DrawText(g, _EmptyMessage, _TextBox.Font, _TextBox.ClientRectangle, Color.Gray, Color.Empty, TextFormatFlags.Left Or TextFormatFlags.VerticalCenter)
      End Using
      ReleaseDC(m.HWnd, dc)
    End If
  End Sub
End Class

Then I just need to attach the TextBox to it:

Private _WaterMark As WaterMark

Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
  _WaterMark = New WaterMark(TextBox1, "Enter Something:")
End Sub
like image 24
LarsTech Avatar answered Oct 11 '22 02:10

LarsTech