Search code examples
vb.netwinformslook-and-feel

Disabling the "disabled look" of disabled buttons (VB.net for desktop)


I have many buttons in my app, and some of them are disabled in various circumstances. The problem is, buttons "look wrong" when .Enabled = False

What follows is an example of a list of properties which may be similarly applied to all buttons.

.BackColor = Color.Goldenrod
.Flatstyle = FlatStyle.Flat
.FlatAppearance.MouseOverBackColor = Color.White
.FlatAppearance.BorderSize = 0
.BackgroundImageLayout = ImageLayout.Stretch
.BackGroundImage = My.Resources.Resources.ButtonFade 'This image is translucent, giving the rounded 3D look as shown below.
.ForeColor = Color.Black
.Image = My.Resources.Resources.refresh 'May be other images.
.Text = "RELOAD"

The .BackColor property may be all kinds of colors, as set by the user via a "theme".

To illustrate my concern, below is a screenshot of three buttons. "NEW" is enabled. "SAVE" is disabled. Although "NEW" AND "SAVE" look similar, "SAVE" is washed out with low contrast colors for the text and image.

I'd like all disabled buttons to look more like "RELOAD". That is, I would like the text and image to remain solid black, for better legibility, but I can set BackgroundImage = Nothing so it won't look 3D. (To the user, the model is "If it isn't 3D, it's not clickable.") I will probably also modify the background color of disabled buttons, but that part is easy. I just need the system to stop "greying out" the text and image when I set Enabled = False.

To get this screenshot, "RELOAD" is actually enabled, but I've removed its background image. Problem is, it can still be clicked.

Buttons

How can I get the look I'm looking for?


Solution

  • You cannot achieve what you want by using the Enabled property, the Button class implements the Windows GUI style guide that disabled controls should look disabled by graying out their appearance. A further restriction is that the button renderers cannot be tinkered with, they are not overridable.

    You need to achieve your goal by making the control act disabled. Add a new class to your project and paste the code shown below. Compile. Drag the new control from the top of the toolbox to your form, replacing the existing button controls. Set the Disabled property to True in your code when you want to disable the button. You probably want to tinker with the code that changes the appearance.

    Imports System.ComponentModel
    Public Class MyButton
        Inherits Button
    
        <DefaultValue(False)> _
        Public Property Disabled As Boolean
            Get
                Return IsDisabled
            End Get
            Set(value As Boolean)
                If Value = IsDisabled Then Return
                IsDisabled = Value
                MyBase.SetStyle(ControlStyles.Selectable, Not IsDisabled)
                If IsDisabled And Me.Focused Then Me.Parent.SelectNextControl(Me, True, True, True, True)
                '' Change appearance...
                If IsDisabled Then
                    Me.FlatStyle = Windows.Forms.FlatStyle.Flat
                Else
                    Me.FlatStyle = Windows.Forms.FlatStyle.Standard
                End If
            End Set
        End Property
    
        Protected Overrides Sub OnMouseEnter(e As EventArgs)
            If Not IsDisabled Then MyBase.OnMouseEnter(e)
        End Sub
    
        Protected Overrides Sub OnMouseDown(mevent As MouseEventArgs)
            If Not IsDisabled Then MyBase.OnMouseDown(mevent)
        End Sub
    
        Protected Overrides Sub OnKeyDown(kevent As KeyEventArgs)
            If Not IsDisabled Then MyBase.OnKeyDown(kevent)
        End Sub
    
        Private IsDisabled As Boolean
    End Class