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:
public class OrientedButton : Button
Declaration of variables and props
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
#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
/// <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
/// <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
/// <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);
}