שתף באמצעות


Button Gets Focus & Highlight

Question

Tuesday, October 14, 2014 8:31 PM

We are using custom controls buttons etc. Anyway, currently are buttons do not highlight if you Tab or they get focus unless you mouse over them. So my question is how do I simulate a mouse over like in regular windows? Or is their a better way or at least how do I incorporate default highlighting that regular windows buttons have by default.

All replies (2)

Tuesday, October 14, 2014 11:45 PM ✅Answered | 1 vote

Hi,

 It would probably be easier if you showed us the code so we knew how the button class is drawn and if it inherits from another class other than a Button.

 Anyways, here is the way i set up a quick button class to draw the highlight color around the button when it gets focus by the Tab key being pressed or by the user clicking on it. It also shows a different yellow highlight when the mouse is over the button.

Public Class MyButton
    Inherits Button

    Private MouseIsOver As Boolean = False
    Private MouseIsDown As Boolean = False

    Public Sub New()
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.ForeColor = Color.White
        Me.Width = 100
        Me.Height = 28
        Me.Font = New Font(Me.Font.Name, Me.Font.Size, FontStyle.Bold)
    End Sub

    Protected Overrides Sub OnGotFocus(ByVal e As System.EventArgs)
        MyBase.OnGotFocus(e)
        Me.Refresh()
    End Sub

    Protected Overrides Sub OnLostFocus(ByVal e As System.EventArgs)
        MyBase.OnLostFocus(e)
        Me.Refresh()
    End Sub

    Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
        MouseIsOver = True
        Me.Refresh()
        MyBase.OnMouseEnter(e)
    End Sub

    Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
        MouseIsOver = False
        Me.Refresh()
        MyBase.OnMouseLeave(e)
    End Sub

    Protected Overrides Sub OnMouseDown(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        MouseIsDown = True
        Me.Refresh()
        MyBase.OnMouseDown(mevent)
    End Sub

    Protected Overrides Sub OnMouseUp(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        MouseIsDown = False
        Me.Refresh()
        MyBase.OnMouseUp(mevent)
    End Sub

    Protected Overrides Sub OnPaint(ByVal pevent As System.Windows.Forms.PaintEventArgs)
        With pevent.Graphics
            Dim StrtClr As Color = Color.Gray
            Dim EndClr As Color = Color.Black

            If MouseIsDown Then
                StrtClr = Color.Black
                EndClr = Color.Gray
            ElseIf MouseIsOver Then
                StrtClr = Color.Silver
                EndClr = Color.Black
            End If

            Using lgb As New Drawing2D.LinearGradientBrush(New Point(0, 0), New Point(0, Me.Height), StrtClr, EndClr)
                .FillRectangle(lgb, 0, 0, Me.Width, Me.Height)
                Using sf As New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center, .FormatFlags = StringFormatFlags.NoWrap, .Trimming = StringTrimming.EllipsisCharacter}
                    Using txtbrsh As New SolidBrush(Me.ForeColor)
                        Dim txtrect As New Rectangle(Me.Padding.Left, Me.Padding.Top, Me.Width - Me.Padding.Left - Me.Padding.Right, Me.Height - Me.Padding.Top - Me.Padding.Bottom)
                        .DrawString(Me.Text, Me.Font, txtbrsh, txtrect, sf)
                    End Using
                End Using
                If Not MouseIsDown Then
                    If MouseIsOver Then
                        Using pn As New Pen(Color.FromArgb(200, Color.Yellow), 2)
                            .DrawRectangle(pn, 1, 1, Me.Width - 2, Me.Height - 2)
                        End Using
                    ElseIf Me.Focused Then
                        Using pn As New Pen(Color.FromKnownColor(KnownColor.Highlight), 2)
                            .DrawRectangle(pn, 1, 1, Me.Width - 2, Me.Height - 2)
                        End Using
                    End If
                End If
            End Using
        End With
    End Sub
End Class

If you say it can`t be done then i`ll try it


Tuesday, October 14, 2014 11:26 PM | 1 vote

We are using custom controls buttons etc. Anyway, currently are buttons do not highlight if you Tab or they get focus unless you mouse over them. So my question is how do I simulate a mouse over like in regular windows? Or is their a better way or at least how do I incorporate default highlighting that regular windows buttons have by default.

Well I tried various methods using standard Button event handlers and even a timer but couldn't figure out a way to do it very well. Although it could be done I suppose.

Since you're using custom buttons anyhow maybe the code in the below class can assist you for GotFocus and LostFocus or something.

I created a new Windows Forms App with a Form. Then added a class to the app and pasted the below code, which I altered a bit for the Focus events, into the class. Then right clicked onto the class name in solution explorer and renamed the class to the class name used with the code.

Built the app and the Button was available as a control in the toolbox.

So I dragged two onto the Form, altered the code a few times and then when the tab control is selected the Buttons highlight.

However whoever made the code makes two different button sizes so the normal button size becomes smaller when the button is selected. And the button no longer retains the highlight color once it is selected. Even though I suppose it still has focus. So some alterations to the code would need to be done to make it work correctly.

I didn't try adding event handlers to the buttons in the Form code though so that hasn't been tested either. And I didn't click on one of them on the Form to see if it added a Button Click event handler into the Forms code window.

The below code, mostly, is from this link ButtonRenderer Class

The two images are pressing tab and Button1 being highlighted switching to Button2 being highlighted.

Option Strict On

'
' Code ButtonRenderer Class is from link http://msdn.microsoft.com/en-us/library/system.windows.forms.buttonrenderer(v=vs.110).aspx
' 
Imports System.Windows.Forms.VisualStyles

Public Class CustomButton
    Inherits Control

    Private clickRectangleValue As New Rectangle()
    Private state As PushButtonState = PushButtonState.Normal

    Public Sub New()
        With Me
            Size = New Size(100, 40)
            Location = New Point(50, 50)
            Font = SystemFonts.IconTitleFont
            Text = "Click here"
        End With
    End Sub

    ' Define the bounds of the smaller pressed button. 
    Public ReadOnly Property ClickRectangle() As Rectangle
        Get
            With clickRectangleValue
                .X = Me.ClientRectangle.X + CInt(0.2 * _
                    Me.ClientRectangle.Width)
                .Y = Me.ClientRectangle.Y + CInt(0.2 * _
                    Me.ClientRectangle.Height)
                .Width = Me.ClientRectangle.Width - _
                    CInt(0.4 * Me.ClientRectangle.Width)
                .Height = Me.ClientRectangle.Height - _
                    CInt(0.4 * Me.ClientRectangle.Height)
            End With
            Return clickRectangleValue
        End Get
    End Property

    ' Draw the large or small button, depending on the current state. 
    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        MyBase.OnPaint(e)

        ' Draw the smaller pressed button image. 
        If state = PushButtonState.Pressed Then
            ' Set the background color to the parent if visual styles   
            ' are disabled, because DrawParentBackground will only paint   
            ' over the control background if visual styles are enabled. 
            If Application.RenderWithVisualStyles Then
                Me.BackColor = Color.Azure
            Else
                Me.BackColor = Me.Parent.BackColor
            End If

            ' If you comment out the call to DrawParentBackground,    
            ' the background of the control will still be visible  
            ' outside the pressed button, if visual styles are enabled.
            ButtonRenderer.DrawParentBackground(e.Graphics, Me.ClientRectangle, Me)
            ButtonRenderer.DrawButton(e.Graphics, ClickRectangle, Me.Text, Me.Font, True, state)

            ' Draw the bigger unpressed button image. 
        Else
            ButtonRenderer.DrawButton(e.Graphics, Me.ClientRectangle, Me.Text, Me.Font, False, state)
        End If
    End Sub

    ' Draw the smaller pressed button image. 
    Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
        MyBase.OnMouseDown(e)
        With Me
            .Text = "Clicked!"
            .state = PushButtonState.Pressed
        End With
        Invalidate()
    End Sub

    ' Draw the button in the hot state.  
    Protected Overrides Sub OnMouseEnter(ByVal e As EventArgs)
        MyBase.OnMouseEnter(e)
        With Me
            .Text = "Click here"
            .state = PushButtonState.Hot
        End With
        Invalidate()
    End Sub

    ' Draw the button in the unpressed state. 
    Protected Overrides Sub OnMouseLeave(ByVal e As EventArgs)
        MyBase.OnMouseLeave(e)
        With Me
            .Text = "Click here"
            .state = PushButtonState.Normal
        End With
        Invalidate()
    End Sub

    ' Draw the button hot if the mouse is released on the button. 
    Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
        MyBase.OnMouseUp(e)
        OnMouseEnter(e)
    End Sub

    ' Detect when the cursor leaves the button area while it  
    ' is pressed. 
    Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
        MyBase.OnMouseMove(e)

        ' Detect when the left mouse button is down and    
        ' the cursor has left the pressed button area.  
        If (e.Button And MouseButtons.Left) = MouseButtons.Left And Not _
            Me.ClientRectangle.Contains(e.Location) And _
            state = PushButtonState.Pressed Then
            OnMouseLeave(e)
        End If
    End Sub

    Protected Overrides Sub OnGotFocus(ByVal e As EventArgs)
        MyBase.OnGotFocus(e)
        ' Detect when got focus.
        state = PushButtonState.Hot
        Invalidate()
    End Sub

    Protected Overrides Sub OnLostFocus(ByVal e As EventArgs)
        MyBase.OnLostFocus(e)
        ' Detect when lost focus.
        state = PushButtonState.Normal
        Invalidate()
    End Sub

End Class

La vida loca