Title: Windows Forms Application Hot Track Button (Windows 7 Style)
Author: Paul Goldhawk
Email: paul@k2workflow.com
Member ID: 3518484
Language: C#
Platform: Windows
Technology: Windows Forms
Level: Advanced
Description: How to create windows forms hot track buttons.
Section Windows Forms UI
SubSection Button Paint Overrides
License: GNU
Introduction
I created the code to give my applications the Windows 7 feel and not be bound by the WPF themes. In my research in to how to do it I saw a great deal of developers looking for similar things. So here is my solution to the problem.
Background
I first did this as a button then I moved it to a User Control with numerous overloads.
Using the code
In order to use the code Copy the CustomControl to your project change the namespace to you projects namespace and compile. You should the see it in your toolbox.
In order to use the button click event toy will need to subscribe to the controls event by adding the following code to the load of your form.
<code>
sC_Button1.SC_Button_Clicked += new SC_Button.SC_Button_ClickEventr(SC_Button_Clicked)
void SC_Button_Clicked(object sender, EventArgs e)
{
Environment.Exit(0)
}</code>
Points of Interest
In order to get a similar effect to the HotTrack effects I need to use a LinearGradientBrush at an angle roughly 90 degrees to the position of the mouse whilst over the control. In order to do this without using sine functions I chose to use 45 * X mouse position in the control where the left of the control is -1 and the right of the control is +1. I used this angle to set the Gradient of the LinearGradientBrush.
In order for the button click to work I bubbled up the click event to the User Control
This is a sample of the custom user control that I made. If you want shaped buttons then you can use transparent images with a solid border of the shape that you would like. Bear in mind though it should match the form or control that the control is on.
<code>
#region -- Unsing --
using System
using System.Collections.Generic
using System.ComponentModel
using System.Drawing
using System.Data
using System.Linq
using System.Text
using System.Windows.Forms
using System.Drawing.Drawing2D
#endregion
namespace WindowsFormsApplication1
{
public partial class SC_Button : UserControl
{
#region -- Delegates --
public delegate void SC_Button_ClickEventr(object sender, EventArgs e)
#endregion
#region -- Events --
public event SC_Button_ClickEventr SC_Button_Clicked
#endregion
#region -- Public Properties --
#region - button backgrounds -
private Color _buttonUpTopColour = Color.FromArgb(100, 100, 100)
public Color ButtonUpTopColour
{
get { return _buttonUpTopColour
set { _buttonUpTopColour = value
}
private Color _buttonUpBottomColour = Color.Black
public Color ButtonUpBottomColour
{
get { return _buttonUpBottomColour
set { _buttonUpBottomColour = value
}
private Color _buttonDownTopColour = Color.LightGreen
public Color ButtonDownTopColour
{
get { return _buttonDownTopColour
set { _buttonDownTopColour = value
}
private Color _buttonDownBottomColour = Color.DarkGreen
public Color ButtonDownBottomColour
{
get { return _buttonDownBottomColour
set { _buttonDownBottomColour = value
}
private Color _buttonPressedTopColour = Color.DarkGreen
public Color ButtonPressedTopColour
{
get { return _buttonPressedTopColour
set { _buttonPressedTopColour = value
}
private Color _buttonPressedBottomColour = Color.DarkGreen
public Color ButtonPressedBottomColour
{
get { return _buttonPressedBottomColour
set { _buttonPressedBottomColour = value
}
#endregion
#region - button images
private Image _buttonBorderMask
public Image ButtonBorderMask
{
get { return _buttonBorderMask
set { _buttonBorderMask = value
}
private Image _buttonImage
public Image ButtonImage
{
get { return _buttonImage
set { _buttonImage = value
}
private ContentAlignment _buttonImageAlign
public ContentAlignment ButtonImageAlign
{
get { return _buttonImageAlign
set { _buttonImageAlign = value
}
#endregion
#region - button text -
public string ButtonText
{
get { return _scButton.Text
set { _scButton.Text = value
}
#endregion
#endregion
#region -- Private Properties --
private bool _onButton = false
private bool _isPressed = false
#endregion
#region -- set the button to fill the control --
public SC_Button()
{
InitializeComponent()
}
#endregion
#region -- draw overrrides --
private LinearGradientBrush getBrush(Control c)
{
if (_onButton)
{
if (_isPressed)
{
return new LinearGradientBrush(new Rectangle(0, 0, c.Width, c.Height), _buttonPressedTopColour, _buttonPressedBottomColour, -90.0f, true)
}
else
{
float xPosOnButton = -2.0f * ((float)c.PointToClient(Cursor.Position).X - ((float)c.Width) / 2) / (float)c.Width
float f = 45.0f * xPosOnButton
return new LinearGradientBrush(new Rectangle(0, 0, c.Width, c.Height), _buttonDownTopColour, _buttonDownBottomColour, f - 90.0f, true)
}
}
else
{
return new LinearGradientBrush(new Rectangle(0, 0, c.Width, c.Height), _buttonUpBottomColour, _buttonUpTopColour, -90.0f, true)
}
}
private void paint_Background(PaintEventArgs e, Control c)
{
if (e == null)
return
if (e.Graphics == null)
return
Graphics g = e.Graphics
System.Drawing.Rectangle rect = new Rectangle(0, 0, c.Width, c.Height)
System.Drawing.Color color = (c as Control).BackColor
LinearGradientBrush brush = getBrush(c)
g.FillRectangle(brush, rect)
if (_buttonImage != null)
{
Rectangle imageRect = new Rectangle()
switch (_buttonImageAlign)
{
case ContentAlignment.BottomCenter:
imageRect = new Rectangle((rect.Width - _buttonImage.Size.Width) / 2, rect.Height - _buttonImage.Size.Height, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.BottomLeft:
imageRect = new Rectangle(2, rect.Height - _buttonImage.Size.Height - 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.BottomRight:
imageRect = new Rectangle(rect.Width - _buttonImage.Size.Width - 2, rect.Height - _buttonImage.Size.Height - 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.MiddleCenter:
imageRect = new Rectangle((rect.Width - _buttonImage.Size.Width) / 2, (rect.Height - _buttonImage.Size.Height) / 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.MiddleLeft:
imageRect = new Rectangle(2, (rect.Height - _buttonImage.Size.Height) / 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.MiddleRight:
imageRect = new Rectangle(rect.Width - _buttonImage.Size.Width - 2, (rect.Height - _buttonImage.Size.Height) / 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.TopCenter:
imageRect = new Rectangle((rect.Width - _buttonImage.Size.Width) / 2, 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.TopLeft:
imageRect = new Rectangle(2, 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
case ContentAlignment.TopRight:
imageRect = new Rectangle(rect.Width - _buttonImage.Size.Width - 2, 2, _buttonImage.Size.Width, _buttonImage.Size.Height)
break
}
g.DrawImage(_buttonImage, imageRect)
}
if (_buttonBorderMask != null)
{
g.DrawImage(_buttonBorderMask, rect)
}
brush.Dispose()
}
private void paint_Text(PaintEventArgs e, Control c)
{
if (e == null)
return
if (e.Graphics == null)
return
System.Drawing.Rectangle rect = e.ClipRectangle
System.Drawing.SizeF size = e.ClipRectangle.Size
Graphics g = c.CreateGraphics()
int width = (int)g.MeasureString(c.Text, c.Font).Width
int height = (int)g.MeasureString(c.Text, c.Font).Height
g.Dispose()
System.Drawing.Point pt = new Point((c.Width - width) / 2, (c.Height - height) / 2)
e.Graphics.DrawString(c.Text, c.Font, new SolidBrush(Color.White), pt.X, pt.Y)
}
#endregion
#region -- flag setting methods for button effects --
private void _scButton_MouseDown(object sender, MouseEventArgs e)
{
_isPressed = true
}
private void _scButton_MouseEnter(object sender, EventArgs e)
{
_onButton = true
}
private void _scButton_MouseMove(object sender, MouseEventArgs e)
{
(sender as Control).Refresh()
}
private void _scButton_MouseLeave(object sender, EventArgs e)
{
_onButton = false
}
private void _scButton_MouseUp(object sender, MouseEventArgs e)
{
_isPressed = false
}
private void _scButton_Paint(object sender, PaintEventArgs e)
{
paint_Background(e, (sender as Control))
paint_Text(e, (sender as Control))
}
#endregion
private void SC_Button_Load(object sender, EventArgs e)
{
_scButton.Width = (sender as Control).Width
_scButton.Height = (sender as Control).Height
_scButton.Left = 0
_scButton.Top = 0
}
void _scButton_Click(object sender, System.EventArgs e)
{
if (SC_Button_Clicked != null)
{
SC_Button_Clicked(sender, e)
}
}
}
}</code>
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.