在 .NET 2.0 VB 应用程序中为 x86 编译时,BitBlt 函数会生成空位图
我的 VB 项目中有一个 BitBlt 包装函数。当编译为 Any CPU 时它工作得很好,但是当我将它瞄准 x86 时它会创建一个空位图。我必须使用 x86,因为应用程序的其他部分需要它。有什么想法可能是错的吗?这是代码:
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
谢谢, 布莱恩
I have a BitBlt wrapper function in my VB project. It works just fine when compiled as Any CPU, but when I aim it at x86 it creates an empty bitmap. I must use x86 as other parts of the app require it. Any ideas what could be wrong? Here is the code:
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
Thanks,
brian
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是 VB.NET 的一个非常经典的问题,pinvoke 声明是错误的。您使用的仅适用于 VB6,由于历史原因,该语言使用 Integer 表示 16 位数字,使用 Long 表示 32 位数字。这可以追溯到在 16 位操作系统上运行的 VB 早期版本。 VB.NET 经过重新设计,可以在 32 位操作系统上正常运行,其 Integer 为 32 位,Long 为 64 位。您必须将参数声明为整数。它偶然在 64 位模式下工作。
使用 pinvoke.net 获取正确的声明。
仔细查看 Graphics.CopyFromScreen 和 Control.DrawToBitmap 以获得非常相似的功能,而无需 pinvoke。
It's a pretty classic problem with VB.NET, the pinvoke declaration is wrong. The one you use only works for VB6, a language that for historical reasons uses Integer for a 16-bit number, Long for a 32-bit number. This goes back to early versions of VB that ran on 16-bit operating systems. VB.NET was redesigned to work well on 32-bit operating systems, its Integer is 32 bits, its Long is 64 bits. You have to declare the arguments as Integer. It works in 64-bit mode by accident.
Use pinvoke.net to get the proper declaration.
And take a good look at Graphics.CopyFromScreen and Control.DrawToBitmap for very similar functionality without needing pinvoke.