Título: Error Genérico en GDI+
Publicado por: bybaal en 9 Abril 2023, 08:22 am
Hola tengo esta función para convertir un bitmap a icono y en algunas ocasiones ocurre la excepción 'Error Genérico en GDI+' en la última línea, alguna idea de que pueda estar pasando Public Function ToIcon(Image As Image, Width As Integer, Height As Integer, Optional MakeTransparent As Boolean = False, Optional Transparent As Color = Nothing) As Icon ToIcon = Nothing If IsNothing(Transparent) Then Transparent = Color.White Dim thumb As Bitmap = CType(Image.GetThumbnailImage(Width, Height, Nothing, IntPtr.Zero), Bitmap) If MakeTransparent Then thumb.MakeTransparent(Transparent) ToIcon = Icon.FromHandle(thumb.GetHicon()) End Function
Título: Re: Error Genérico en GDI+
Publicado por: LlopoRobot en 9 Abril 2023, 17:45 pm
La excepción 'Error Genérico en GDI+' suele ocurrir cuando hay un problema con los recursos de GDI+ del sistema. Es posible que se esté produciendo una fuga de memoria o que se esté utilizando demasiada memoria. Para solucionar este problema, puedes intentar liberar los recursos de memoria de GDI+ llamando al método Dispose en la imagen de vista previa y en el objeto Bitmap, así: Public Function ToIcon(Image As Image, Width As Integer, Height As Integer, Optional MakeTransparent As Boolean = False, Optional Transparent As Color = Nothing) As Icon ToIcon = Nothing If IsNothing(Transparent) Then Transparent = Color.White Dim thumb As Bitmap = CType(Image.GetThumbnailImage(Width, Height, Nothing, IntPtr.Zero), Bitmap) If MakeTransparent Then thumb.MakeTransparent(Transparent) ToIcon = Icon.FromHandle(thumb.GetHicon()) thumb.Dispose() Image.Dispose() End Function
Además, asegúrate de que la imagen y el objeto Bitmap se estén utilizando dentro de un bloque Using o se estén liberando adecuadamente en otro lugar del código.
Título: Re: Error Genérico en GDI+
Publicado por: bybaal en 10 Abril 2023, 20:28 pm
Ya lo agregué, pero sigue el problema, por eso aquí comparto todo el código para que se vea mejor cual puede ser el problema Public Class Form1 Private WithEvents tmrRefresh As New Timer With {.Enabled = True, .Interval = 1} Private Sub tmrRefresh_Tick(sender As Object, e As EventArgs) Handles tmrRefresh.Tick Dim gr As Graphics Dim bmp As Bitmap = My.Resources.white Dim br As New SolidBrush(Color.Black) Dim free As String = AutoScaleSize(My.Computer.Info.AvailablePhysicalMemory, 2, False) Dim x() As String Dim por As Integer Dim colBar As Color Text = free x = Split(free) free = x(0) x = Split(free, ",") If Len(x(0)) = 1 Then x(0) = $"0{x(0)}" If Len(x(1)) = 1 Then x(1) = $"0{x(1)}" gr = Graphics.FromImage(bmp) gr.DrawString($"{x(0)},", New Font("Arial", 12, FontStyle.Bold), br, New PointF(0, 0)) gr.DrawString(x(1), New Font("Arial", 12, FontStyle.Bold), br, New PointF(0, 14)) por = Porciento(My.Computer.Info.AvailablePhysicalMemory, My.Computer.Info.TotalPhysicalMemory) Select Case por Case Is >= 75 : colBar = Color.Green Case Is >= 50 : colBar = Color.Yellow Case Is >= 25 : colBar = Color.Orange Case Is >= 0 : colBar = Color.Red End Select gr.DrawLine(New Pen(colBar, 5), 28, 2, 28, 30) Icon = ToIcon(bmp, 32, 32) bmp.Dispose() gr.Dispose() br.Dispose() End Sub End Class Module modExtras Public Function Porciento(Parte As ULong, Total As ULong, Optional Round As Boolean = False, Optional Decimals As Integer = 0) As Double Porciento = 0 Try Porciento = Parte * 100 / Total If Round Then Porciento = Math.Round(Porciento, Decimals) Catch ex As Exception End Try End Function Public Function ToIcon(Image As Image, Width As Integer, Height As Integer, Optional MakeTransparent As Boolean = False, Optional Transparent As Color = Nothing) As Icon ToIcon = Nothing 'Try If IsNothing(Transparent) Then Transparent = Color.White Dim thumb As Bitmap = CType(Image.GetThumbnailImage(Width, Height, Nothing, IntPtr.Zero), Bitmap) If MakeTransparent Then thumb.MakeTransparent(Transparent) ToIcon = Icon.FromHandle(thumb.GetHicon()) thumb.Dispose() Image.Dispose() 'Catch ex As Exception 'End Try End Function Public Function AutoScaleSize(Bytes As Decimal, Optional Decimals As Integer = 2, Optional FullName As Boolean = False, Optional BaseMil As Boolean = False) As String AutoScaleSize = "" Try Dim C As Integer Dim b As Decimal = Bytes Dim Div As Integer If BaseMil Then Div = 1000 Else Div = 1024 Do While b >= Div b /= Div C += 1 Loop b = Math.Round(b, Decimals) Select Case C Case 0 : If FullName Then Return b & " Bytes" Else Return b & " B" Case 1 : If FullName Then Return b & " KiloBytes" Else Return b & " KB" Case 2 : If FullName Then Return b & " MegaBytes" Else Return b & " MB" Case 3 : If FullName Then Return b & " GigaBytes" Else Return b & " GB" Case 4 : If FullName Then Return b & " TeraBytes" Else Return b & " TB" Case 5 : If FullName Then Return b & " PetaBytes" Else Return b & " PB" Case 6 : If FullName Then Return b & " ExaBytes" Else Return b & " EB" Case 7 : If FullName Then Return b & " ZettaBytes" Else Return b & " ZB" Case 8 : If FullName Then Return b & " YottaBytes" Else Return b & " YB" Case Else : If FullName Then Return Bytes & " Bytes" Else Return Bytes & " B" End Select Catch ex As Exception End Try End Function End Module
Título: Re: Error Genérico en GDI+
Publicado por: Elektro Enjuto en 30 Agosto 2023, 19:23 pm
El tamaño y las características de la imagen de recurso "white" son desconocidos, así que no soy capaz de reproducir el problema que describes. De todas formas, estás añadiendo una carga altísima y totalmente innecesaria al utilizar procedimientos de dibujado manual, generando una lentitud de respuesta en tu aplicación, y por culpa de un intervalo de temporizador tan reducido, todo para hacer cosas que son facilmente accesibles mediante las propiedades del Form... Primeramente, ¿por qué asignas la imagen de icono más de una única vez?. En cada iteración del temporizador vuelves a pasar por todo el procedimiento de copia de imagen y resscalado solo para volver a reasignar la misma imagen una y otra vez, sin descanso. Lo mismo haces al dibujar texto en la barra de título del form, cosa que puedes asignar mediante la propiedad Form.Text, y eso siempre estará mucho más optimizado que cualquier procedimiento casero de dibujado como el que estás utilizando. Por último aquí te dejo una versión simplificada de la función ToIcon, sin recurrir a la función GetThumbnailImage para no deteriorar la calidad inicial pre-obtención de icono: <DebuggerStepThrough> Public Function ToIcon(image As Image, size As Size, Optional makeTransparent As Boolean = False, Optional transparentColor As Color = Nothing) As Icon Using clone As New Bitmap(image, size) If makeTransparent AndAlso (transparentColor <> Color.Empty) Then clone.MakeTransparent(transparentColor) End If Return Icon.FromHandle(clone.GetHicon()) End Using End Function
Saludos.
|