Introduction
This is my very first article to any open source site. Since I've gotten a lot useful
article from this site, I'll be glad if I can to contribute to this
great site.
This article will explain
how to make a button that has a glow feature.
Background (optional)
When I installed Windows Vista, I was amazed by it's appearance. It had a very nice user interface and so many eye candy controls. That make me think about making something
just like that. I've created some fancy controls that look like Vista components
since that day. Also, I've always thought about making an article or tutorial to share
my knowledge. Finally, while creating this glow button control, I've decided to make
an article for it too.
So why Glow Button? I've been interested in this control since I played with Vista Windows,
especially with its Minimize, Maximize and Close Buttons. They have some fancy glow
affects. And thanks to .NET Framework 2.0, it's easier to create them.
Using the code
Basically, to create the glow effect, you have to make a "Layer" that will create the
glow with GDI+. Unfortunately, .NET Framework 2.0 doesn't allow a control that can
make other controls mid-transparent. Or rather, when you place a control
above another control, you can't see the control below, even you set full transparency
at the upper control. The trick for this button is to request from another button
that surrounds it to make a glow layer for that control.
Since we want to ask other glow controls to make glow effects, we need a layer status
for the control:
Public Enum LayerStatus
None = 0
Self = 1
TopLeft = 2
Top = 3
TopRight = 4
Left = 5
Right = 6
BottomLeft = 7
Bottom = 8
BottomRight = 9
End Enum
Now we have a status for the control to make layer as requested. If we must ask
another surrounding button to make glow effect, how can we do that if the button
is at the edge, side, top, bottom etc? For this problem, we need a special container
for our control, so the control at edge or side can ask this container to make the
glow effect. Let's name it "Grid".
Another feature that we will add is the ability to change themes dynamically. For this,
we will use a colortable class called GlassColorTable
and some defined colors
for our control. Let's name it ColorSet
. Also remember that a button
has four default states, which is: Normal, Highlighted (Mouse Over), Pressed and Disabled.
For the moment, I'm not including Disabled state, due to to the fact that I don't have enough
time to experiment with it. I'll include it when I update my article.
Public Interface IGlassColor
Enum States
Normal = 0
Highlighted = 1
Pressed = 2
Disabled = 3
End Enum
Sub NormalState()
Sub HighlightState()
Sub PressedState()
Sub DisabledState()
End Interface
Public Class ColorSet
Public BackgroundHigh As Color
Public TextColor As Color
Public BackgroundHighFocus As Color
Public TextColorFocus As Color
Public GlowCenter As Color
End Class
Public Class GlassColorTable
Implements IGlassColor
Protected _BackgroundHigh As Color
Protected _BackgroundLow As Color
Protected _ShineHigh As Color
Protected _ShineLow As Color
Protected _BorderLeft As Color
Protected _BorderRight As Color
Protected _BorderTop As Color
Protected _BorderBottom As Color
Protected _TextColor As Color
Protected _GlowCenter As Color
Private _State As IGlassColor.States
Private _cSet As ColorSet
Public Overridable ReadOnly Property BackgroundLow() As Color
Get
Return _BackgroundHigh
End Get
End Property
End Class
To change themes dynamically, we must create a property.
<Browsable(False)> _
Public Property Renderer() As ColorSet
Get
Return _ColorTable.Renderer
End Get
Set(ByVal value As ColorSet)
_ColorTable.Renderer = value
_ColorTable.State = IGlassColor.States.Normal
Me.Refresh()
End Set
End Property
Since we now have the ability to change themes for the button, we must let the button
know which color we want to be layered from another control.
<Browsable(False)> _
Public Property LayerColor() As Color
Get
Return _ColorTable.GlowCenter
End Get
Set(ByVal value As Color)
_LayerColor = value
End Set
End Property
So, the most important part is done. It's time to use them for our application.
Since we must ask help from another control to make the glow effect, we must set
up in each control events which are "mouse enter" and "mouse leave" events.
Private Sub GlowButton1_MouseEnter(ByVal sender As Object,
ByVal e As System.EventArgs) Handles GlowButton1.MouseEnter
GlowButton2.Layer = GlowingButton.GlowButton.LayerStatus.Left
GlowButton4.Layer = GlowingButton.GlowButton.LayerStatus.Top
GlowButton5.Layer = GlowingButton.GlowButton.LayerStatus.TopLeft
GlowButton2.LayerColor = GlowButton1.LayerColor
GlowButton4.LayerColor = GlowButton1.LayerColor
GlowButton5.LayerColor = GlowButton1.LayerColor
Grid1.GlowColor = GlowButton1.LayerColor
Grid1.GlowStartPoint = New Point(GlowButton1.Location.X - 7,
GlowButton1.Location.Y - 7)
Grid1.GlowStyle = GlowingButton.Grid.GlowStyles.TopLeft
End Sub
Private Sub GlowButton1_MouseLeave(ByVal sender As Object,
ByVal e As System.EventArgs) Handles GlowButton1.MouseLeave
GlowButton2.Layer = GlowingButton.GlowButton.LayerStatus.None
GlowButton4.Layer = GlowingButton.GlowButton.LayerStatus.None
GlowButton5.Layer = GlowingButton.GlowButton.LayerStatus.None
Grid1.GlowStyle = GlowingButton.Grid.GlowStyles.None
End Sub
To change themes dynamically, use the Renderer
property.
For Each g As GlowingButton.GlowButton In Grid1.Controls
g.Renderer = New GlowingButton.DiamondRed
Next
Points of Interest
Since we need to ask other controls to apply effects, we have to setup
every control we have in the application. It will take time to setup everything,
especially when we work with many buttons. To solve this problem, I suggest you
make a class that inherits Grid control, place all glow buttons in the grid, and perform the required setup automatically
with AddHandler
methods. When I have more spare time, I'll explain in separate
articles about this.
Additional notes about the demo: did some of you notice my other reason for creating
this control? Yes, it's a Sudoku puzzle! My original motive with this control was for
creating a Sudoku Puzzle Solver that can apply customized regions (that's why it
needed themes or colorsets). The solver itself is still a long way to go because I've
include it with many useful features.
That's all.
History
April 20th, 2007: Original Article.