Как можно отключить отключенный PictureBox в качестве кнопки? - PullRequest
0 голосов
/ 02 мая 2020

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

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

Как можно сгенерировать тот же эффект , используя Picturebox.

1 Ответ

1 голос
/ 04 мая 2020

Вариант 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 Image

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

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

ControlPaint PictureBox disabled Image

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