I really like the glow effect around a focused
Textbox when inputting data on a form on a Chrome web page. It really makes it easier to track your position and enter data. I wanted to have this same effect on a Winform. I thought, here we go again with another big control project, but to my surprise I got the basic control working in no time with very little code. Especially since I borrowed the glow part from one of my other controls. For more details on how the glow technique is achieved, check out the gLabel[^] control.
Using the Code
gGlowBox Inherits a
Panel, resizes to fit one child control (any control, not just a
Textbox), and activates and deactivates the glow effect when the child control gets or loses focus.
There are only three new properties:
Get or set the color of the glow.
Turn the glow effect on or off.
EffectType As eEffectType
GlowColor As Color
GlowOn As Boolean
Simple to use: Drop the
gGlowBox on a
Form, set the
GlowColor, drop a control in the
gGlowBox will resize automatically to fit the child control), and resize if needed.
In version 1.0.1, from Yogi Yang's suggestion, I added a new control that can handle a group of controls. I added the
gGlowGroupBox rather than replace the original control to allow more flexibility. The main coding difference is the
gGlowGroupBox has the re-sizing methods removed.
In version 1.0.2, from N. Henrik Lauridsen's suggestion, I added a Drop Shadow option to the
In version 1.0.4, it was suggested that I implement the
IExtenderProvider to extend the
glow property to each control added to the
gGlowGroupBox. Well, I jumped right on it and a short seven years later, I did it.
Points of Interest
Design Time View - gGlowBox
Design Time View - gGlowGroupBox
Using the technique explained in the gLabel[^] control, a blurred rectangle is drawn around the edge of the
gGlowBox. Because the
gGlowBox is slightly bigger than the child control, it creates a glowing effect around the child control. For the
DropShadow, the Blurred Rectangle is drawn at an offset.
gGlowGroupBox acts as a
Panel to hold a group of controls. The
Glow will be painted around each control when it recieves focus. As of this version, the glow and its color can be set individually and uniquely for each control that can receive focus.
Sizing the gGlowBox and the Child Control
To make sizing easier, the
gGlowBox sizes itself automatically to the child control.
First, if the child control is Added or Resized, the
Layout event fires and resizes the
gGlowBox to match up with the child control.
Private Sub gGlowBox_Layout(ByVal sender As Object, _
ByVal e As LayoutEventArgs) Handles Me.Layout
If Controls.Count > 0 Then
If e.AffectedControl Is Controls(0) Then
Size = New Size(Controls(0).Width + 7, Controls(0).Height + 7)
Controls(0).Location = New Point(4, 4)
Second, when the
gGlowBox is resized, the
Resize event will size the child control to fit inside the
gGlowBox. An anchored
gGlowBox will not return to its original size when the
Parent form is minimised unless this step is skipped, so a check is made to see what the
WindowState is first.
Private Sub gGlowBox_Resize(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Me.Resize
If IsNothing(FindForm) OrElse
FindForm.WindowState = FormWindowState.Minimized Then Exit Sub
If Controls.Count > 0 Then
Controls(0).Size = New Size(Width - 7, Height - 7)
Control Focus Event Wire-up
The child control's
LostFocus events are added to the
gGlowBox in the
ControlAdded event and point to the
ChildLostFocus methods. These methods simply turn the glow on and off.
Private Sub gGlowBox_ControlAdded(ByVal sender As Object,_
ByVal e As ControlEventArgs) Handles Me.ControlAdded
AddHandler e.Control.GotFocus, AddressOf ChildGotFocus
AddHandler e.Control.LostFocus, AddressOf ChildLostFocus
As an extra note, I did not want the glow to turn on if the
Textbox was set to
ReadOnly. Simple if the child control was always going to be a
Textbox, but the
gGlowBox was designed to house any basic control. Some controls like the
Combobox do not have this property. To deal with this, I used the
GetProperty function to check if the unknown control has that property and if it does, use the
CallByName method to get the value.
Private Sub ChildGotFocus()
If Controls.Count > 0 Then
If Not IsNothing(Controls(0).GetType().GetProperty("ReadOnly")) Then
GlowOn = Not CallByName(Controls(0), "ReadOnly", CallType.Get)
GlowOn = True
Private Sub ChildLostFocus()
GlowOn = False
As usual, documentation was limited and obscure. The basic idea is to define the properties that will extend to the child controls on the
gGlowGroupBox. An example is like when a ToolTip component is added to the form and the ToolTip text property appears magically on all the controls on the form.
The properties to be extended are not created like a standard property in a class, and they are not actually a direct part of the child control. The
gGlowGroupBox keeps a collection of the references to each control and its properties which are projected to the control where it can be interacted with and the change is not saved to the control, but instead is projected back to the
gGlowGroupBox) to be saved back into the Collection.
IExtenderProvider and ProvideProperty
First of all, the Class must Implement the
Public Class gGlowGroupBox
ProvidePropertyAttribute is added to the
Class for each property like this
This is the complete Header. Though the child controls only have three properties, I had to use four due to a serialization issue that I will explain shortly.
<ToolboxItem(True), ToolboxBitmap(GetType(gGlowBox), "gControlLib.gGlowGroupBox.bmp")>
Public Class gGlowGroupBox
IExtenderProvider must have a
CanExtend Function to define which child control should have the extended properties. I could have just put
If TypeOf extendee Is Control Then Return True (where
extendee is the control on the
gGlowGroupBox), but I do not want the properties to appear on an non-focusable controls like a
Also in the
CanExtend is a function called
GetControlStyle that uses Reflection to get the
ControlStyle out of the control. I used this to get the Selectable value since there isn't a focusable property to check. There are two checks for
ContainerControl. One is to find normal
ContainerControls like a
Panel and the other uses the
ControlStyle to check for controls such as
UserControls that have this
ControlStyle set to
Public Function CanExtend(extendee As Object) As Boolean Implements IExtenderProvider.CanExtend
If (TypeOf extendee Is Control AndAlso CType(extendee, Control).Parent Is Me) Then
If GetControlStyle(CType(extendee, Control), ControlStyles.ContainerControl) = False AndAlso
GetControlStyle(CType(extendee, Control), ControlStyles.Selectable) = True Then
If TypeOf extendee Is ContainerControl Then Return False
Private Class GlowProperties
Public UseEffect As Boolean
Public GlowColor As Color
Public EffectType As eEffectType
Public Sub New(GlowColorDef As Color, EffectTypeDef As eEffectType)
UseEffect = True
GlowColor = GlowColorDef
EffectType = EffectTypeDef
Private glowProps As New Hashtable
The control references and properties will be stored in a
HashTable with the control as the Key and the Properties class object as the Value.
To create the extended properties, two functions are needed to
Set the values. The format requires that the
Function name is GetXXX and SetXXX where XXX = Property Name defined in the
ProvideProperty Attribute. So
<ProvideProperty("UseEffect", GetType(Control))> would be defined like this with the
EnsurePropertiesExists() function ensuring there is a valid property value returned.
<Description("Set if this Control creates a Focus Glow")>
Public Function GetUseEffect(g As Control) As Boolean
Public Sub SetUseEffect(g As Control, value As Boolean)
EnsurePropertiesExists(g).UseEffect = value
All went well until I created the Property for the
Color does not Serialize automatically. The Designer quickly let me know this fact. To get around this problem, I created a
Class object (
Public Class SerialColor) with properties that could be serialized to and from a
Color object. At its base level, the
Color object has A, R, G, B Properties for the Alpha, Red, Green, and Blue properties, and sometimes a
GetGlowColor needs to be of Type
Color so the property in the
PropertyGrid has the normal
Color Type Editor in the Design window, but it can't be serialized to the Designer. To fix this, the Attribute
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) is added to the
GetGlowColor Property. But the value must be serialized somehow to the designer so it will persist after a build and not reset or error out. An extra property (
sGlowColor) of Type
SerialColor is added with the
Browsable(False) Attribute so it will not appear in the
PropertyGrid. The serializable color value is saved to and from the designer and gets and sets the real
GlowColor Color property seen in the Design window. TaDa!
Public Function GetGlowColor(g As Control) As Color
Public Sub SetGlowColor(g As Control, value As Color)
EnsurePropertiesExists(g).GlowColor = value
Public Function GetsGlowColor(g As Control) As SerialColor
Return New SerialColor(EnsurePropertiesExists(g).GlowColor)
Public Sub SetsGlowColor(g As Control, value As SerialColor)
EnsurePropertiesExists(g).GlowColor = value.DeserializeColor()
- Version 1.0.0
- Version 1.0.1
gGlowGroupBox from Yogi Yang's suggestion
- Version 1.0.2
DropShadow Option to the
gGlowGroupBox from N. Henrik Lauridsen's suggestion
- Version 1.0.4
IExtenderProvider to extend the properties to each individual control on the
I first got hooked on programing with the TI994A. After it finally lost all support I reluctantly moved to the Apple IIe. Thank You BeagleBros for getting me through. I wrote programs for my Scuba buisness during this time. Currently I am a Database manager and software developer. I started with VBA and VB6 and now having fun with VB.NET/WPF/C#...