vb .NET custom control inheriting from TextBox doesn't fire Paint event - vb.net

I need a multiline TextBox which is always disabled, but it shouldn't paint itself in gray, but I want to keep its designer choosen color.
I previously had the same requirement with an always-black Label (no multiline) and so I inherited from Label like:
Imports System.ComponentModel
Public Class LabelDisabled
Inherits Label
Sub New()
InitializeComponent()
Enabled = False
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
' always draw it black
e.Graphics.DrawString(Me.Text, Me.Font, Brushes.Black, 0, 0)
End Sub
End Class
That works fine. Now I want the same thing but with a multiline label, so I chose to inherit from TextBox:
Imports System.ComponentModel
Public Class CustomControl1
Inherits TextBox
Sub New()
InitializeComponent()
'Paint never fires anyway
'Enabled = False
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim brush As New SolidBrush(Me.ForeColor)
e.Graphics.DrawString(Me.Text, Me.Font, brush, 0, 0)
End Sub
End Class
Now the Paint event is never fired in the CustomControl1 - TextBox inherited - control.
Why can't I get the Paint event?
Also, if I want to make the Enabled property invisible and not-settable by the user, I do:
<Browsable(False),
DefaultValue(False)>
Public Overloads Property Enabled As Boolean
Get
Return False
End Get
Set(ByVal value As Boolean)
End Set
End Property
But this way, neither I can set the "real" Enabled property, I mean the backing field.

I've found a solution. It looks like a TextBox disables the Paint event even for subclasses. But you can force the WM_PAINT bit calling SetStyle:
Public Class DisabledTextBox
Inherits TextBox
Public Sub New()
InitializeComponent()
Enabled = False
SetStyle(ControlStyles.Selectable, False)
SetStyle(ControlStyles.UserPaint, True)
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim brush As New SolidBrush(Me.ForeColor)
e.Graphics.DrawString(Me.Text, Me.Font, brush, 0, 0)
End Sub
End Class
It works perfectly as expected :)

here is your answer:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
e.Graphics.FillRectangle(Brushes.LightGray, Me.DisplayRectangle)
Dim sf As New StringFormat
sf.FormatFlags = StringFormatFlags.NoWrap
sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Show 'if Mnemonic property is set to true
sf.HotkeyPrefix = Drawing.Text.HotkeyPrefix.Hide 'or none if Mnemonic property is set to false
sf.LineAlignment = StringAlignment.Center 'horizontal alignment
sf.Alignment = StringAlignment.Center ' vertical ...
Dim rect As Rectangle = Me.DisplayRectangle ' this is your text bounds for setting your text alignement using StringFormat(sf)
e.Graphics.DrawString("Something", Me.Font, Brushes.DarkOliveGreen, rect, sf)
End Sub

Related

Custom Toggle Control "Checked" Property Does Not Save (Or Restore) With My.Settings()

I added a custom control to my project, which is a toggle switch that inherits the functionality of a checkbox. The problem I am facing is when I try to create an Application Setting to bind the control to, it does not save (or restore, I don't really know which) the Checked: property. To be more clear, no exception is thrown. The toggle works as designed, however it does not save the state of whether it was checked or not when relaunching the program. It just defaults back to its assigned state that was set in the designer. It's just not saving the fact that it was checked or unchecked when closing or relaunching the program. The My.Settings() code is fine, I've tested it with a checkbox and it saved and restored correctly. The problem lies in the Toggle.vb Class file I'd assume. Here is the source:
Imports System.ComponentModel
Imports System.Drawing.Drawing2D
Namespace CustomControls.RJControls
Public Class RJToggleButton
Inherits CheckBox
'Fields
Private onBackColorField As Color = Color.FromArgb(128, 255, 128)
Private onToggleColorField As Color = Color.White
Private offBackColorField As Color = Color.Black
Private offToggleColorField As Color = Color.White
Private solidStyleField As Boolean = True
'Properties
<Category("RJ Code Advance")>
Public Property OnBackColor As Color
Get
Return onBackColorField
End Get
Set(ByVal value As Color)
onBackColorField = value
Me.Invalidate()
End Set
End Property
<Category("RJ Code Advance")>
Public Property OnToggleColor As Color
Get
Return onToggleColorField
End Get
Set(ByVal value As Color)
onToggleColorField = value
Me.Invalidate()
End Set
End Property
<Category("RJ Code Advance")>
Public Property OffBackColor As Color
Get
Return offBackColorField
End Get
Set(ByVal value As Color)
offBackColorField = value
Me.Invalidate()
End Set
End Property
<Category("RJ Code Advance")>
Public Property OffToggleColor As Color
Get
Return offToggleColorField
End Get
Set(ByVal value As Color)
offToggleColorField = value
Me.Invalidate()
End Set
End Property
<Browsable(False)>
Public Overrides Property Text As String
Get
Return MyBase.Text
End Get
Set(ByVal value As String)
End Set
End Property
<Category("RJ Code Advance")>
<DefaultValue(True)>
Public Property SolidStyle As Boolean
Get
Return solidStyleField
End Get
Set(ByVal value As Boolean)
solidStyleField = value
Me.Invalidate()
End Set
End Property
'Constructor
Public Sub New()
Me.MinimumSize = New Size(45, 22)
End Sub
'Methods
Private Function GetFigurePath() As GraphicsPath
Dim arcSize As Integer = Me.Height - 1
Dim leftArc As Rectangle = New Rectangle(0, 0, arcSize, arcSize)
Dim rightArc As Rectangle = New Rectangle(Me.Width - arcSize - 2, 0, arcSize, arcSize)
Dim path As GraphicsPath = New GraphicsPath()
path.StartFigure()
path.AddArc(leftArc, 90, 180)
path.AddArc(rightArc, 270, 180)
path.CloseFigure()
Return path
End Function
Protected Overrides Sub OnPaint(ByVal pevent As PaintEventArgs)
Dim toggleSize As Integer = Me.Height - 5
pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias
pevent.Graphics.Clear(Me.Parent.BackColor)
If Me.Checked Then 'ON
'Draw the control surface
If solidStyleField Then
pevent.Graphics.FillPath(New SolidBrush(onBackColorField), GetFigurePath())
Else
pevent.Graphics.DrawPath(New Pen(onBackColorField, 2), GetFigurePath())
End If
'Draw the toggle
pevent.Graphics.FillEllipse(New SolidBrush(onToggleColorField), New Rectangle(Me.Width - Me.Height + 1, 2, toggleSize, toggleSize)) 'OFF
Else
'Draw the control surface
If solidStyleField Then
pevent.Graphics.FillPath(New SolidBrush(offBackColorField), GetFigurePath())
Else
pevent.Graphics.DrawPath(New Pen(offBackColorField, 2), GetFigurePath())
End If
'Draw the toggle
pevent.Graphics.FillEllipse(New SolidBrush(offToggleColorField), New Rectangle(2, 2, toggleSize, toggleSize))
End If
End Sub
End Class
End Namespace
The binding code:
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Toggle1.Checked = My.Settings.ToggleState
End Sub
Private Sub Toggle1_CheckedChanged(sender As Object, e As EventArgs) Handles Toggle1.CheckedChanged
My.Settings.ToggleState = Toggle1.Checked
My.Settings.Save()
End Sub
My Settings:
Name: ToggleState, Type: Boolean, Scope: User, Value: True
Since I am barely a novice when it comes to coding, is there someway I can make the toggle function exactly as a checkbox, or allow it's state to be saved with My.Settings()? What am I missing to add that functionality to the toggle?
Environment: VB, .NET 6.0, Visual Basic 2022
When creating the new Application Setting, the type Boolean was assigned, and the Value assigned was True. In the form Designer, the Checked Property was also set to True. It seemed the Setting Value True or False would set the Toggle's default checked state. The Checked Value in the designer had to be set to false, in order to allow the New Setting to function properly with My.Settings().

add button to TreeNode

Good day.
There is a custom control that adds a button to each Node
Imports System.Windows.Forms.VisualStyles
Public Class CustomTreeView
Inherits TreeView
Private buttonRect As New Rectangle(80, 2, 50, 26)
Private ReadOnly stringFormat As StringFormat
Public Sub New()
SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
DrawMode = TreeViewDrawMode.OwnerDrawText
ShowLines = False
FullRowSelect = True
ItemHeight = 30
stringFormat = New StringFormat With {
.Alignment = StringAlignment.Near,
.LineAlignment = StringAlignment.Center
}
End Sub
Protected Overrides Sub OnDrawNode(ByVal e As DrawTreeNodeEventArgs)
e.Graphics.DrawString(e.Node.Text, Me.Font, New SolidBrush(Me.ForeColor), e.Bounds, stringFormat)
ButtonRenderer.DrawButton(e.Graphics, New Rectangle(e.Node.Bounds.Location + New Size(buttonRect.Location), buttonRect.Size), "btn", Me.Font, True, If(e.Node.Tag IsNot Nothing, CType(e.Node.Tag, PushButtonState), PushButtonState.Normal))
End Sub
Protected Overrides Sub OnNodeMouseClick(ByVal e As TreeNodeMouseClickEventArgs)
Select Case e.Node.Tag
Case Nothing, Is <> PushButtonState.Pressed
Return
End Select
e.Node.Tag = PushButtonState.Normal
MessageBox.Show(e.Node.Text & " clicked")
' force redraw
e.Node.Text = e.Node.Text
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
Dim tnode As TreeNode = GetNodeAt(e.Location)
If tnode Is Nothing Then
Return
End If
Dim btnRectAbsolute As New Rectangle(tnode.Bounds.Location + New Size(buttonRect.Location), buttonRect.Size)
If btnRectAbsolute.Contains(e.Location) Then
tnode.Tag = PushButtonState.Pressed
tnode.Text = tnode.Text
End If
End Sub
End Class
tell me how you can display the button only to the first (main) nod?
And how, when you click on this button, not display a message, but let's say call some procedure?
There is no built-in button tree node. But you can create a custom tree node having a button yourself. This custom tree node inherits from TreeNode. To improve extensibility, we declare an interface for tree nodes having a DrawNode method:
Imports System.Windows.Forms.VisualStyles
Public Interface ICustomDrawTreeNode
Sub DrawNode(ByVal e As DrawTreeNodeEventArgs, buttonState As PushButtonState)
End Interface
We also create a module containing some settings used in the custom tree view and in the custom tree node
Module Settings
Public ReadOnly ButtonRect As New Rectangle(80, 2, 50, 26)
Public ReadOnly TextStringFormat = New StringFormat() With {
.Alignment = StringAlignment.Near,
.LineAlignment = StringAlignment.Center,
.FormatFlags = StringFormatFlags.NoClip Or StringFormatFlags.FitBlackBox Or StringFormatFlags.LineLimit
}
End Module
We can then implement a button node like this
Imports System.Windows.Forms.VisualStyles
Public Class ButtonTreeNode
Inherits TreeNode
Implements ICustomDrawTreeNode
Private ReadOnly buttonText As String
Public Sub New(text As String, buttonText As String)
MyBase.New(text)
Me.buttonText = buttonText
End Sub
Public Sub DrawNode(e As DrawTreeNodeEventArgs, buttonState As PushButtonState) _
Implements ICustomDrawTreeNode.DrawNode
Dim font As Font = e.Node.TreeView.Font
' Draw Text to the left of the button
Dim rect As Rectangle = New Rectangle(
e.Node.Bounds.Location,
New Size(Settings.ButtonRect.Left, e.Bounds.Height))
e.Graphics.DrawString(e.Node.Text, font, Brushes.Black, rect, Settings.TextStringFormat)
' Draw the button
rect = New Rectangle(
e.Node.Bounds.Location + Settings.ButtonRect.Location,
Settings.ButtonRect.Size)
ButtonRenderer.DrawButton(e.Graphics, rect, buttonText, font, True, buttonState)
End Sub
End Class
It has a Private ReadOnly buttonText As String to store the text of the button. The normal node text and the button text are passed in the constructor of ButtonTreeNode:
Public Sub New(text As String, buttonText As String)
The DrawNode method will be called be the CustomTreeView in OnDrawNode.
In CustomTreeView I declared a NodeButtonClick event that will be raised when the button of a node is clicked. You can then handle this event in the form. When you select the CustomTreeView in the designer, this new event will appear in the "Action" section of the events.
Imports System.ComponentModel
Imports System.Windows.Forms.VisualStyles
Public Class CustomTreeView
Inherits TreeView
<Category("Action")>
Public Event NodeButtonClick(e As TreeNodeMouseClickEventArgs)
Private _isButtonPressed As Boolean
Public Sub New()
SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
DrawMode = TreeViewDrawMode.OwnerDrawText
ShowLines = False
FullRowSelect = True
ItemHeight = 30
End Sub
Protected Overrides Sub OnDrawNode(e As DrawTreeNodeEventArgs)
Dim customDrawNode As ICustomDrawTreeNode = TryCast(e.Node, ICustomDrawTreeNode)
If customDrawNode Is Nothing Then ' Normal text node.
e.Graphics.DrawString(e.Node.Text, Font, Brushes.Black, e.Node.Bounds, Settings.TextStringFormat)
Else
customDrawNode.DrawNode(e, If(_isButtonPressed, PushButtonState.Pressed, PushButtonState.Normal))
End If
End Sub
Protected Overrides Sub OnNodeMouseClick(e As TreeNodeMouseClickEventArgs)
If _isButtonPressed Then
_isButtonPressed = False
Refresh()
Dim buttonNode = TryCast(e.Node, ButtonTreeNode)
If buttonNode IsNot Nothing Then
RaiseEvent NodeButtonClick(e)
End If
End If
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
Dim buttonNode = TryCast(GetNodeAt(e.Location), ButtonTreeNode)
If buttonNode IsNot Nothing Then
Dim btnRectAbsolute As New Rectangle(
buttonNode.Bounds.Location + Settings.ButtonRect.Location,
Settings.ButtonRect.Size)
_isButtonPressed = btnRectAbsolute.Contains(e.Location)
If _isButtonPressed Then
Refresh()
End If
End If
End Sub
End Class
In the form you can write
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TreeView1.Nodes.Add("Text")
TreeView1.Nodes.Add(New ButtonTreeNode("Caption", "Button"))
End Sub
Private Sub TreeView1_NodeButtonClick(e As TreeNodeMouseClickEventArgs) _
Handles TreeView1.NodeButtonClick
MessageBox.Show(e.Node.Text & " clicked")
End Sub
End Class
This adds a normal text node and a custom button node to the TreeView. It also handles the NodeButtonClick of the custom TreeView.

Changing 'lamp' Colour Indicator within the Graphical User Interface (Visual Studio 2019)

I would like to change the colour within a single circular indicator within a Graphical User Interface, so that it shows when an action is completed or when it fails ['two tone green/red LED']. I've looked through the inbuilt presets within the Toolbox but have been unable find anything.
I would therefore be grateful for any assistance.
I've found this code on the msdn.microsoft.com forum, which changes the colour of the centre of the 'dot' when you press the RadioButton.
Private Sub RadioButton_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles RadioButton1.Paint, RadioButton2.Paint
If DirectCast(sender, RadioButton).Checked Then
e.Graphics.FillEllipse(Brushes.Red, New RectangleF(2.5, 4.7, 7.2, 7.2))
End If
So have incorporated it into my code, its not at all elegant and there is clearly room for improvement, but it does work.
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If My.Computer.Network.Ping("192.168.0.1") Then
RadioButton1.ForeColor = Color.Green
RadioButton1.ForeColor = Color.Black
Else
RadioButton1.ForeColor = Color.Red
RadioButton1.ForeColor = Color.Black
End If
End Sub
Private Sub RadioButton_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles RadioButton1.Paint
If My.Computer.Network.Ping("192.168.0.1") Then
e.Graphics.FillEllipse(Brushes.Green, New RectangleF(2.5, 4.7, 7.2, 7.2))
Else
e.Graphics.FillEllipse(Brushes.Red, New RectangleF(2.5, 4.7, 7.2, 7.2))
End If
End Sub
Explanation: when the 'Test Network' button is pressed it sends out a network ping, and depending upon the return the Network RadioButton 'dot' changes colour to either Green or Red,
Here's ON/OFF LED control.
Add a new class to your project, name it say OnOffLed.vb, copy the code below and paste it in the new class.
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Drawing2D
Public Class OnOffLed
Inherits Panel
Public Enum LedState
[On]
Off
End Enum
Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or
ControlStyles.OptimizedDoubleBuffer Or
ControlStyles.ResizeRedraw Or
ControlStyles.UserPaint, True)
UpdateStyles()
End Sub
Private _state As LedState = LedState.Off
Public Property State As LedState
Get
Return _state
End Get
Set(value As LedState)
_state = value
Invalidate()
End Set
End Property
Private _onText As String
Public Property OnText As String
Get
Return _onText
End Get
Set(value As String)
_onText = value
Invalidate()
End Set
End Property
Private _offText As String
Public Property OffText As String
Get
Return _offText
End Get
Set(value As String)
_offText = value
Invalidate()
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim rec As New Rectangle(2, 2, Height - 5, Height - 5)
Dim recText As New Rectangle(Height + 2, 1, Width - (Height - 2), Height)
Dim G As Graphics = e.Graphics
G.SmoothingMode = SmoothingMode.AntiAlias
G.Clear(Parent.BackColor)
If _state = LedState.On Then
Dim cb As New ColorBlend With {
.Colors = {Color.Green, Color.DarkGreen, Color.Green},
.Positions = {0, 0.5, 1}
}
Using lgb As New LinearGradientBrush(rec, Color.Empty, Color.Empty, 90.0F) With {.InterpolationColors = cb}
G.FillEllipse(lgb, rec)
End Using
Else
Dim cb As New ColorBlend With {
.Colors = {Color.Red, Color.DarkRed, Color.Red},
.Positions = {0, 0.5, 1}
}
Using lgb As New LinearGradientBrush(rec, Color.Empty, Color.Empty, 90.0F) With {.InterpolationColors = cb}
G.FillEllipse(lgb, rec)
End Using
End If
G.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
Using br As New SolidBrush(ForeColor)
Using sf As New StringFormat With {.Alignment = StringAlignment.Near, .LineAlignment = StringAlignment.Center}
G.DrawString(If(_state = LedState.On, _onText, _offText), Font, br, recText, sf)
End Using
End Using
End Sub
End Class
Rebuild your project.
In the ToolBox under your project's component tab, you'll find the new control. OnOffLed. Drop it in your form as you drop any other control.
You can toggle the state through the State property, set different text if you need that for each state through the OnText and OffText properties.
Usage Example:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If My.Computer.Network.Ping("192.168.2.01") Then
OnOffLed1.State = OnOffLed.LedState.On
Else
OnOffLed1.State = OnOffLed.LedState.Off
End If
End Sub
Good luck.

Vertical text in windows form using onPaint

I found this Vertical Text on Button Control I thought that looks easy but I can't get it to work.
Public Class VerticalButton3
Inherits System.Windows.Forms.Button
Private _VerticalText As String
Public Property VerticalText() As String
Get
Return _VerticalText
End Get
Set(ByVal value As String)
_VerticalText = value
End Set
End Property
Private Fmt As New StringFormat
Public Sub New()
Fmt.Alignment = StringAlignment.Center
Fmt.LineAlignment = StringAlignment.Center
End Sub
Protected Overrides Sub OnPaint(ByVal PaintEvt As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint (PaintEvt)
PaintEvt.Graphics.TranslateTransform(Width, 0)
PaintEvt.Graphics.RotateTransform (90)
PaintEvt.Graphics.DrawString(_VerticalText, Font, Brushes.Black, New Rectangle(0, 0, Height, Width), Fmt)
End Sub
End Class
But I get both vertical and horizontal text.
I tried to use Public Overrides Property Text() similar to Vertical Label Control in VB.NET but that didn't work either
How do I get the vertical text only?
I tested your code. It works as you require if you set the Text Property to ""
Here is the code I tried
Private WithEvents vbtn As New VerticalButton3
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
vbtn.Top = 0
vbtn.Left = 0
vbtn.Text = "" ' Note Text property is set to ""
vbtn.VerticalText = "Vertical"
vbtn.Height = 100
Controls.Add(vbtn)
End Sub
Alternatively you can use Text="" in the Constructor of your class
Public Sub New()
Fmt.Alignment = StringAlignment.Center
Fmt.LineAlignment = StringAlignment.Center
Text = ""
End Sub
Edit: I think it is a better to override the Text Property itself, because if by mistake the Text property is set the both may show up. Here is how you can override the Text Property (you may no longer need the VerticalText property).
Public Shadows Property Text
Get
Return _VerticalText
End Get
Set(ByVal value)
_VerticalText = value
End Set
End Property

Highlighting around textboxes

I am trying to draw a highlighted border around a custom textbox control so that I can reuse the highlighting feature for each new program I create. My approach so far has been to override the paint event in the control library (dll) after the custom property I have created is set. The code for the control is below.
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Drawing
Imports System.ComponentModel.Design
<ToolboxBitmap(GetType(Button))>
Public Class Textbox_Custom
Inherits System.Windows.Forms.TextBox
Public Event OnEnterKeyPress()
Public Event MissingInfo_Change As EventHandler
Dim iMissing_Info As Boolean
Dim iCharacterInput As Cinput
Public Property CharacterInput As Cinput
'<Browsable(True), DefaultValue("AllowAll")>
Get
Return Me.iCharacterInput
End Get
Set(ByVal value As Cinput)
Me.iCharacterInput = value
End Set
End Property
Public Property Missing_Info As Boolean
'<Browsable(True), DefaultValue(True)>
Get
Return iMissing_Info
End Get
Set(value As Boolean)
iMissing_Info = value
**MyBase.Refresh()**
End Set
End Property
Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
MyBase.OnKeyPress(e)
If Asc(e.KeyChar) = 13 Then
RaiseEvent OnEnterKeyPress()
End If
Select Case Me.iCharacterInput
Case Cinput.CharactersOnly
If IsNumeric(e.KeyChar) Then
e.Handled = True
End If
Case Cinput.NumericOnly
If Not IsNumeric(e.KeyChar) And Asc(e.KeyChar) <> 8 Then
e.Handled = True
End If
End Select
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
**If iMissing_Info = True Then**
Dim rect As New Rectangle(New Point(0, 0), New Size(Me.Size.Width + 2, Me.Size.Height + 2))
Dim pen As New Pen(Brushes.OrangeRed, 2)
e.Graphics.DrawRectangle(pen, rect)
e.Dispose()
End If
End Sub
End Class
Public Enum Cinput
AllowAll
NumericOnly
CharactersOnly
End Enum
While debugging I have set a breakpoint in the OnPaint override (lines **), but it never hits it. I then put a breakpoint in the Set section of the Missing_Info property where I am trying to invalidate the control to redraw. It does hit the MyBase.Refresh breakpoint so I don't understand what I've missed.
I realize there have been several other posts on this topic, but from what I can tell they seem to require putting panels behind the control. I feel like I should be able to include this action in a custom control and not have to code a new highlighting section for each new project. Thanks for any help in advance.
In the end I decided to just go with changing the control background to a semi-transparent red color which should be obvious enough for what I'm doing.