2011-12-10 20 views
5

He estado haciendo una aplicación para tomar instantáneas de sitios web. todo funciona bien, hasta ahora: tengo la aplicación tomar fotos muchos, y el proceso de la toma de imágenes se realiza de la siguiente manera:El parámetro es una excepción no válida al usar Graphics.GetHdc

using (Graphics graphics = Graphics.FromImage(mBitmap)) 
{ 
    IntPtr hdc = graphics.GetHdc(); 
    SendMessage(new HandleRef(mWebBrowser, mWebBrowser.Handle), 791, hdc, (IntPtr)30); 
    BitBlt(new HandleRef(graphics, hdc), 0, 0, mBitmap.Width, mBitmap.Height, new HandleRef(graphics, hdc), 0, 0, 13369376); 
    graphics.ReleaseHdc(); 
} 

(esta es una variación de un código de DrawToBitmap desde el control WebBrowser tomado con ILSpy).

El error ocurre en el IntPtr hdc = graphics.GetHdc(); línea.

Busqué personas que preguntaran acerca de este "Parámetro no es válido" cuando usan el método GetHdc, y la gente dijo que podría ser por no haber liberado objetos GDI anteriores. este no es el caso, dado que el objeto Graphics está usando una instrucción using, y también lo es el mapa de bits ...

Tengo que tener en cuenta que tengo muchos webbrowers al mismo tiempo (nunca los destruyo, repito utilícelos, esto es por otro error que tuve y esta fue la única forma en que pude resolverlo ...)

Cuando estoy buscando en el TaskManager la cantidad de objetos GDI, veo que es un enorme cantidad. Pero - el error no ocurrió cuando tuve la mayoría de los objetos GDI ... Supongo que esta cantidad de objetos proviene de los WebBrowsers ...?

El código original del DrawToBitmap ILSpy es:

int nWidth = Math.Min(this.Width, targetBounds.Width); 
int nHeight = Math.Min(this.Height, targetBounds.Height); 
Bitmap image = new Bitmap(nWidth, nHeight, bitmap.PixelFormat); 
using (Graphics graphics = Graphics.FromImage(image)) 
{ 
    IntPtr hdc = graphics.GetHdc(); 
    UnsafeNativeMethods.SendMessage(new HandleRef(this, this.Handle), 791, hdc, (IntPtr)30); 
    using (Graphics graphics2 = Graphics.FromImage(bitmap)) 
    { 
     IntPtr hdc2 = graphics2.GetHdc(); 
     SafeNativeMethods.BitBlt(new HandleRef(graphics2, hdc2), targetBounds.X, targetBounds.Y, nWidth, nHeight, new HandleRef(graphics, hdc), 0, 0, 13369376); 
     graphics2.ReleaseHdcInternal(hdc2); 
    } 
    graphics.ReleaseHdcInternal(hdc); 
} 

La documentación afirma que Webbrowser no soporta DrawToBitmap, pero funciona muy bien hasta que alguna etapa en la que acaba de lanza esta excepción.

+1

Hay un límite de sistema para la cantidad _total_ de identificadores disponibles. Pero pensé que era bastante alto en estos días. –

+0

Estoy un poco confundido por qué estás creando múltiples 'HandleRef's para la misma llamada. Probablemente sea mejor escribir 'var href = new HandleRef (graphics, hdc)', y luego pasar esa ref en ambos lugares a 'BitBlt'. Dicho eso, aparentemente no es el problema? También me pregunto por qué estás llamando 'BitBlt' en lugar de usar' Graphics.DrawImage' o algo así. –

+0

El navegador web está oculto. como dije entre paréntesis, este código fue variado de un código tomado de ILSPy en System.windows.forms. Lo hice porque quería tener un mayor grado de control sobre lo que sucede, en lugar de simplemente usar WebBrowser.DrawToBitmap. Gracias por el comentario sobre los HandleRefs. –

Respuesta

1

Incluso este post es muy antiguo Quiero ayudar a resolver este problema, porque tenía la misma y he resuelto de esta manera:

private static Graphics graphics = null; 
private static IntPtr hdc = IntPtr.Zero; 
private static IntPtr dstHdc = IntPtr.Zero; 

private static Capture() 
{ 
    if (graphics == null) 
    { 
     hdc = GetDC(IntPtr.Zero); 
     graphics = Graphics.FromImage(bitmap); 
     dstHdc = graphics.GetHdc(); 
    } 
    BitBlt(dstHdc, 0, 0, screen_resolution.Width, screen_resolution.Height, hdc, 0, 0, RasterOperation.SRC_COPY); 
} 

La solución para mí fue, que yo llamo graphics.GetHdc() solo una vez cuando el objeto es cero. Después de eso, nunca uso call graphics.GetHdc().

Cuestiones relacionadas