Hi all, I am trying to make a custom textbox, with a few more features than the "normal" one has...

Things I have tried to implement is
  • background text when the textbox text property is empty. choose text and color
  • picture with the possibility to act as button (clickable, raises event)


these things works quite fine, but I’m sure it can be improved a bit with the help from some of you.
Things I have in mind:
  • Reduce flickering
  • Better coding (some examples, if there’s a more proper way of doing some things)
  • New features


I don’t know if this is something people want to help with, but it could be real nice as there is almost no examples of custom textboxes (I haven’t found any, but haven’t looked that much).

My English skills are not the best, hope you all understand...



The Class i made:

Code:
Imports System.ComponentModel

Public Class testText
    Inherits TextBox

#Region "Variables"
    Private Const WM_PAINT As Integer = &HF
    Private _IsEntryMandatory As Boolean = True
    Private pic As Image
    Private empText As String
    Private empBrush As New SolidBrush(Color.SlateGray)
    Private picClick As Boolean
    Private inbutton As Boolean
    Public Event Picture_Click()
#End Region

#Region "Properties"
    <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), _
    Description("Select a icon for the textbox."), _
    Browsable(True)> _
    Public Property Picture() As Image
        Get
            Return pic
        End Get
        Set(ByVal value As Image)
            pic = value
            Me.Invalidate()
        End Set
    End Property

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), _
    Description("Select a color for the empty text."), _
    Browsable(True)> _
    Public Property TextNothingColor() As Color
        Get
            Return empBrush.Color
        End Get
        Set(ByVal value As Color)
            empBrush.Color = value
            Me.Invalidate()
        End Set
    End Property

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), _
    Description("Select a text to be displayed when textbox is empty."), _
    Browsable(True)> _
    Public Property TextNothing() As String
        Get
            Return empText
        End Get
        Set(ByVal value As String)
            empText = value
            Me.Invalidate()
        End Set
    End Property

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), _
    Description("Use picture as button (Raises Picture_Click event)."), _
    Browsable(True)> _
    Public Property PictureIsButton() As Boolean
        Get
            Return picClick
        End Get
        Set(ByVal value As Boolean)
            picClick = value
            Me.Invalidate()
        End Set
    End Property

    Public Property IsEntryMandatory() As Boolean
        Get
            Return _IsEntryMandatory
        End Get
        Set(ByVal value As Boolean)
            _IsEntryMandatory = value
        End Set
    End Property
#End Region
    
#Region "The Custom Drawing"
    Private Sub DrawString()
        Dim G As Graphics = Me.CreateGraphics
        G.DrawString(empText, Me.Font, empBrush, 0, 0)
        G.Dispose()
    End Sub

    Private Sub DrawRect()
        If Not pic Is Nothing Then
            Dim G As Graphics = Me.CreateGraphics
            G.FillRectangle(Brushes.LightCyan, New Rectangle(Me.Width - 30, -2, 25, Me.Height))
            G.DrawRectangle(Pens.Black, New Rectangle(Me.Width - 30, -2, 25, Me.Height))
            G.Dispose()
            DrawTheImage()
        End If
    End Sub

    Private Sub DrawTheImage()
        If Not pic Is Nothing Then
            Dim G As Graphics = Me.CreateGraphics
            G.DrawImage(Me.pic, New Rectangle(Me.Width - 25, 0, 15, 15))
            G.Dispose()
        End If
    End Sub
#End Region

#Region "Mouse handling"
    Private Sub testText_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        Me.Invalidate()
    End Sub

    Private Sub testText_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
        If picClick Then
            If e.Location.X >= Me.Width - 30 And e.Location.X <= Me.Width Then
                Me.Cursor = Cursors.Default
                DrawRect()
                inbutton = True
            Else
                Me.Cursor = Cursors.IBeam
                If inbutton Then
                    inbutton = False
                    Me.Invalidate()
                End If
            End If
        End If
    End Sub

    Private Sub testText_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        If picClick Then
            If e.Location.X >= Me.Width - 20 And e.Location.X <= Me.Width - 5 Then
                RaiseEvent Picture_Click()
            End If
        End If
        Me.Invalidate()
    End Sub
#End Region

#Region "The Rest"
    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
        MyBase.OnTextChanged(e)
        Me.Invalidate()
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        MyBase.WndProc(m)
        If Not IsEntryMandatory Then Return
        If m.Msg = WM_PAINT Then
            If Not empText = "" Then
                If Me.Text.Length = 0 Then
                    DrawString()
                    DrawTheImage()
                Else
                    DrawTheImage()
                End If
            End If
        End If
    End Sub

    Public Sub New()
        Me.SetStyle(ControlStyles.UserPaint, False)
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        Me.UpdateStyles()
    End Sub

    Private Sub testText_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Me.Invalidate()
    End Sub
#End Region
  
End Class