开发者

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>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜