有几点需要考虑:
- 当控件被绘制到位图时,DataGridView 的行和列必须可见,
- 可能存在滚动条,
- Rows 的高度可能不同,所以我们必须将所有行的高度相加,
- 列也是如此,因为每个列都有自己的宽度,
- CellFormatting可能已经到位,所以我们需要在绘制之前刷新DataGridView:不可见的行可能还没有格式化,
- 位图尺寸有限制 (32,767)。
按如下方式调用此方法,指定是否要包含行标题或列标题或排除两者,将True/False 作为ColumnHeaders 和@987654324 传递@ 参数。
dgv 参数当然是要绘制的 DataGridView 控件实例:
' Prints the DataGridView including the Columns' Headers only
Dim dgvBitmap = DataGridViewToBitmap(DataGridView1, True, False)
Dim imagePath = Path.Combine(AppContext.BaseDirectory, $"{NameOf(DataGridView1)}.tiff")
dgvBitmap.Save(imagePath, ImageFormat.Tiff)
' Dispose of the Bitmap or set it as the PictureBox.Image, dispose of it later.
dgvBitmap.Dispose()
Private Function DataGridViewToBitmap(dgv As DataGridView, ColumnHeaders As Boolean, RowHeaders As Boolean) As Bitmap
dgv.ClearSelection()
Dim originalSize = dgv.Size
dgv.Height = dgv.Rows.OfType(Of DataGridViewRow).Sum(Function(r) r.Height) + dgv.ColumnHeadersHeight
dgv.Width = dgv.Columns.OfType(Of DataGridViewColumn).Sum(Function(c) c.Width) + dgv.RowHeadersWidth
dgv.Refresh()
Dim dgvPosition = New Point(If(RowHeaders, 0, dgv.RowHeadersWidth), If(ColumnHeaders, 0, dgv.ColumnHeadersHeight))
Dim dgvSize = New Size(dgv.Width, dgv.Height)
If dgvSize.Height > 32760 OrElse dgvSize.Width > 32760 Then Return Nothing
Dim rect As Rectangle = New Rectangle(Point.Empty, dgvSize)
Using bmp As Bitmap = New Bitmap(dgvSize.Width, dgvSize.Height)
dgv.DrawToBitmap(bmp, rect)
If (dgv.Width > originalSize.Width) AndAlso dgv.ScrollBars.HasFlag(ScrollBars.Vertical) Then
dgvSize.Width -= SystemInformation.VerticalScrollBarWidth
End If
If (dgv.Height > originalSize.Height) AndAlso dgv.ScrollBars.HasFlag(ScrollBars.Horizontal) Then
dgvSize.Height -= SystemInformation.HorizontalScrollBarHeight
End If
dgvSize = New Size(dgvSize.Width - dgvPosition.X, dgvSize.Height - dgvPosition.Y)
dgv.Size = originalSize
Return bmp.Clone(New Rectangle(dgvPosition, dgvSize), PixelFormat.Format32bppArgb)
End Using
End Function