zoukankan      html  css  js  c++  java
  • C# WinForm下DataGridView绘制背景图

    昨天一个朋友突然问我如何在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;
                }
            }
        }
    }
    

    效果图:

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

  • 相关阅读:
    图片展示,带分页
    miniui动态合并datagrid列
    使用webcam和video插件/华为云播放插件,实现视频播放及拍照上传功能
    Java实现excel导出(内容循环多个)
    C# 图片与Base64互转
    C#中将字符串转成 Base64 编码 (加密--解密)
    ASP.NET导出Excel之二
    利用Aspose转PDF
    ASP.NET视频播放
    Oracle存储过程导入,判断已有数据更新,没有的数据导入,统计导入成功与失败数,返回一个表
  • 原文地址:https://www.cnblogs.com/think8848/p/2103971.html
Copyright © 2011-2022 走看看