ImageButton that will AutoSize the image
I'm searching for a button control that will AutoSize
its image. Normal button controls won't do this. I'm using C#.Net 2.0.
For example, I have a Button that is 200 x 50px and an image that is 800 x 100px. I want to resize the Image so that it is a little to the left,开发者_StackOverflow near the text of the button. With a PictureBox
I can do this. But when I lay a PictureBox
over the Button
its very ugly because you can't click there.
You can do this as follows:
button.Image = Image.FromFile(path);
button.AutoSize = true;
E.g: Or, You can create a new Button type that will change the size of the image:
public class AutoSizeButton : Button
{
public new Image Image
{
get { return base.Image; }
set
{
Image newImage = new Bitmap(Width, Height);
using (Graphics g = Graphics.FromImage(newImage))
{
g.DrawImage(value, 0, 0, Width, Height);
}
base.Image = newImage;
}
}
}
Test:
AutoSizeButton button = new AutoSizeButton();
button.Location = new Point(27, 52);
button.Name = "button";
button.Size = new Size(75, 23);
button.Text = "Test";
button.UseVisualStyleBackColor = true;
button.Image = Image.FromFile(path);
Controls.Add(button);
I was looking for a version of this in vb.net, so I started with mykhaylo's answer and improved it a bit. This code resizes the image to fit proportionally, centers the image in the button, and provides inner padding for the image.
This button actually does not use the "Image" property of the button and exposes a property "AutoScaleImage" that should be set alternately.
Here is the C# version - VB.net at bottom. Enjoy!
[System.ComponentModel.DesignerCategory("")]
public class AutoScaleButton : Button
{
private Image _AutoScaleImage;
public Image AutoScaleImage {
get { return _AutoScaleImage; }
set {
_AutoScaleImage = value;
if (value != null)
this.Invalidate();
}
}
private int _AutoScaleBorder;
public int AutoScaleBorder {
get { return _AutoScaleBorder; }
set {
_AutoScaleBorder = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawResizeImage(ref e.Graphics);
}
private void DrawResizeImage(Graphics g)
{
if (_AutoScaleImage == null)
return;
int iB = AutoScaleBorder;
int iOff = 0;
Rectangle rectLoc = default(Rectangle);
Rectangle rectSrc = default(Rectangle);
Size sizeDst = new Size(Math.Max(0, this.Width - 2 * iB),
Math.Max(0, this.Height - 2 * iB));
Size sizeSrc = new Size(_AutoScaleImage.Width,
_AutoScaleImage.Height);
double ratioDst = sizeDst.Height / sizeDst.Width;
double ratioSrc = sizeSrc.Height / sizeSrc.Width;
rectSrc = new Rectangle(0, 0, sizeSrc.Width, sizeSrc.Height);
if (ratioDst < ratioSrc) {
iOff = (sizeDst.Width -
(sizeDst.Height * sizeSrc.Width / sizeSrc.Height)) / 2;
rectLoc = new Rectangle(iB + iOff,
iB,
sizeDst.Height * sizeSrc.Width / sizeSrc.Height,
sizeDst.Height);
} else {
iOff = (sizeDst.Height - (sizeDst.Width * sizeSrc.Height / sizeSrc.Width)) / 2;
rectLoc = new Rectangle(iB,
iB + iOff,
sizeDst.Width,
sizeDst.Width * sizeSrc.Height / sizeSrc.Width);
}
g.DrawImage(_AutoScaleImage, rectLoc, rectSrc, GraphicsUnit.Pixel);
}
}
Or my original VB.NET Version.
<System.ComponentModel.DesignerCategory("")> _
Public Class AutoScaleButton
Inherits Button
Private _AutoScaleImage As Image
Public Property AutoScaleImage() As Image
Get
Return _AutoScaleImage
End Get
Set(value As Image)
_AutoScaleImage = value
If value IsNot Nothing Then Me.Invalidate()
End Set
End Property
Private _AutoScaleBorder As Integer
Public Property AutoScaleBorder() As Integer
Get
Return _AutoScaleBorder
End Get
Set(ByVal value As Integer)
_AutoScaleBorder = value
Me.Invalidate()
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
DrawResizeImage(e.Graphics)
End Sub
Private Sub DrawResizeImage(ByRef g As Graphics)
If _AutoScaleImage Is Nothing Then Exit Sub
Dim iB As Integer = AutoScaleBorder, iOff As Integer = 0
Dim rectLoc As Rectangle, rectSrc As Rectangle
Dim sizeDst As Size = New Size(Math.Max(0, Me.Width - 2 * iB), Math.Max(0, Me.Height - 2 * iB))
Dim sizeSrc As Size = New Size(_AutoScaleImage.Width, _AutoScaleImage.Height)
Dim ratioDst As Double = sizeDst.Height / sizeDst.Width
Dim ratioSrc As Double = sizeSrc.Height / sizeSrc.Width
rectSrc = New Rectangle(0, 0, sizeSrc.Width, sizeSrc.Height)
If ratioDst < ratioSrc Then
iOff = (sizeDst.Width - (sizeDst.Height * sizeSrc.Width / sizeSrc.Height)) / 2
rectLoc = New Rectangle(iB + iOff, iB, _
sizeDst.Height * sizeSrc.Width / sizeSrc.Height, _
sizeDst.Height)
Else
iOff = (sizeDst.Height - (sizeDst.Width * sizeSrc.Height / sizeSrc.Width)) / 2
rectLoc = New Rectangle(iB, iB + iOff, _
sizeDst.Width, _
sizeDst.Width * sizeSrc.Height / sizeSrc.Width)
End If
g.DrawImage(_AutoScaleImage, rectLoc, rectSrc, GraphicsUnit.Pixel)
End Sub
End Class
public class ExtButton : Button
{
public new Image Image
{
get { return base.Image; }
set {
base.Image = ScaleImage(value, this.Width, this.Height);
}
}
private Image ScaleImage(Image image, int maxWidth, int maxHeight)
{
var ratioX = (double)maxWidth / image.Width;
var ratioY = (double)maxHeight / image.Height;
var ratio = Math.Min(ratioX, ratioY);
var newWidth = (int)(image.Width * ratio);
var newHeight = (int)(image.Height * ratio);
var newImage = new Bitmap(newWidth, newHeight);
Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
return newImage;
}
}
I originally proposed using a standard ImageButton but then read your comment that you are trying to size the button to the image. For that use a LinkButton:
<asp:LinkButton ID="foo" runat="server" OnClick="LinkButton1_Click">
<asp:Image ID="imagefoo" runat="server" ImageUrl="~/Foo.jpg" />
</asp:LinkButton>
精彩评论