Windows Forms C#: 当调整标签大小时,动态调整标签图片的大小

3
这是我的问题:
我通过编程方式向表单添加标签,包括一些属性,以便在运行时通过鼠标右键单击并拖动它们来调整大小。
我的情况是,我通过OpenDialog从给定文件中编程方式添加一个带图像的标签,并且我想将此图像调整大小以填充标签大小,就像我拉伸标签一样。不幸的是,我无法通过访问标签中的image.Size属性在运行时设置大小,因为它是只读属性...有什么建议吗?
这是受影响的代码片段:
Point _oldPosition;
public static Label _ctrlActiveControl;

if (e.Button == MouseButtons.Right)
{
    _ctrlActiveControl.Cursor = Cursors.SizeNWSE;

    //Code to resize the control based on the mouse position
    Point newPosition = new Point(e.X, e.Y);
   _ctrlActiveControl.Width += (newPosition.X - _oldPosition.X);
   _ctrlActiveControl.Height += (newPosition.Y - _oldPosition.Y);

    //Some security to make sure I don't shrink the control too much
    if (_ctrlActiveControl.Width < 10) _ctrlActiveControl.Width = 10;
    if (_ctrlActiveControl.Height < 10) _ctrlActiveControl.Height = 10;

    //Here I check if the label contains an image and, if so, I should resize
    //The image to "Autofill" the label
    if (_ctrlActiveControl.Image != null)
    {
      Image image = _ctrlActiveControl.Image;
      image.Size = new Size(_ctrlActiveControl.Width, _ctrlActiveControl.Height);
    }

    _oldPosition = newPosition;
}

我想知道是否有任何方法可以做到这一点,或者我应该使用其他控件类型(我知道我可以使用其他控件,但是在添加更多变量之前,我想知道是否有任何可用的解决方法)。


1
你想改变图片的大小,因此你可以在这里找到一些有用的示例:https://dev59.com/SXI-5IYBdhLWcg3wTWdu。但我认为你应该使用PictureBox而不是Label来完成这个任务。 - Steve
PictureBox有一个SizeMode属性,可以设置为Stretch或Zoom,这样就可以自动完成您想要的效果。 - Hjalmar Z
那就是关键所在……如果它是一个PicBox,那就容易多了。问题在于,在代码的后面,我将对创建的标签列表进行相当多的操作,因此我希望保持属性标准化,以便我可以处理一种对象类型而不是太多类型,特别是它们的空值。 - Mario
2个回答

4
你可以将其转换为 Bitmap 然后使用 Graphics 进行重新绘制。然后用新创建的图像替换旧图像。我不知道这在性能方面是否可行,但我认为值得一试。
Bitmap newImage = new Bitmap(_ctrlActiveControl.Width, _ctrlActiveControl.Height);
using (Bitmap bm = new Bitmap(_ctrlActiveControl.Image))
{
    using (Graphics g = Graphics.FromImage(newImage))
    {
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        Point[] corners = { new Point(0, 0), new Point(newImage.Width, 0), new Point(0, newImage.Height) };
        g.DrawImage(bm, corners);
    }
}
_ctrlActiveControl.Image = newImage;

您需要使用 System.DrawingSystem.Drawing.Drawing2D

谢谢Hjalmar。我也遇到了与图形相关的问题,因为对象位于另一个面板的子面板中...长话短说,Graphics的DrawImage方法也是另一个问题,因为对象会消失,而我不想让问题变得更复杂...不过还是谢谢你的建议! - Mario
哈哈。整个想法是制作一些定制的、简单易用的报表设计工具。用户可以点击这里那里来添加图像、文字、系统数据等,以及 SQL 查询中的字段,从而创建一个模板。一旦模板完成,我将所有标签及其属性存储在 XML 文件中,以供不同目的使用。由于大多数对象都是标签,所以我希望(如果可能的话)始终使用这种类型的对象,以保持简单。 - Mario

2
根据Steve的建议,我已经进行了替换。
if (_ctrlActiveControl.Image != null)
{
  Image image = _ctrlActiveControl.Image;
  image.Size = new Size(_ctrlActiveControl.Width, _ctrlActiveControl.Height);
}

并改为写成:

if (_ctrlActiveControl.Image != null)
{
     _ctrlActiveControl.Image = ResizeImage(_ctrlActiveControl.Image, _ctrlActiveControl.Width, _ctrlActiveControl.Height);
}

.....

public static Bitmap ResizeImage(Image image, int width, int height)
{
    var destRect = new Rectangle(0, 0, width, height);
    var destImage = new Bitmap(width, height);

    destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

    using (var graphics = Graphics.FromImage(destImage))
    {
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        using (var wrapMode = new ImageAttributes())
        {
            wrapMode.SetWrapMode(WrapMode.TileFlipXY);
            graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
            graphics.Dispose();
        }
    }

    return destImage;
}

如果您反复拉伸和收缩标签,它将变得无用(如果标签太小,然后我们尝试重新放大标签,图像质量将会降低)。但是,作为起点,它可能有效。我可以重新编码以直接引用文件作为图像源,这样我就可以始终获得新鲜的文件...感谢您的建议。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接