Button stays in MouseDown

121 views Asked by At

Well, I'm getting back into GDI, and I came across my old first attempt, which was in c#. I converted it to VB.NET, and saw no errors. However, when I tested it out, the button would stay the color for the MouseDown state until I closed the MessageBox that it opens. Any ideas?

GDI -

Public Class BasicButton
Inherits Control
Public Enum MouseState
    Normal
    Down
End Enum
Private _mouseState As MouseState = MouseState.Normal
Protected Overrides Sub CreateHandle()
    MyBase.CreateHandle()

End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
    Dim g = e.Graphics
    Select Case _mouseState
        Case MouseState.Normal
            g.FillRectangle(Brushes.Orange, ClientRectangle)
            Exit Select
        Case MouseState.Down
            g.FillRectangle(Brushes.DarkOrange, ClientRectangle)
            Exit Select

    End Select
    MyBase.OnPaint(e)
    Dim sf As New StringFormat()
    sf.LineAlignment = StringAlignment.Center
    sf.Alignment = StringAlignment.Center
    g.DrawString(Text, Font, New SolidBrush(Color.White), New Rectangle(0, 0, Width, Height), sf)
End Sub
Private Sub SwitchMouseState(state As MouseState)
    _mouseState = state
    Invalidate()
End Sub
Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
    SwitchMouseState(MouseState.Normal)
    MyBase.OnMouseUp(e)
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
    SwitchMouseState(MouseState.Down)
    MyBase.OnMouseDown(e)
End Sub

End Class

Button -

Private Sub BasicButton1_Click(sender As Object, e As EventArgs) Handles BasicButton1.Click
    MessageBox.Show("Text")
End Sub
2

There are 2 answers

0
Sam Axe On

MessageBox.Show is a blocking method that gets called between OnMouseDown and OnMouseUp. Basically, your OnMouseUp code is not called until after the MessageBox.Show method returns.

1
Sam Axe On

While not an answer, I believe it is important for you to be aware that creating resources within the Paint method should be done as sparingly as possible - hopefully not at all. Paint is called MANY MANY times per second in some cases.

So for instance where your code reads:

Dim sf As New StringFormat()
    sf.LineAlignment = StringAlignment.Center
    sf.Alignment = StringAlignment.Center
    g.DrawString(Text, Font, New SolidBrush(Color.White), New Rectangle(0, 0, Width, Height), sf)

You are creating a StringFormat, and a SolidBrush, and a Rectangle.

The StringFormat and SolidBrush could be cached (by making them class-level variables). The Rectangle can also be cached by making it a class-level variable and updating it during the Resize event.