【问题标题】:How can I gray-out a disabled PictureBox used as Button?如何使用作按钮的已禁用图片框变灰?
【发布时间】:2020-08-17 08:07:25
【问题描述】:

我在我的应用主仪表板中使用 Picturebox 控件作为按钮。
PictureBox 当然有一个识别按钮功能的图像。

如果我使用普通的 Button 控件,禁用时,Buttons 的图像会自动变灰。
使用 PictureBox 不会发生这种情况。

如何使用图片框生成相同的效果

【问题讨论】:

  • 查看已接受答案here 的最后一个代码块。如果控件被禁用,最好创建一个自定义 PictureBox 并重写 Paint 方法以正常绘制图像或变灰。您还可以在创建 ColorMatrix 作为附加效果时降低不透明度 (Matrix33)。
  • 我知道,但我不想使用按钮。我正在使用图片框
  • 不使用按钮的人如何将图像转换为已在图片框中的灰度
  • 需要处理Paint事件,根据Enabled属性的值绘制图像。也许带有图像的 PictureBox 的屏幕截图有助于了解您要做什么。

标签: c# winforms graphics picturebox


【解决方案1】:

选项一:CustomControl (PictureBox) + ColorMatrix

由于您不想使用按钮,当控件被禁用时,它会使图像变灰,您可以使用ColorMatrixPictureBox.BackgroundImage 或(图像)更改为灰度.

您在此处看到的 GrayScale 矩阵使用众所周知的值将图像转换为缩放的灰色表示。您可以找到可能产生不同结果的同一矩阵对象的其他解释。
自己测试或调整它会很有趣。

灰度过程被实现为Extension method,因为它在其他情况下可能会派上用场。
它扩展了 Image 类,添加了一个ToGrayScale() 方法(您当然也可以扩展 Bitmap 类:您只需要调用 Image 扩展,将 Bitmap 转换为 Image,或者其他方式,如您所愿)。


假设您有一个自定义控件,当 BackgroundImage 发生更改时,您创建它的灰度表示并存储它。

然后覆盖 OnEnabledChanged 以将 BackgroundImage 更改为原始版本或其灰度版本。一个简单的检查可以防止代码在内部更改 BackgroundImage 时生成新的 GrayScale 图像(这是一种有点简化的方法,您应该改为绘制背景。我会尽快更新它)。

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

[DesignerCategory("Code")]
public class ButtonPicture : PictureBox
{
    private Image m_sourceImage = null;
    private Image m_grayImage = null;

    public ButtonPicture() { }

    protected override void OnEnabledChanged(EventArgs e) {
        base.OnEnabledChanged(e);
        this.BackgroundImage = this.Enabled ? m_sourceImage : m_grayImage;
    }
        
    protected override void OnBackgroundImageChanged(EventArgs e) {
        base.OnBackgroundImageChanged(e);
        if (this.BackgroundImage == m_sourceImage || 
            this.BackgroundImage == m_grayImage) return;
        m_sourceImage = this.BackgroundImage;
        m_grayImage = m_sourceImage.ToGrayScale();
    }

    protected override void Dispose(bool disposing) {
        if (disposing) {
            m_grayImage.Dispose();
        }
        base.Dispose(disposing);
    }
}

扩展方法:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

public static class ImageExtensions
{
    static ColorMatrix grayMatrix = new ColorMatrix(new float[][]
    {
        new float[] { .2126f, .2126f, .2126f, 0, 0 },
        new float[] { .7152f, .7152f, .7152f, 0, 0 },
        new float[] { .0722f, .0722f, .0722f, 0, 0 },
        new float[] { 0, 0, 0, 1, 0 },
        new float[] { 0, 0, 0, 0, 1 }
    });

    public static Bitmap ToGrayScale(this Image source) {
        var grayImage = new Bitmap(source.Width, source.Height, source.PixelFormat);
        grayImage.SetResolution(source.HorizontalResolution, source.VerticalResolution);

        using (var g = Graphics.FromImage(grayImage))
        using (var attributes = new ImageAttributes()) {
            attributes.SetColorMatrix(grayMatrix);
            g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height),
                        0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes);
            return grayImage;
        }
    }
}


选项 2:ControlPaint + PictureBox.Paint 事件(蹩脚)

您可以使用ControlPaint.DrawImageDisabled() 方法来绘制一个禁用位图。

  • 方法所需的Graphics对象由Control的PaintEventArgs提供:订阅PictureBox.Paint事件并将e.Graphics对象传递给方法。
  • Image 参数可以是PictureBox.Image 属性值的副本。
  • 唯一的优点是您需要的代码少得多,但无法控制默认实现,结果是,有问题(但对于一般用途来说可能已经足够了)。

► 比较左侧的图像,禁用使用 ColorMatrix,与右侧的图像,禁用使用 ControlPaint 方法:

private void buttonPicture_Paint(object sender, PaintEventArgs e)
{
    var pict = sender as PictureBox;
    if (pict != null && (!pict.Enabled)) {
        using (var img = new Bitmap(pict.Image, pict.ClientSize)) {
            ControlPaint.DrawImageDisabled(e.Graphics, img, 0, 0, pict.BackColor);
        }
    }
}

【讨论】:

    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    相关资源
    最近更新 更多