función BitBlt produce mapa de bits vacío cuando compilado para x86 en .NET aplicación 2.0 VB
Pregunta
Tengo una función de contenedor BitBlt en mi proyecto de VB. Funciona muy bien cuando se compila como cualquiera de las CPU, pero cuando me apunto al 86 crea un mapa de bits vacío. Debo usar x86 como otras partes de la aplicación así lo requieran. ¿Alguna idea sobre que podría ir mal? Aquí está el código:
Imports System.Drawing.Imaging
''' <summary>
''' Provides the static method ControlCapture used to
''' take screenshots of the specified control.
''' </summary>
''' <remarks>This fails unless compiled targeting Any CPU!!!</remarks>
Public Class ControlCapture
''' <summary>
''' Pointer to gdi.exe win32 function.
''' </summary>
''' <param name="hDestDC">destination device context</param>
''' <param name="x">x coord. of output rectangle</param>
''' <param name="y">y coord. of output rectangle</param>
''' <param name="nWidth">width of source and dest. rectangle</param>
''' <param name="nHeight">height of source and dest. rectangle</param>
''' <param name="hSrcDC">source device context</param>
''' <param name="xSrc">x coord. of rectangle to capture</param>
''' <param name="ySrc">y coord. of rectangle to capture</param>
''' <param name="dwRop">mode (raster op)</param>
''' <returns>0 on failure, non-zero on success</returns>
''' <remarks>from http://support.microsoft.com/kb/147810 </remarks>
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, _
ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _
ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, _
ByVal ySrc As Long, ByVal dwRop As Long) As Long
''' <summary>
''' Grab a screen capture of the given control.
''' </summary>
''' <param name="control">control to grab</param>
''' <returns>Bitmap image</returns>
''' <remarks>used by mappoint map viewer and bing map viewer</remarks>
Public Shared Function ControlCapture(ByVal control As Control) As Bitmap
'capture params
Dim width As Integer = control.Width
Dim height As Integer = control.Height
'output object
Dim bitmap As Bitmap = New Bitmap(width, height, PixelFormat.Format32bppArgb)
'get handles to source and destination objects as graphics
Dim sourceGraphics As Graphics = control.CreateGraphics()
Dim destGrahpics As Graphics = Drawing.Graphics.FromImage(bitmap)
'actual handles
Dim sourceGraphicsPointer As System.IntPtr = sourceGraphics.GetHdc()
Dim destGraphicsPointer As System.IntPtr = destGrahpics.GetHdc()
'get references as ints
Dim destAddress As Integer = destGraphicsPointer
Dim sourceAddress As Integer = sourceGraphicsPointer
'call win32 api
BitBlt(destAddress, 0, 0, width, height, sourceAddress, 0, 0, Codes.SourceCopy)
'clean up
sourceGraphics.ReleaseHdc(sourceGraphicsPointer)
destGrahpics.ReleaseHdc(destGraphicsPointer)
Return bitmap
End Function
''' <summary>
''' SRCCOPY(CC0020) Copies the source bitmap to destination bitmap.
''' </summary>
''' <remarks>From http://support.microsoft.com/kb/147810 </remarks>
Private Enum Codes
SourceCopy = &HCC0020
End Enum
End Class
Gracias, Brian
Solución
Es un problema bastante clásico con VB.NET, la declaración PInvoke está mal. El que sólo utiliza trabaja para VB6, un lenguaje que por razones históricas utiliza un número entero de 16 bits, mucho tiempo para un número de 32 bits. Esto se remonta a las primeras versiones de VB que se ejecutaban en sistemas operativos de 16 bits. VB.NET fue rediseñada para funcionar bien en sistemas operativos de 32 bits, el número entero es de 32 bits, su largo es de 64 bits. Usted tiene que declarar los argumentos como enteros. Funciona en modo de 64 bits por accidente.
pinvoke.net para obtener la declaración correspondiente.
Y echar un vistazo bueno en Graphics.CopyFromScreen y Control.DrawToBitmap para una funcionalidad muy similar sin necesidad PInvoke.