Search code examples
vb.neteventsgraphicsenterdrawrectangle

Graphics.DrawRectangle not working in control events


First of all thank you for taking the time out of your busy schedule to assist me.

I am developing a project (Win Application) with a Form and 3 textboxes (TextBox1, TextBox2 and TextBox3).

I need draw a rectangle around the textbox when focused this.

The code is:

Private Sub TextBox123_Enter(sender As Object, e As System.EventArgs) Handles TextBox1.Enter, TextBox2.Enter, TextBox3.Enter
    Using g As Graphics = Me.CreateGraphics
        Dim r As Rectangle = sender.Bounds
        r.Inflate(4, 4)
        g.DrawRectangle(Pens.Blue, r)
    End Using
End Sub

The problem is the following:

  • The first time the textbox1 gains focus rectangle is not drawn.
  • The first time the textbox2 gains focus rectangle is not drawn.

Why not the rectangle is drawn when the first two events enter are fired?


Solution

  • Drawing with CreateGraphics is almost always not the correct approach. If you notice also, when you move from one box to another, the old rectangle is not being erased. You need to use the Form_Paint event to get it to work right. Or...perhaps simpler would be to create a UserControls which is 1-2 pixels larger than a child TextBox and set the backcolor of the UserControl canvas, draw your rectangle when the control gets the focus.

    For form paint:

    Public Class Form1
        Private HotControl As Control
    

    If you are only going to do TextBoxes, you can declare it As TextBox. This way it allows you to do the same for other control types. Set/clear the tracker:

    Private Sub TextBox3_Enter(sender As Object, e As EventArgs) Handles TextBox3.Enter,
               TextBox2.Enter, TextBox1.Enter
        HotControl = CType(sender, TextBox)
        Me.Invalidate()
    End Sub
    
    Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave,
               TextBox2.Leave, TextBox3.Leave
        HotControl = Nothing
        Me.Invalidate()
    End Sub
    

    The Me.Invalidate tells the form to redraw itself, which happens in Paint:

    Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    
        If HotControl IsNot Nothing Then
            Dim r As Rectangle = HotControl.Bounds
            r.Inflate(4, 4)
            e.Graphics.DrawRectangle(Pens.Blue, r)
        End If
    
    End Sub
    

    You should also turn on Option Strict.