【问题标题】:How to solve 'Generic error occured in GDI+'如何解决“GDI+ 中发生一般错误”
【发布时间】:2014-08-28 20:06:10
【问题描述】:

目标

能够在我的 DataGridViews 中绘制行,以帮助用户更好地了解应用程序中正在发生的事情。以这张图片为例:

  • 浅红色 = 已删除
  • 黄色 = 与选项类型选择的关系(左上角)
  • 亮红色 = 已删除并与所选选项类型相关(左上角)


问题

当我在我的选项类型 DataGridView 中上/下时,它将根据我选择的选项类型绘制强制和附加部分。在这样做了一段时间(大约 70 次)之后,我在 GDI 中得到了一般错误。

如您在上面的屏幕截图中所见,其中一个附加编辑按钮未正确显示(这是发生错误的地方)。它总是在下面一行:

ico = Icon.FromHandle(bmpFind.GetHicon)

完整代码如下:

代码

Private Sub dgvAdditionalOptions_CellPainting(sender As Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgvAdditionalOptions.CellPainting
    'Dim bmpFind As Bitmap
    Dim drRow As HunterManagement.dtConveyorFunctionAdditionalOptionsRow
    Dim myOptn As clsOptions

    If dgvAdditionalOptions.Columns(e.ColumnIndex).Name = "ColBtnEditAdditional" AndAlso e.RowIndex >= 0 Then
        drRow = dsHunterManagement.dtConveyorFunctionAdditionalOptions.FindByPK_ConveyorFunctionAdditionalOption(dgvAdditionalOptions.Rows(e.RowIndex).Cells("PK_ConveyorFunctionAdditionalOption").Value)
        myOptn = New clsOptions(CInt(drRow.FK_Option))
        e.Paint(e.CellBounds, DataGridViewPaintParts.All)

        If Not drRow Is Nothing AndAlso myOptn.InDrawing Then
            Using bmpFind As Bitmap = My.Resources.Edit_16x16_2 'Use 16x16 PNG / BitMap images
                Using ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
                    e.Graphics.DrawIcon(ico, e.CellBounds.Left + 3, e.CellBounds.Top + 2.5)
                    e.Handled = True
                End Using
            End Using
        Else
            Using bmpFind As Bitmap = My.Resources.Edit_Disabled_16x16_2 'Use 16x16 PNG / BitMap images
                Using ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
                    e.Graphics.DrawIcon(ico, e.CellBounds.Left + 3, e.CellBounds.Top + 2.5)
                    e.Handled = True
                End Using
            End Using
        End If
    ElseIf dgvAdditionalOptions.Columns(e.ColumnIndex).Name = "ColBtnDeleteAdditional" AndAlso e.RowIndex >= 0 Then
        e.Paint(e.CellBounds, DataGridViewPaintParts.All)
        Using bmpFind As Bitmap = My.Resources.Delete_16x16 'Use 16x16 PNG / BitMap images
            Using ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
                e.Graphics.DrawIcon(ico, e.CellBounds.Left + 2, e.CellBounds.Top + 2.5)
                e.Handled = True
            End Using
        End Using
    End If
End Sub

我尝试搜索这个问题,它都与“保存”图像有关......虽然我没有保存图像,我只是得到 BMP 图像的图标。我一定是忘记处理一些东西了。

有什么想法吗?

【问题讨论】:

  • 您正在使用位图和图标对象来显示看起来过多的图像。如果该列是DataGridViewImageColumn,您只需使用一张图片即可。
  • @Plutonix 我正在使用DataGridViewButtonColumn 并试图将它们保持为 16x16 大小的格式。我什至对其进行了调整以使用DataGridViewDisableButtonColumn

标签: vb.net winforms datagridview gdi+


【解决方案1】:

这个错误通常是由我的 gdi+ 泄漏引起的。您需要 Dispose Icon 这是一个 gdi+ 资源。完成后添加ico.Dispose

使用Icon.FromHandle时,需要通过DestroyIcon API手动清理。

使用此方法时,您必须使用 Win32 API 中的 DestroyIcon 方法以确保资源是 发布。

请参考this answer,Hans 给出了解决此问题的方法。

还请注意,当您从Resources.YourBitmap 获取它时,您也必须DisposeBitmap,因为Resources.YourBitmap 基本上每次调用它时都会创建一个新的位图。 Bitmap 也是一个 gdi+ 资源,你也应该处理它。

正如@Hanspassant 在 cmets 中指出的那样,更喜欢 Using 语句而不是 Dispose 资源。它们提供了一种方便可靠的资源处理方式。

【讨论】:

  • 我在 e.Graphics.DrawIcon() 之后尝试过,它仍然可以。我没有把它放在正确的地方吗?
  • 更新了我的答案,你需要调用DestroyIcon api。我建议您将 Icon 存储为实例字段,无需一次又一次地创建新的。这也是另一种解决方法。
  • +1 寻求帮助。明天我回去工作的时候试试看。如果它有效,我会接受你的回答。再次感谢您的帮助
  • 您需要指出位图也需要处理。没关系,它们是资源。并推荐 Using 语句。
  • @HansPassant 原来的问题就在那里,如果你看到编辑历史你就会知道。这就是我没有指出的原因。我也会补充的。谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 2019-11-18
  • 1970-01-01
相关资源
最近更新 更多