C# WinForm下DataGridView绘制背景图

摘要:
昨天,一位朋友突然问我如何在C#下绘制DataGridView的背景图。当我使用一些第三方控件时,我看到它们有这个功能,但我没有这样的要求,所以我尝试了。GridView真的没有办法绘制背景吗?我不相信,所以我再次探索MSDN,找到了一种方法:protectedvirtualvoidPaintBackground;看着这个名字真是太棒了。赶紧重写它:protectedoverridevoidPaintBackground{graphics.DrawImageUnsaledAndClipped;}呵呵,如果你不让我使用BackgroundImage,我必须使用它。BackgroundImage只是“隐藏”的,但使用它没有问题。现在正是保存背景图像的时候。

昨天一个朋友突然问我如何在C#下给DataGridView绘制背景图,以前使用一些第三方控件时,看见它们有这个功能,只是我还没有过这种需求,于是便动手试了下。

最先想到的是BackgroundImage,这两天正在做B/S的界面,还觉得要说做界面方便,还得说CSS,从这点上来说,WPF或者Silverlight还真不赖,只可惜的是现在C/S的用武之地越来越小,除了游戏必须(当然,是大型的游戏)为桌面应用程序外,貌似使用C/S做个管理系统实无必要;在企业管理系统中,WPF和Silverlight莫非就是传中的屠龙技?

又说远了去了,但是很快发现BackgroundImage不行,且看其定义:

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override Image BackgroundImage { get; set; }

不可见的,一个刻意对开发工具隐藏了的属性,你能指望它会有功能?不死心,代码中一试,如果没有任何效果。

于是想起来终极大法:OnPaint方法,一般情况下在控件中,重写这个方法,肯定能绘制出来你想要的任何形状,但是在DataGridVeiw控件中,居然出现了意想不到的问题:

1.当在base.OnPaint(e)之前调用e.Graphics.DrawImage()方法时,数据行的部分是透明的,但是背景部分仍是原来的颜色;

2.当在base.OnPaint(e)之后调用e.Graphics.DrawImage()方法时,DataGridView全部被图片遮盖,想想这种情况也是必须的。

难道GridView真没有办法绘制背景么?我不太相信,于是再探MSDN(很多人平时根本不看MSDN,遇到问题就求救,这样相当不好),果然发现一个方法:

        protected virtual void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds);

看名字就很给力啊,赶紧重写:

        protected override void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds)
        {
            graphics.DrawImageUnscaledAndClipped(this.BackgroundImage, gridBounds);
        }

呵呵,你不让我使用BackgroundImage,我还非得使用了,BackgroundImage只是被“隐藏”,但是使用还是没有问题的,正好拿来保存背景图片。

果然,运行程序后出结果了,但是又有另一个问题了,数据行的背景是透明的,这样的话数据就可能被背景影响,导致看不清楚,最好是能给数据行加一个半透明的背景,(此处略过一小时的研究过程...)最终发现有一个方法可以绘制单元格的背景,单元格绘制了,数据行不就自然O了吗?

        protected internal virtual void OnCellPainting(DataGridViewCellPaintingEventArgs e);

最终代码确定了:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.dataGridView1.BackgroundImage = Image.FromFile("c:\\2216400.jpg");
            this.dataGridView1.DefaultCellStyle.BackColor = Color.FromArgb(128, Color.White);
            this.dataGridView1.DefaultCellStyle.SelectionBackColor = Color.FromArgb(128, Color.Blue);
        }
    }

    public class MyDataGrid : DataGridView
    {
        protected override void PaintBackground(Graphics graphics, Rectangle clipBounds, Rectangle gridBounds)
        {
            graphics.DrawImageUnscaledAndClipped(this.BackgroundImage, gridBounds);
        }

        protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
        {
            if (e.RowIndex == -1 || e.ColumnIndex == -1)
            {
                return;
            }
            Rectangle newRect = new Rectangle(e.CellBounds.X + 1,
                e.CellBounds.Y + 1, e.CellBounds.Width - 4,
                e.CellBounds.Height - 4);

            using (
                Brush gridBrush = new SolidBrush(this.GridColor),
                backColorBrush = new SolidBrush(e.CellStyle.BackColor),
                selectedColorBrush = new SolidBrush(e.CellStyle.SelectionBackColor))
            {
                using (Pen gridLinePen = new Pen(gridBrush))
                {
                    if (this.Rows[e.RowIndex].Selected)
                    {
                        e.Graphics.FillRectangle(selectedColorBrush, e.CellBounds);
                    }
                    else
                    {
                        e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
                    }
                    if (e.Value != null)
                    {
                        e.Graphics.DrawString((String)e.Value, e.CellStyle.Font,
                            Brushes.Black, e.CellBounds.X + 2,
                            e.CellBounds.Y + 2, StringFormat.GenericDefault);
                    }
                }
                e.Handled = true;
            }
        }
    }
}

效果图:

C# WinForm下DataGridView绘制背景图第1张

这段代码只能说明一个思路,如果要实用的话肯定得花些力气,比如说缩放时防止抖动,单元格的边框等等,我只是做一个原型,就不继续深入了。

免责声明:文章转载自《C# WinForm下DataGridView绘制背景图》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇thinkphp5实现文件上传ARM与MIPS平台优劣对比分析下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

winform小结

窗体是程序与用户交互的可视界面,窗体也是对象,窗体类定义了生成窗体的模版,实例化一个窗体类就产生了一个窗体。 .NET框架类库的System.Windows.Forms命名空间中定义的Form类是所有窗体类的基类。 1、常用属性 属性:图标、标题、位置、背景等可在窗体属性面板设置,也可以代码实现。 (1)Name属性:用来获取或设置窗体的名称,在应用程序中...

008-多线程-基础-ThreadGroup线程组

线程组ThreadGroup表示一组线程的集合,一旦一个线程归属到一个线程组之中后,就不能再更换其所在的线程组。那么为什么要使用线程组呢?个人认为有以下的好处:方便统一管理,线程组可以进行复制,快速定位到一个线程,统一进行异常设置等。ThreadGroup它其实并不属于Java并发包中的内容,它是java.lang中的内容。但是掌握对其的于理解,在实际应用...

winform把图片存储到数据库

1、先在Form中放一个PictureBox控件,再放三个按钮。 2、双击打开按钮,在里面写如下代码: OpenFileDialog open1 = newOpenFileDialog(); DialogResult isok =open1.ShowDialog(); if (isok ==DialogRe...

从网页抓取数据的一般方法

首先要了解对方网页的运行机制 ,这可以用httpwacth或者httplook来看一下http发送和接收的数据。这两个工具应该说是比较简单易懂的。这里就不再介绍了。主要关注的内容是header和post的内容。一般会包括cookie,Referer页面和其他一些乱其八糟可能看不懂的变量,还有就是正常交互的参数,比如需要post或者get的querystri...

Android日志监听工具logcat命令详解(转)

Android日志系统提供了记录和查看系统调试信息的功能。日志都是从各种软件和一些系统的缓冲区中记录下来的,缓冲区可以通过logcat命令来查看和使用. 在使用logcat之前,请确保手机的USB调试模式已经开启,可以通过"Setting->Application->Development->USB debugging"来开启。 logc...

【转】文本框(Textbox)和下拉框(Combobox)自动联想功能的实现

看见一大侠介绍这种联想的效果,很棒! 怎样使自己程序中的文本框或下拉框具有像百度和Google那样的自动联想功能?微软的TextBox和Combobox控件为我们提供了简便方法。 首先需要学习TextBox(或Combobox)的两个属性,一个属性是AutoCompleteMode,指定控件中使用的自动完成功能的模式,有四种模式,分别是: None:禁用控...