如何保留按钮图像.net的宽高比

时间:2010-12-14 09:03:33

标签: c# .net

我正在尝试重新调整Button控件的大小,同时保留原始图像的宽高比,这样新图像看起来不会被压扁/拉伸。

当我再次将其恢复到原始位置(正常窗口最大化状态)时,它应保持其原始分辨率。

基本上我希望所有显示器分辨率的图像看起来都一样。

例如:在我的申请中, 显示器分辨率 1280 * 1024(5:4)时,全球图像看起来很好 但看起来像椭圆一样伸展,显示器分辨率 1920×1080(16:9)

我知道我必须以编程方式进行某种形式的转换,但我不知道该怎么做。我尝试在OnResize事件上调用下面的方法,虽然它适用于第一次迭代,但随后调整大小时图像会变小,最后我最终丢失了我的图像。

public Rectangle MaintainAspectRatio(Image imgPhoto,Rectangle thumbRect)     {         int sourceWidth = imgPhoto.Width;         int sourceHeight = imgPhoto.Height;         int sourceX = 0;         int sourceY = 0;         int destX = 0;         int destY = 0;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)thumbRect.Width / (float)sourceWidth);
    nPercentH = ((float)thumbRect.Height / (float)sourceHeight);

    //if we have to pad the height pad both the top and the bottom
    //with the difference between the scaled height and the desired height
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = (int)((thumbRect.Width - (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = (int)((thumbRect.Height - (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);

    Rectangle retRect = new Rectangle(thumbRect.X, thumbRect.Y, destWidth, destHeight);
    return retRect;
}

我在我的重写OnPaint事件处理程序方法中使用此代码:

protected override void OnPaint(PaintEventArgs e)     {          base.OnPaint(E);          图形g = e.Graphics;

     int iHeight;
     int iWidth;

     if (Image != null)
     {
         Rectangle ResizedRectangle = MaintainAspectRatio(Image,ClientRectangle);
         iHeight = ResizedRectangle.Height;
         iWidth = ResizedRectangle.Width;

     }
     else
     {
         iWidth = ClientRectangle.Width;
         iHeight = ClientRectangle.Height;
     }


     // Draw border
     Color oLeftTopColor = SystemColors.ControlLightLight;
     Color oRightBottomColor = SystemColors.ActiveCaption;
     Pen oLeftTopPen = new Pen(oLeftTopColor);
     Pen oRightBottomPen = new Pen(oRightBottomColor);
     // top line
     g.DrawLine(oLeftTopPen, 0, 0, iWidth - 1, 0);
     //g.DrawLine(new Pen(SystemColors.ControlLight), 1, 1, iWidth-2, 1);
     // bottom line
     g.DrawLine(oRightBottomPen, 0, iHeight, iWidth - 1, iHeight);
     //g.DrawLine(new Pen(SystemColors.ControlDark), 1, iHeight-2, iWidth-2, iHeight-2);
     // right line
     g.DrawLine(oRightBottomPen, iWidth, 0, iWidth, iHeight - 1);
     //g.DrawLine(new Pen(SystemColors.ControlDark), iWidth-2, 1, iWidth-2, iHeight-2);
     // left line
     g.DrawLine(oLeftTopPen, 0, 0, 0, iHeight - 1);
     //g.DrawLine(new Pen(SystemColors.ControlLightLight), 1, 1, 1, iHeight-2);

     // Draw image
     if (Image != null)
     {

         Rectangle oDrawRectagle = new Rectangle(
            0, 0, iWidth, iHeight);
         if (Enabled == false)
         {
             e.Graphics.DrawImage(Image, oDrawRectagle,
                0, 0, Image.Width, Image.Height,
                GraphicsUnit.Pixel);
         }
         else
         {
             e.Graphics.DrawImage(Image, oDrawRectagle);

         }
     }

     // Draw text
     if (Text != null)
     {
         int iTextTop = 5;
         int iTextLeft = 5;
         int iMaxTextWidth = iWidth - 10;
         int iMaxTextHeight = iHeight - 10;
     }
}

任何人都可以指导我如何处理这个问题?

2 个答案:

答案 0 :(得分:1)

目前还不是很清楚如何使用图像 - 也许您应该将代码发布到实际显示图像的位置。

如果两个分辨率的像素长宽比(PAR)不同,图像可能会在不同分辨率下出现变形 - 这是您的情况吗?是否要显示独立于PAR的图像?

在这种情况下,您需要将图像内部保持在已知的DPI值(通常为96),然后使用您的方法将其拉伸为当前分辨率的DPI值,可以通过以下方式获得:

Single xDpi, yDpi;

IntPtr dc = GetDC(IntPtr.Zero);

using(Graphics g = Graphics.FromHdc(dc))
{
    xDpi = g.DpiX;
    yDpi = g.DpiY;
}

if (ReleaseDC(IntPtr.Zero) != 0)
{
    // GetLastError and handle...
}


[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);    
[DllImport("user32.dll")]
private static extern Int32 ReleaseDC(IntPtr hwnd);

然后你需要缩放图像,使最终宽度=原始宽度* 96 / xDpi,高度相似。

答案 1 :(得分:1)

  

我尝试调用以下方法   OnResize事件,虽然它适用于   第一次迭代,图像得到   随后调整大小和   最后我终于失去了我的形象。

我认为您应该使用DisplaySettingsChanged而不是OnResize事件,只有在更改分辨率时才会触发。