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:
public class OrientedButton : Button
Hope it helps!
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
protected override void OnMouseDown(MouseEventArgs mevent)
{
base.OnMouseDown(mevent);
mState = System.Windows.Forms.VisualStyles.PushButtonState.Pressed;
Invalidate();
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
Invalidate();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
mState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
Invalidate();
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
Invalidate();
}
#endregion
OnPaint Method
protected override void OnPaint(PaintEventArgs pevent)
{
base.OnPaint(pevent);
if (mOrientation == Orientation.Horizontal)
return;
if (mState == System.Windows.Forms.VisualStyles.PushButtonState.Pressed)
{
this.BackColor = Application.RenderWithVisualStyles ?
Color.Azure : this.Parent.BackColor;
ButtonRenderer.DrawParentBackground(pevent.Graphics,
ClientRectangle, this);
ButtonRenderer.DrawButton(pevent.Graphics, this.ClientRectangle,
"", this.Font, true, mState);
}
else
{
ButtonRenderer.DrawButton(pevent.Graphics, ClientRectangle,
"", this.Font, false, mState);
}
if (this.Text != "")
this.DrawText(pevent.Graphics);
if (this.Image != null)
this.DrawImage(pevent.Graphics);
}
The DrawText Method
private void DrawText(System.Drawing.Graphics pGraphics)
{
SizeF sizeOfText = pGraphics.MeasureString(this.Text, this.Font);
float temp = sizeOfText.Width;
sizeOfText.Width = sizeOfText.Height;
sizeOfText.Height = temp;
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;
}
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;
}
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
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