![]() |
Desktop Development »
Button Controls »
General
Intermediate
License: The Code Project Open License (CPOL)
Custom Button Control with Gradient Colors and Extra Image (VB.NET)By SSDiver2112This is a simple to use custom button control, but with a lot of visual design options. |
VB, Windows, .NET 2.0, GDI+, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
The CButton is a simple custom button control written in VB.NET. Sorry I didn't realize the "C" prefix was a language specific thing when I started. It is just short for Custom Button. I won't let it happen again. This is a great alternative to the plain Microsoft button.
Here is a list of the primary features:
I improved design time editing in Version 1.2 by adding UITypeEditors and ControlDesigners. See UITypeEditorsDemo[^] for a detailed explanation. This enabled me to combine some properties into one single property, or improve on others.
For example:
ButtonColorA, ButtonColorB, and ButtonColorC were combined into ColorFillBlend allowing unlimited Color blend instead of being limited to only three colors ButtonColorCenterPoint, and ButtonColorCenterPtOffset were combined into FocalPoints CornerRadius became an expandable property Corners allowing each corner to be adjusted separately
Here is another example of needing (well, let's be honest, a plain button would work, so I wanted) a better looking and visually versatile button. There are a lot of great button controls already, but not with all the features I was looking for. Basically, I created the properties I was looking for, and then took over the OnPaint to draw it the way I wanted.
Here is a list of the primary properties:
Shape
What shape the button is (Rectangle, Ellipse, Triangle)
ColorFillBlend
Colors to use in gradient blend fills
BorderColor, BorderShow
Show the border in a different color
FillType
What color gradient type to use (Solid, Linear, or Path)
FocalPoints
CenterPoint and FocusScales for Path Gradient Type Fills
Corners
Radius for each corner arc
DimFactorHover, DimFactorClick
Number to adjust the buttons color during mouse rollover and click
TextShadow, TextShadowShow
Show or not show the shadow of the text and in what color
TextMargin
Push the text away from the inside edge of the button
SideImage
Add an extra image that can be placed outside the button surface
Padding
Offset the edges of the ButtonArea from the edge of the Control
Once you get the CButton designed the way you want, there isn't really any complicated code. Just use it like a normal button.
Because the Click event fires if you click anywhere on the control, I added the ClickButtonArea event in Version 1.1 to fire only when the mouse clicks inside the button part of the control.
'Add a new Click event for only when the ButtonArea is Clicked
Public Event ClickButtonArea(ByVal Sender As Object, ByVal e As EventArgs)
Private Sub CButton_MouseUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
If MouseDrawState = eMouseDrawState.Down _
Then RaiseEvent ClickButtonArea(Me, New EventArgs)
MouseDrawState = eMouseDrawState.Up
Me.Invalidate(ButtonArea)
End Sub
The control is just a process of layering the parts together in the right positions. There are four main areas to track. The control area, button area, text area, and image area. The button area is reduced from the control area by the control padding values. The text area is reduced from the button area by the text margin values and the image area. The image area is based on the image size. The items are placed into these areas based on their layout options.
Protected Overrides Sub _
OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
'Gray the Text and Border Colors if Disabled
Dim bColor, tColor, tsColor As Color
If Me.Enabled Then
bColor = _BorderColor
tColor = Me.ForeColor
tsColor = _TextShadow
Else
bColor = GrayTheColor(_BorderColor)
tColor = GrayTheColor(Me.ForeColor)
tsColor = GrayTheColor(_TextShadow)
End If
Dim MyPen As New Pen(bColor)
MyPen.Alignment = PenAlignment.Inset
'Shrink the Area so the Border draws correctly, _
'then trim off the Padding to get the button surface area
ButtonArea = AdjustRect(New Rectangle(0.5, 0.5, _
Me.Size.Width - 1, Me.Size.Height - 1), Me.Padding)
'Create the ButtonArea Path
Dim gp As GraphicsPath = GetPath()
If Me.BackgroundImage Is Nothing Then
'Color the ButtonArea with the right Brush
Select Case Me.FillType
Case eFillType.Solid
Using br As Brush = New SolidBrush(GetFill)
e.Graphics.FillPath(br, gp)
End Using
Case eFillType.GradientPath
Using br As PathGradientBrush = New PathGradientBrush(gp)
Dim cb As New ColorBlend
cb.Colors = GetFillBlend()
cb.Positions = Me.ColorFillBlend.iPoint
br.FocusScales = FocalPoints.FocusScales
br.CenterPoint = New PointF( _
Me.Width * FocalPoints.CenterPoint.X, _
Me.Height * FocalPoints.CenterPoint.Y)
br.InterpolationColors = cb
e.Graphics.FillPath(br, gp)
End Using
Case eFillType.GradientLinear
Using br As LinearGradientBrush = New LinearGradientBrush( _
ButtonArea, Color.White, Color.White, FillTypeLinear)
Dim cb As New ColorBlend
cb.Colors = GetFillBlend()
cb.Positions = Me.ColorFillBlend.iPoint
br.InterpolationColors = cb
e.Graphics.FillPath(br, gp)
End Using
End Select
End If
If BorderShow Then
e.Graphics.DrawPath(MyPen, gp)
End If
gp.Dispose()
Dim ipt As Point = ImageLocation(GetStringFormat(Me.SideImageAlign), _
Me.Size, Me.SideImageSize)
'Put the SideImage behind the Text
If SideImageBehindText AndAlso Me.SideImage IsNot Nothing Then
e.Graphics.DrawImage(EnableDisableImage(Me.SideImage), ipt.X, ipt.Y, _
Me.SideImageSize.Width, Me.SideImageSize.Height)
End If
'Layout the Text and Image on the button surface
SetImageAndText(e.Graphics)
If Not Me.Image Is Nothing Then
e.Graphics.DrawImage(EnableDisableImage(Me.Image), Imagept.X, Imagept.Y, _
Me.ImageSize.Width, Me.ImageSize.Height)
End If
'Draw the Text and Shadow
If TextShadowShow Then
TextArea.Offset(1, 1)
e.Graphics.DrawString(Me.Text, Me.Font, _
New SolidBrush(tsColor), TextArea, GetStringFormat(Me.TextAlign))
TextArea.Offset(-1, -1)
End If
e.Graphics.DrawString(Me.Text, Me.Font, _
New SolidBrush(tColor), TextArea, GetStringFormat(Me.TextAlign))
'Put the SideImage in front of the Text
If Not SideImageBehindText AndAlso Not Me.SideImage Is Nothing Then
e.Graphics.DrawImage(EnableDisableImage(Me.SideImage), ipt.X, ipt.Y, _
Me.SideImageSize.Width, Me.SideImageSize.Height)
End If
MyPen.Dispose()
End Sub
To Gray the colors when the control is disabled, I used two methods:
To Gray a single color, I used this Function:
Function GrayTheColor(ByVal GrayColor As Color) As Color
Dim gray As Integer = _
CInt(GrayColor.R * 0.3 + GrayColor.G * 0.59 + GrayColor.B * 0.11)
Return Color.FromArgb(GrayColor.A, gray, gray, gray)
End Function
To Gray an Image, I used this Function:
Private Function EnableDisableImage(ByVal img As Image) As Bitmap
If Me.Enabled Then Return img
Dim bm As Bitmap = New Bitmap(img.Width, img.Height)
Dim g As Graphics = Graphics.FromImage(bm)
Dim cm As ColorMatrix = New ColorMatrix(New Single()() _
{New Single() {0.5, 0.5, 0.5, 0, 0}, _
New Single() {0.5, 0.5, 0.5, 0, 0}, _
New Single() {0.5, 0.5, 0.5, 0, 0}, _
New Single() {0, 0, 0, 1, 0}, _
New Single() {0, 0, 0, 0, 1}})
Dim ia As ImageAttributes = New ImageAttributes()
ia.SetColorMatrix(cm)
g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), 0, 0, _
img.Width, img.Height, GraphicsUnit.Pixel, ia)
g.Dispose()
Return bm
End Function
New in Version 1.5, when the FillType is GradientPath a small square and circle selection will appear on the control. Drag the circle around to move the CenterPoint, and drag the square to move the FocusScales. Check out the UITypeEditorsDemo link above to see an explanation of this feature.
ClickButtonArea event UITypeEditors and ControlDesigner FocalPoints and Corners properties to immediately refresh the control when the child properties are changed in the PropertyGridFocalPoints Modal UITypeEditor and added direct adjustment of the points on the design surface
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 24 Dec 2008 Editor: Deeksha Shenoy |
Copyright 2008 by SSDiver2112 Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |