c# - 如何使用作按钮的已禁用图片框变灰?
问题描述
我在我的应用程序的主仪表板中使用 Picturebox 控件作为按钮。
PictureBox 当然有一个识别按钮功能的图像。
如果我使用普通的按钮控件,当禁用时,按钮的图像会自动变灰。
使用 PictureBox 不会发生这种情况。
如何使用 Picturebox生成相同的效果。
解决方案
选项 1:自定义控件(图片框)+ ColorMatrix
由于您不想使用按钮,当控件被禁用时,它会为您灰显图像,您可以使用ColorMatrix将PictureBox.BackgroundImage
or (Image) 更改为灰度。
您在此处看到的 GrayScale 矩阵使用众所周知的值将图像转换为按比例缩放的灰色表示。您可以找到可能产生不同结果的同一矩阵对象的其他解释。
测试一些或自己调整它会很有趣。
GrayScale 过程是作为扩展方法实现的,因为它在其他情况下可能会派上用场。
它扩展了 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);
}
}
}
推荐阅读
- python - 如何优化这段代码的性能?
- tree - Prolog 中的树
- java - Install4j - 如何在 UI 表单中添加组框
- php - 在mysql php中得到真假结果
- vue.js - 在 Vue 子组件中提取道具中的信息
- html - SVG:如何在元素内均匀地居中多行文本?
- c - C - 在阅读 CTRL+Z 之前如何阅读短语?
- javascript - 检测您的网页是否在应用程序的 WebView 中查看?
- fortran - Fortran 编译器指示无效表达式
- azure-devops - 如何通过 Azure Devops 将 UWP 包发布到 Windows 应用商店?