Как сделать серым отключенный PictureBox, используемый в качестве кнопки?

Я использую элемент управления Picturebox в качестве кнопки на главной панели управления моего приложения.
PictureBox, конечно же, имеет изображение, которое идентифицирует функцию кнопки.

Если я использую обычные элементы управления Button, когда они отключены, изображение кнопок автоматически становится серым.
Этого не происходит при использовании PictureBox.

Как я могу создать тот же эффект с помощью Picturebox.


person Yousuf Iqbal    schedule 02.05.2020    source источник
comment
См. Последний блок кода принятого ответа здесь. Лучше создать настраиваемый PictureBox и переопределить метод Paint, чтобы изображение отображалось обычным или серым цветом, если элемент управления отключен. Также вы можете уменьшить непрозрачность (Matrix33) при создании ColorMatrix в качестве дополнительного эффекта.   -  person    schedule 03.05.2020
comment
Альтернатива: ControlPaint. DrawImageDisabled   -  person    schedule 03.05.2020
comment
Я знаю это, но не хочу использовать кнопку. Я использую PictureBox   -  person Yousuf Iqbal    schedule 03.05.2020
comment
Ребята, не используя кнопку, как я могу преобразовать изображение в оттенки серого, которое уже есть в Picturebox   -  person Yousuf Iqbal    schedule 03.05.2020
comment
Вам необходимо обработать событие Paint, чтобы нарисовать изображение в соответствии со значением свойства Enabled. Возможно, снимок экрана для PictureBox с изображением поможет понять, что вы пытаетесь сделать.   -  person    schedule 03.05.2020


Ответы (1)


Вариант 1. CustomControl (PictureBox) + ColorMatrix

Поскольку вы не хотите использовать кнопку, которая будет затемнять изображение для вас, когда элемент управления отключен, вы можете использовать ColorMatrix, чтобы изменить PictureBox.BackgroundImage или (Изображение) на шкалу серого.

Матрица GrayScale, которую вы видите здесь, использует хорошо известные значения для преобразования изображения в масштабированное представление серого цвета. Вы можете найти другие интерпретации одного и того же матричного объекта, которые могут дать разные результаты.
Может быть интересно протестировать некоторые или настроить их самостоятельно.

Процедура GrayScale реализована как Метод расширения, так как он может пригодиться в других ситуациях.
Он расширяет класс Image, добавляя метод ToGrayScale() (вы, конечно, также можете расширить класс Bitmap: вам просто нужно вызвать расширение Image , преобразование Bitmap в Image или наоборот, как вам удобнее).


Предполагая, что у вас есть настраиваемый элемент управления, при изменении BackgroundImage вы создаете его представление GrayScale и сохраняете его.

Затем переопределите OnEnabledChanged, чтобы изменить BackgroundImage либо на исходное, либо на его версию GrayScale. Простая проверка не позволяет коду генерировать новое изображение GrayScale при внутреннем изменении BackgroundImage (это несколько упрощенный метод, вместо этого вы должны закрасить фон. Я обновлю его, когда смогу).

Изображение GrayScale Matrix PictureBox

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, который необходим методам, предоставляется PaintEventArgs: подписаться на событие PictureBox.Paint и передать объект e.Graphics методу.
  • Аргумент Image может быть копией значения свойства PictureBox.Image.
  • Единственное преимущество состоит в том, что вам нужно гораздо меньше кода, но реализацию по умолчанию нельзя контролировать, и результат, в общем, сомнительный (но, вероятно, достаточно хорош для общего использования).

► Сравните изображение слева, отключено с помощью ColorMatrix, с изображением справа, отключено с помощью метода ControlPaint:

«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);
        }
    }
}
person Jimi    schedule 04.05.2020