65.9K
CodeProject 正在变化。 阅读更多。
Home

自定义绘制 DataGridView 列标题(Excel 2007 风格)

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.94/5 (9投票s)

2007年1月28日

CPOL

3分钟阅读

viewsIcon

94670

downloadIcon

2304

重写 DataGridView 的 cellpaint 事件,使其具有渐变背景。

Sample Image - GradientColumnheader.png

引言

我一直在使用 CodeProject 作为一个可靠的资源,因为它帮助我提高了开发技能。我觉得现在是我自己发布内容的时候了。最近我下载了新的 Office 2007,并且对新的布局感到非常兴奋。我经常处理数据,并且想改进 DataGridView 的界面,使其列标题类似于 Excel 2007 中的列标题,并具有一些渐变颜色。

概述

我首先尝试了列标题,并且发现我必须关闭 EnableHeadersVisibleStyle 选项才能获得背景颜色。然而,单一的颜色看起来并不像 Office 2007 中的渐变标题。

所以,我更深入地研究,并在重写 DataGridView 的 cell paint 事件中找到了解决方案。列标题的 rowindex 为 -1,这使得将该方法限制为仅在列标题上执行变得容易。在重写 cell paint 事件时,有很多选项可供选择,以便获得自定义绘制的列标题。我选择使用 Graphics 对象和 DrawImage 方法,这允许我使用图像资源作为背景。这为将代码重新用作皮肤项目的一部分提供了可能性,但目前这超出了我的需求。

由于使用了 Graphics 对象,因此有其他选择来自定义绘制 DataGridView 列标题,例如使用 LinearGradientBrush。要做到这一点,只需将方法的 DrawImage 部分替换为 FillRectangle 方法。

代码

在窗体的打开事件中,我编写了一些代码来填充 DataGridView。我们在这里跳过这部分。

您可以选择创建一个继承自 DataGridView 的类,并在那里重写 cell paint 事件,或者您可以直接在窗体类中重写该事件(我在示例中选择了第二种选择)。

代码如下:

Private Sub DataGridView1_CellPainting(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) _
        Handles DataGridView1.CellPainting
    If e.RowIndex = -1 Then
        Dim img As Image
        img = My.Resources.Header
        TekenAchtergrond(e.Graphics, img, e.CellBounds, 1)
        Dim format1 As StringFormat
        format1 = New StringFormat
        format1.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show
        Dim ef1 As SizeF = e.Graphics.MeasureString(e.Value, Me.Font, _
            New SizeF(CType(e.CellBounds.Width, Single), _
            CType(e.CellBounds.Height, Single)), format1)

        Dim txts As Size
        txts = Drawing.Size.Empty

        txts = Drawing.Size.Ceiling(ef1)
        e.CellBounds.Inflate(-4, -4)

        Dim txtr As Rectangle = e.CellBounds
        txtr = HAlignWithin(txts, txtr, ContentAlignment.MiddleCenter)
        txtr = VAlignWithin(txts, txtr, ContentAlignment.MiddleCenter)
        Dim brush2 As Brush
        format1 = New StringFormat
        format1.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show

        brush2 = New SolidBrush(Color.FromArgb(21, 66, 139))

        e.Graphics.DrawString(e.Value, Me.Font, brush2, _
                              CType(txtr, RectangleF), format1)
        brush2.Dispose()
        Dim recBorder As New Rectangle(e.CellBounds.X - 1, e.CellBounds.Y, _
                         e.CellBounds.Width, e.CellBounds.Height - 1)
        e.Graphics.DrawRectangle(Pens.LightSlateGray, recBorder)

        e.Handled = True
    End If
End Sub

CellPaint 事件中,我从资源文件中获取标题背景,并将其与 Graphics 对象、绘制矩形和一个索引参数一起传递给 Tekenachtergrond 方法。如果图像文件包含多个模板,该索引参数可以用于皮肤目的。(我来自比利时,tekenachtergrond 是荷兰语,意思是类似于绘制背景)。由于在此示例中我只使用一个模板,所以我将索引设置为 1。

该方法基于我在本网站上找到的一篇文章,它处理控件的皮肤(链接到文章),以及一些额外的对齐方法和变量,如下所示:

Private Sub TekenAchtergrond(ByVal g As Graphics, _
        ByVal obj As Image, ByVal r As Rectangle, _
        ByVal index As Integer)
    If (obj Is Nothing) Then
        Return
    End If
    Dim oWidth As Integer = obj.Width
    Dim lr As Rectangle = Rectangle.FromLTRB(0, 0, 0, 0)
    Dim r2 As Rectangle
    Dim r1 As Rectangle
    Dim x As Integer = ((index - 1) _
                * oWidth)
    Dim y As Integer = 0
    Dim x1 As Integer = r.Left
    Dim y1 As Integer = r.Top
    If ((r.Height > obj.Height) _
                AndAlso (r.Width <= oWidth)) Then
        r1 = New Rectangle(x, y, oWidth, lr.Top)
        r2 = New Rectangle(x1, y1, r.Width, lr.Top)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        r1 = New Rectangle(x, (y + lr.Top), oWidth, (obj.Height _
                        - (lr.Top - lr.Bottom)))
        r2 = New Rectangle(x1, (y1 + lr.Top), r.Width, (r.Height _
                        - (lr.Top - lr.Bottom)))
        If ((lr.Top + lr.Bottom) _
                    = 0) Then
            r1.Height = (r1.Height - 1)
        End If
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        r1 = New Rectangle(x, (y _
                        + (obj.Height - lr.Bottom)), oWidth, lr.Bottom)
        r2 = New Rectangle(x1, (y1 _
                        + (r.Height - lr.Bottom)), r.Width, lr.Bottom)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
    ElseIf ((r.Height <= obj.Height) _
                AndAlso (r.Width > oWidth)) Then
        r1 = New Rectangle(x, y, lr.Left, obj.Height)
        r2 = New Rectangle(x1, y1, lr.Left, r.Height)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        r1 = New Rectangle((x + lr.Left), y, (oWidth _
                        - (lr.Left - lr.Right)), obj.Height)
        r2 = New Rectangle((x1 + lr.Left), y1, (r.Width _
                        - (lr.Left - lr.Right)), r.Height)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        r1 = New Rectangle((x _
                        + (oWidth - lr.Right)), y, lr.Right, obj.Height)
        r2 = New Rectangle((x1 _
                        + (r.Width - lr.Right)), y1, lr.Right, r.Height)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
    ElseIf ((r.Height <= obj.Height) _
                AndAlso (r.Width <= oWidth)) Then
        r1 = New Rectangle(((index - 1) _
                        * oWidth), 0, oWidth, (obj.Height - 1))

        g.DrawImage(obj, New Rectangle(x1, y1, r.Width, r.Height), _
                    r1, GraphicsUnit.Pixel)
    ElseIf ((r.Height > obj.Height) _
                AndAlso (r.Width > oWidth)) Then
        'top-left
        r1 = New Rectangle(x, y, lr.Left, lr.Top)
        r2 = New Rectangle(x1, y1, lr.Left, lr.Top)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'top-bottom
        r1 = New Rectangle(x, (y _
                        + (obj.Height - lr.Bottom)), lr.Left, lr.Bottom)
        r2 = New Rectangle(x1, (y1 _
                        + (r.Height - lr.Bottom)), lr.Left, lr.Bottom)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'left
        r1 = New Rectangle(x, (y + lr.Top), lr.Left, (obj.Height _
                        - (lr.Top - lr.Bottom)))
        r2 = New Rectangle(x1, (y1 + lr.Top), lr.Left, (r.Height _
                        - (lr.Top - lr.Bottom)))
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'top
        r1 = New Rectangle((x + lr.Left), y, (oWidth _
                        - (lr.Left - lr.Right)), lr.Top)
        r2 = New Rectangle((x1 + lr.Left), y1, (r.Width _
                        - (lr.Left - lr.Right)), lr.Top)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'right-top
        r1 = New Rectangle((x _
                        + (oWidth - lr.Right)), y, lr.Right, lr.Top)
        r2 = New Rectangle((x1 _
                        + (r.Width - lr.Right)), y1, lr.Right, lr.Top)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'Right
        r1 = New Rectangle((x _
                        + (oWidth - lr.Right)), (y + lr.Top), lr.Right, (obj.Height _
                        - (lr.Top - lr.Bottom)))
        r2 = New Rectangle((x1 _
                        + (r.Width - lr.Right)), (y1 + lr.Top), lr.Right, (r.Height _
                        - (lr.Top - lr.Bottom)))
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'right-bottom
        r1 = New Rectangle((x _
                        + (oWidth - lr.Right)), (y _
                        + (obj.Height - lr.Bottom)), lr.Right, lr.Bottom)
        r2 = New Rectangle((x1 _
                        + (r.Width - lr.Right)), (y1 _
                        + (r.Height - lr.Bottom)), lr.Right, lr.Bottom)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'bottom
        r1 = New Rectangle((x + lr.Left), (y _
                        + (obj.Height - lr.Bottom)), (oWidth _
                        - (lr.Left - lr.Right)), lr.Bottom)
        r2 = New Rectangle((x1 + lr.Left), (y1 _
                        + (r.Height - lr.Bottom)), (r.Width _
                        - (lr.Left - lr.Right)), lr.Bottom)
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
        'Center
        r1 = New Rectangle((x + lr.Left), (y + lr.Top), (oWidth _
                        - (lr.Left - lr.Right)), (obj.Height _
                        - (lr.Top - lr.Bottom)))
        r2 = New Rectangle((x1 + lr.Left), (y1 + lr.Top), (r.Width _
                        - (lr.Left - lr.Right)), (r.Height _
                        - (lr.Top - lr.Bottom)))
        g.DrawImage(obj, r2, r1, GraphicsUnit.Pixel)
    End If
End Sub

您可以在本文顶部的附件屏幕截图中看到结果如何,或者您可以直接下载代码并在Release文件夹中执行 exe 文件。

我希望这段小代码对某些人有用,就像我在本网站上找到的许多优秀的示例代码一样。

© . All rights reserved.