Results 1 to 7 of 7

Thread: [RESOLVED] Custom TextBox BackColor

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    May 2003
    Posts
    758

    Resolved [RESOLVED] Custom TextBox BackColor

    I know this should be easy, but I am stumped at this point. I have a custom TextBox that has a property ControlState. ControlState points to an Enum with values like Normal, Warning, Error, etc. When ControlState gets changed, it paints the BackColor accordingly. That works great. Where my problem comes in is when the user has changed the BackColor at design time to say Green. When a Warning state occurs and the BackColor is set to say Yellow and then the Warning state is fixed, I want to paint it back to Green. However, I cannot figure out where to pickup the color that was selected at design time (or the default color if nothing was set at design time).


    Here are some things I have tried:

    Code that applies to all of the scenarios:
    Code:
        <System.ComponentModel.Description("Sets the control state to Warning or Error.  Changes the border color based upon the selection."), System.ComponentModel.Category("Validation")> _
        Property ControlState() As ControlStates
            Get
                Return _ControlState
            End Get
            Set(ByVal value As ControlStates)
                _ControlState = value
    
                Me.BackColor = GetBackgroundColor()
            End Set
        End Property
    
        Private Function GetBackgroundColor() As Color
            Dim RetVal As Color
    
            If Not Me.Enabled Then
                RetVal = System.Drawing.SystemColors.Control
            Else
                Select Case True
                    Case Me.ControlState = ControlStates.Warning
                        RetVal = Color.PaleGoldenrod
    
                    Case Me.ControlState = ControlStates.Error
                        RetVal = Color.LightCoral
    
                    Case Me.IsRequired
                        RetVal = Color.OldLace
    
                    Case Me.ReadOnly
                        RetVal = Color.FromArgb(245, 245, 245)
    
                    Case Else
                        RetVal = _BackColor
    
                End Select
            End If
    
            Return RetVal
        End Function

    In this scenario, I was trying to catch the BackColor the first time it was changed (Static) and then set MyBase.BackColor. This would never change the BackColor of the control. I am guessing that since I am changing the color of MyBase and not Me, that is creating my situation.
    Code:
        Private _BackColor As Color
    
        Overrides Property BackColor As Color
            Get
                Return _BackColor
            End Get
            Set(value As Color)
                Static bDone As Boolean
    
                If Not bDone Then
                    _BackColor = value
                    bDone = True
                End If
    
                MyBase.BackColor = value
            End Set
        End Property

    I tried to override the OnBackColorChanged event to catch it first being set. This worked if you set it to something other than default at design time. If you left it at default, the static variable didn't get set until the first time the BackColor was changed in the app. That would mean that it has the wrong color to set it back to when set back to Normal.
    Code:
        Protected Overrides Sub OnBackColorChanged(e As EventArgs)
            MyBase.OnBackColorChanged(e)
    
            Static bDone As Boolean
    
            If Not bDone Then
                _BackColor = Me.BackColor
                bDone = True
            End If
        End Sub
    Thanks in advance!!
    My.Settings.Signature = String.Empty

  2. #2
    PowerPoster JuggaloBrotha's Avatar
    Join Date
    Sep 2005
    Location
    Lansing, MI; USA
    Posts
    4,286

    Re: Custom TextBox BackColor

    The easiest way I can think of to handle this is when you change the backcolour of your control use MyBase.BackColor as the property to change.
    Then shadow the current BackColor property and provide your own internal variable, that way when it's set back to "normal" you can use your own variable value.

    From the form perspective it will look like it's the regular BackColor property still, even though it's not.
    Currently using VS 2015 Enterprise on Win10 Enterprise x64.

    CodeBank: All ThreadsColors ComboBoxFading & Gradient FormMoveItemListBox/MoveItemListViewMultilineListBoxMenuButtonToolStripCheckBoxStart with Windows

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    May 2003
    Posts
    758

    Re: Custom TextBox BackColor

    It sounds like what you are proposing is to Override the BackColor property and set MyBase.BackColor = Value. That is what I attempted to do in the second code box above. It never changed the BackColor of the control. I put in a break point and that line is getting processed and the value is getting set. However, the backcolor is still white.
    My.Settings.Signature = String.Empty

  4. #4
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,764

    Re: Custom TextBox BackColor

    It wasn't clear if the state could go from warning to error, then back to warning, and then normal. This should give you some ideas. It should also take care of the normal color being the color the user chose at design time.

    Code:
    Public Enum ControlStates
        Normal
        Warning
        Err
        PreviousState
    End Enum
    
    Public Class myTB : Inherits TextBox
    
        Private _BackColor As New List(Of Color)
        Private _ControlState As ControlStates
    
        Public Sub New()
            MyBase.New()
            Me._BackColor.Add(MyBase.BackColor) 'this is the normal color
        End Sub
    
        <System.ComponentModel.Description("Sets the control state to Warning or Error.  Changes the border color based upon the selection."), System.ComponentModel.Category("Validation")> _
        Property ControlState() As ControlStates
            Get
                Return Me._ControlState
            End Get
            Set(ByVal value As ControlStates)
                Me._ControlState = value
    
                Me.BackColor = GetBackgroundColor()
            End Set
        End Property
    
        Private Function GetBackgroundColor() As Color
    
            Select Case True
    
                Case Me.ControlState = ControlStates.Normal
                    Me.normalColor()
    
                Case Me.ControlState = ControlStates.Warning
                    Me._BackColor.Add(Color.PaleGoldenrod)
    
                Case Me.ControlState = ControlStates.Err
                    Me._BackColor.Add(Color.LightCoral)
    
                Case Me.ControlState = ControlStates.PreviousState
                    If Me._BackColor.Count > 1 Then
                        Me._BackColor.RemoveAt(Me._BackColor.Count - 1)
                    End If
    
                Case Else 'back to normal
                    Me.normalColor()
    
            End Select
    
            Return Me._BackColor(Me._BackColor.Count - 1)
    
        End Function
    
        Private Sub normalColor()
            Me._BackColor = (From bc In Me._BackColor Take 1).ToList
        End Sub
    End Class
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  5. #5
    PowerPoster JuggaloBrotha's Avatar
    Join Date
    Sep 2005
    Location
    Lansing, MI; USA
    Posts
    4,286

    Re: Custom TextBox BackColor

    Quote Originally Posted by Aspnot View Post
    It sounds like what you are proposing is to Override the BackColor property and set MyBase.BackColor = Value. That is what I attempted to do in the second code box above. It never changed the BackColor of the control. I put in a break point and that line is getting processed and the value is getting set. However, the backcolor is still white.
    After some playing with it, I've realized that we can't Override the BackColor of your Inherited TextBox, it causes the whole thing to not work, so instead I Shadowed the current BackColor to make it readonly and added a 2nd BackColor (BackColor2) property to allow you to know/change what the "Normal" backcolor is. Here's the class:
    vb.net Code:
    1. Imports System.ComponentModel
    2.  
    3. Public Class BackgorundTextBox
    4.     Inherits TextBox
    5.  
    6.     Private _backColor As Color
    7.     Private _controlState As ControlStates
    8.     Private _isRequired As Boolean
    9.  
    10.     Public Sub New
    11.         MyBase.New()
    12.         _backColor = MyBase.BackColor
    13.         _controlState = ControlStates.Normal
    14.         _isRequired = False
    15.     End Sub
    16.  
    17.     Public Shadows ReadOnly Property BackColor As Color
    18.         Get
    19.             Return MyBase.BackColor
    20.         End Get
    21.     End Property
    22.  
    23.     Public Property BackColor2 As Color
    24.         Get
    25.             Return _backColor
    26.         End Get
    27.         Set(value As Color)
    28.             If Not _backColor.Equals(Value)
    29.                 _backColor = Value
    30.                 MyBase.BackColor = GetBackgroundColor()
    31.             End If
    32.         End Set
    33.     End Property
    34.  
    35.     Public Property IsRequired As Boolean
    36.         Get
    37.             Return _isRequired
    38.         End Get
    39.         Set(value As Boolean)
    40.             If _isRequired <> value Then
    41.                 _isRequired = value
    42.                 MyBase.BackColor = GetBackgroundColor()
    43.             End If
    44.         End Set
    45.     End Property
    46.  
    47.     <Description("Sets the control state to Normal, Warning, or Error.  Changes the back color based upon the selection."),
    48.      Category("Validation")>
    49.     Property ControlState() As ControlStates
    50.         Get
    51.             Return _ControlState
    52.         End Get
    53.         Set(value As ControlStates)
    54.             If _ControlState <> Value Then
    55.                 _ControlState = value
    56.                 MyBase.BackColor = GetBackgroundColor()
    57.             End If
    58.         End Set
    59.     End Property
    60.  
    61.     Private Function GetBackgroundColor() As Color
    62.         Dim retVal As Color
    63.  
    64.         If Not Me.Enabled Then
    65.             retVal = SystemColors.Control
    66.         Else
    67.             Select Case True
    68.                 Case _controlState = ControlStates.Warning
    69.                     retVal = Color.PaleGoldenrod
    70.  
    71.                 Case _controlState = ControlStates.Error
    72.                     retVal = Color.LightCoral
    73.  
    74.                 Case _isRequired
    75.                     retVal = Color.OldLace
    76.  
    77.                 Case Me.ReadOnly
    78.                     retVal = Color.WhiteSmoke
    79.  
    80.                 Case Else
    81.                     retVal = _backColor
    82.             End Select
    83.         End If
    84.  
    85.         Return retVal
    86.     End Function
    87. End Class
    88.  
    89. Public Enum ControlStates
    90.     Normal = 0
    91.     Warning = 1
    92.     [Error] = 2
    93. End Enum
    I've also uploaded the example project I made to play with this.
    Attached Files Attached Files
    Currently using VS 2015 Enterprise on Win10 Enterprise x64.

    CodeBank: All ThreadsColors ComboBoxFading & Gradient FormMoveItemListBox/MoveItemListViewMultilineListBoxMenuButtonToolStripCheckBoxStart with Windows

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    May 2003
    Posts
    758

    Re: Custom TextBox BackColor

    Quote Originally Posted by dbasnett View Post
    Code:
        Public Sub New()
            MyBase.New()
            Me._BackColor.Add(MyBase.BackColor) 'this is the normal color
        End Sub
    I was hoping that it would be this easy as I had always tried to grab Me.BackColor in the New() method. However, MyBase.BackColor returns White even when I set it to Green at design time.
    My.Settings.Signature = String.Empty

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    May 2003
    Posts
    758

    Re: Custom TextBox BackColor

    OK. I created a small app to play with this. I added a form with my TextBox and set the BackColor = Green. I set a break point on the first line of code under New() and ran the app. When it stopped at the break point, I looked at the form that had my TextBox on it and the BackColor was White. I realized then that some other code must be running prior to New(). It turned out to be the code from my properties. My properties call GetBackgroundColor to set the BackColor when a user sets ControlState. At runtime, this code was firing before the New() ran and the Case Else was setting RetVal = _BackColor which has a default value of White.

    I thought New() was supposed to run before any properties were set. I did some digging on the event firing order of a control, but didn't find anything about this.

    To get around this, I added the following code to my GetBackgroundColor() routine.
    Code:
            Static bDone As Boolean
    
            If Not bDone Then
                _BackColor = MyBase.BackColor
                bDone = True
            End If

    Now I have everything resolved!

    Thanks everyone for the assistance. I initially thought I must be missing something so simple. Turns out to have been a simple fix, it was just a little more involved.
    My.Settings.Signature = String.Empty

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width