【问题标题】:ImageLayout.Center does not center background imageImageLayout.Center 不居中背景图像
【发布时间】:2015-07-10 11:17:35
【问题描述】:

我想将背景图片居中。但是背景图像比我的控件大(这是一个平面样式的复选框)。

A picture to make my problem clear

通常如果背景图片比控件小,它会像黑框一样显示(正确居中);但在我的情况下,它会在绿色框(左上角)中显示部分图像,但我想要的最终结果是橙色框(图像的中心),或者按比例缩放以填充控件并切断多余的部分( ImageLayout.Zoom 将显示带有空白区域的整个图像)。

更新:使用的代码:

        Image img = Image.FromFile("xxxx.png");
        mycheckbox.BackgroundImage = img;
        mycheckbox.BackgroundImageLayout = ImageLayout.Center;

【问题讨论】:

  • 你试过 ImageLayout.Strech 吗?您还可以提供一些代码,它会有所帮助:)
  • @msmolcic Stretch 会产生扭曲的图像。代码真的很简单,但我会把它放进去。对于这种特殊情况,我可以使用 checkBox.Image 属性而不是 .BackgroundImage 但它只有在图像大于控件时才有效,并且不是每个控件都有 .Image属性,所以我想看到一个更通用的解决方案。
  • 一般来说:当您有可能的值列表时,我建议您全部尝试。其中一个应该可以正常工作。
  • @Mitulátbáti 我做了,但没有一个工作。我想我可能需要沿着 Graphics 路径而不是使用 Control 属性:/
  • 要获取橙色框,您可以设置Image 属性而不是BackGroundImage(与ImageAlign = MiddleCenter),但我不知道这是否适合您的所有图像?

标签: c# winforms


【解决方案1】:

可以使用Image代替BackgroundImage来获取图片的一部分作为示例的橙色矩形。

如果图像没有填满整个复选框,并且可以接受更改正在设置的图像(应该可以正常工作,但如果复选框大小在运行时发生变化,则不会是动态的),则可以先调整图像大小按最大比例:

        var img = Image.FromFile("xxxx.png");
        float ratio = Math.Max(mycheckbox.Height / (float)img.Height,mycheckbox.Width / (float)img.Width);            
        if (ratio > 1)
        {
            Func<float, int> calc = f => (int)Math.Ceiling(f * ratio);
            var bmp = new Bitmap(img,  calc(img.Width ), calc(img.Height ));
            img.Dispose();
            img = bmp;
        }
        mycheckbox.ImageAlign = ContentAlignment.MiddleCenter;
        mycheckbox.Image = img;

float ratio = Math.Max(mycheckbox.Height / (float)img.Height,mycheckbox.Width / (float)img.Width); 行简单地计算了高度比和宽度比。如果其中一个大于 1,则表示复选框的高度或宽度较大。哪一个无关紧要,只有哪个更大,因此是 Math.Max。大于 1 的检查是对最大比例进行的,如果需要,图像会按照该比例放大。

编辑一种更通用的方法,即缩放和剪切图像,以便填充控件大小和使用BackGroundImage 属性:

    public static void SetImage(this Control ctrl, Image img)
    {
        var cs = ctrl.Size;
        if (img.Size != cs)
        {
            float ratio = Math.Max(cs.Height / (float)img.Height, cs.Width / (float)img.Width);
            if (ratio > 1)
            {
                Func<float, int> calc = f => (int)Math.Ceiling(f * ratio);
                img = new Bitmap(img, calc(img.Width), calc(img.Height));                    
            }

            var part = new Bitmap(cs.Width, cs.Height);
            using (var g = Graphics.FromImage(part))
            {
                g.DrawImageUnscaled(img, (cs.Width - img.Width) /2, (cs.Height - img.Height) / 2);
            }                
            img = part;
        }
        ctrl.BackgroundImageLayout = ImageLayout.Center;
        ctrl.BackgroundImage = img;
    }

【讨论】:

  • 同样,不是每个控件都有Image 属性,例如Panel。或者,如果您需要Image 属性用于其他用途,您应该使用Graphics.DrawImage()。但是在尝试之后,我发现Panel 的绘图调用非常缓慢,但ButtonCheckBox 不是(使用完全相同的调用)。无论哪种方式,如果需要,需要对图像进行缩放,感谢图像缩放代码!
  • 哎呀,完全错过了您自己提到 Image 和 BackgroundImage 并提到其他控件类型的评论。只看到你对我自己的评论做出的回答,所以没有意识到它也必须适用于其他控件,对此感到抱歉。但事实上,即使使用自定义绘画,也可以使用相同的缩放比例。
  • @anetworknoobie ,重新定义了多种控制类型的要求,图像可以被改变,只保留需要的部分,背景图像可以用于确保一般使用。如果您愿意,我可以尝试将其添加到答案中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 2020-01-22
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多