Click here to Skip to main content
15,891,837 members
Articles / Desktop Programming / Windows Forms

Oriented Button in Windows Forms

Rate me:
Please Sign up or sign in to vote.
4.00/5 (2 votes)
3 Apr 2010CPOL 19.8K   3   1
Oriented Button in Windows Forms

The following class is a button which can be oriented both horizontally and vertically (like in the picture of your left). Text and image react properly to this orientation and so do their Alignments. The control also includes customizable margins for the text and image inside the button and a SizePercent property for the Image. Please keep in mind that if Orientation is set to “Horizontal”, the normal Draw methods from the base class are called, so all of this properties are ignored. However, you can change this behavior or add any other property very easily if you need it.

The whole thing has been designed to use as less resources as possible (accept suggestions on this of course ;), but you can very easily add other features, like a PictureBox for the image rendering (re-using all the PictureBox features as: BorderStyle, SizeMode, etc.).

You can just copy-paste the following parts of code into a class which inherits from Button, and you´ll have it. Something like this:

C#
public class OrientedButton : Button

Hope it helps!

Declaration of Variables and Props

C#
private Orientation mOrientation = Orientation.Horizontal;
private int mTextMargin = 5;
private int mImageMargin = 5;
private int mImageScalingPercent = 100;
private System.Windows.Forms.VisualStyles.PushButtonState mState = 
                      System.Windows.Forms.VisualStyles.PushButtonState.Normal;

#region Props
[Category("Appearance")]
[DefaultValue(5)]
public int TextMargin
{
    get { return mTextMargin; }
    set { mTextMargin = value; }
}
[Category("Appearance")]
[DefaultValue(5)]
public int ImageMargin
{
    get { return mImageMargin; }
    set { mImageMargin = value; }
}     
[Category("Appearance")]
[DefaultValue(Orientation.Horizontal)]
public Orientation Orientation
{
    get { return mOrientation; }
    set { mOrientation = value; }
}
[Category("Appearance")]
[DefaultValue(100)]       
public int ImageScalingPercent
{
    get { return mImageScalingPercent; }
    set { mImageScalingPercent = value; }
}

#endregion

Mouse Events Handling

C#
region Mouse Events
/// <summary>
/// 
/// </summary>
/// <param name="mevent"></param>
protected override void OnMouseDown(MouseEventArgs mevent)
{
    base.OnMouseDown(mevent);
    mState = System.Windows.Forms.VisualStyles.PushButtonState.Pressed;
    Invalidate();
}
/// <summary>
/// 
/// </summary>
/// <param name="mevent"></param>
protected override void OnMouseUp(MouseEventArgs mevent)
{
    base.OnMouseUp(mevent);
    mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
    Invalidate();
}        
/// <summary>
/// 
/// </summary>
/// <param name="e"></param>
protected override void OnMouseLeave(EventArgs e)
{
    base.OnMouseLeave(e);
    mState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
    Invalidate();
}
/// <summary>
/// 
/// </summary>
/// <param name="e"></param>
protected override void OnMouseEnter(EventArgs e)
{
    base.OnMouseEnter(e);
    mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
    Invalidate();
}
#endregion

OnPaint Method

C#
/// <summary>
/// Some code parts were taken from here: http://msdn.microsoft.com/es-es/library/f0ys5025.aspx
/// </summary>
/// <param name="pevent"></param>
protected override void OnPaint(PaintEventArgs pevent)
{
    base.OnPaint(pevent);
    
    if (mOrientation == Orientation.Horizontal)
        return;
        
    // Base Button Draw
    if (mState == System.Windows.Forms.VisualStyles.PushButtonState.Pressed)
    {
        // Set the background color to the parent if visual styles  
        // are disabled, because DrawParentBackground will only paint  
        // over the control background if visual styles are enabled.
        this.BackColor = Application.RenderWithVisualStyles ?
            Color.Azure : this.Parent.BackColor;
            
        // If you comment out the call to DrawParentBackground, 
        // the background of the control will still be visible 
        // outside the pressed button, if visual styles are enabled.
        ButtonRenderer.DrawParentBackground(pevent.Graphics,
            ClientRectangle, this);
        ButtonRenderer.DrawButton(pevent.Graphics, this.ClientRectangle,
            "", this.Font, true, mState);
    }
    else
    {
        // Draw the bigger unpressed button image.
        ButtonRenderer.DrawButton(pevent.Graphics, ClientRectangle,
            "", this.Font, false, mState);
    }
    
    // Draw Text
    if (this.Text != "")
        this.DrawText(pevent.Graphics);
        
    // Draw Image
    if (this.Image != null)
        this.DrawImage(pevent.Graphics);
}

The DrawText Method

C#
/// <summary>
/// 
/// </summary>
private void DrawText(System.Drawing.Graphics pGraphics)
{
    // Calc size of text (la func devuelve el size horizontal)
    SizeF sizeOfText = pGraphics.MeasureString(this.Text, this.Font);
    float temp = sizeOfText.Width;
    sizeOfText.Width = sizeOfText.Height;
    sizeOfText.Height = temp;
    
    // Calc X coord of Text            
    float x = mTextMargin;
    switch (this.TextAlign)
    {
        case ContentAlignment.MiddleCenter:
        case ContentAlignment.TopCenter:
        case ContentAlignment.BottomCenter:
            x = (this.Width / 2) - (sizeOfText.Width / 2);
            break;
        case ContentAlignment.MiddleRight:
        case ContentAlignment.BottomRight:
        case ContentAlignment.TopRight:
            x = this.Width - mTextMargin - sizeOfText.Width;
            break;
    }
    
    // Calc Y coord of Text
    float y = mTextMargin;
    switch (this.TextAlign)
    {
        case ContentAlignment.BottomCenter:
        case ContentAlignment.BottomLeft:
        case ContentAlignment.BottomRight:
            y = this.Height - mTextMargin - sizeOfText.Height;
            break;
        case ContentAlignment.MiddleCenter:
        case ContentAlignment.MiddleLeft:
        case ContentAlignment.MiddleRight:
            y = (this.Height / 2) - (sizeOfText.Height / 2);
            break;
    }
    
    // Draw text
    System.Drawing.SolidBrush drawBrush = new System.Drawing.SolidBrush(this.ForeColor);
    System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
    drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;
    pGraphics.DrawString(this.Text, this.Font, drawBrush, x, y, drawFormat);
    drawBrush.Dispose();
}

The DrawImage Method

C#
/// <summary>
/// 
/// </summary>
/// <param name="pGraphics"></param>
private void DrawImage(System.Drawing.Graphics pGraphics)
{
    float imageScaling = (float)mImageScalingPercent / 100f;
    float finalWidth = (float)this.Image.Width * imageScaling;
    float finalHeight = (float)this.Image.Height * imageScaling;
    float halfFinalWidth = finalWidth / 2f;
    float halfFinalHeight = finalHeight / 2f;
    
    float x = mImageMargin;
    float y = mImageMargin;
    switch (this.ImageAlign)
    {
        case ContentAlignment.MiddleCenter:
        case ContentAlignment.TopCenter:
        case ContentAlignment.BottomCenter:
            x = (this.Width / 2f) - halfFinalWidth;
            break;
        case ContentAlignment.MiddleRight:
        case ContentAlignment.BottomRight:
        case ContentAlignment.TopRight:
            x = this.Width - mImageMargin - finalWidth;
            break;
    }
    switch (this.ImageAlign)
    {
        case ContentAlignment.BottomCenter:
        case ContentAlignment.BottomLeft:
        case ContentAlignment.BottomRight:
            y = this.Height - mImageMargin - finalHeight;
            break;
        case ContentAlignment.MiddleCenter:
        case ContentAlignment.MiddleLeft:
        case ContentAlignment.MiddleRight:
            y = (this.Height / 2f) - halfFinalHeight;
            break;
    }
    System.Drawing.Drawing2D.Matrix rotMat = new System.Drawing.Drawing2D.Matrix();
    PointF rotationCenter = new PointF(x + halfFinalWidth, y + halfFinalHeight);            
    rotMat.RotateAt(90, rotationCenter);
    pGraphics.Transform = rotMat;
    
    System.Drawing.Rectangle destRect = 
       new Rectangle((int)x, (int)y, (int)finalWidth, (int)finalHeight);
    System.Drawing.Rectangle srcRect = new Rectangle(0, 0, this.Image.Width, this.Image.Height);
    pGraphics.DrawImage(this.Image, destRect, srcRect, GraphicsUnit.Pixel);
}

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Spain Spain
Inaki Ayucar is a Microsoft MVP in DirectX/XNA, and a software engineer involved in development since his first Spectrum 48k, in the year 1987. He is the founder and chief developer of The Simax Project (www.simaxvirt.com) and is very interested in DirectX/XNA, physics, game development, simulation, C++ and C#.

His blog is: http://graphicdna.blogspot.com

To contact Inaki: iayucar@simax.es

Comments and Discussions

 
GeneralVersion of DrawButton used Pin
Henry Minute25-May-10 4:35
Henry Minute25-May-10 4:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.