在 .NET 2.0 VB 应用程序中为 x86 编译时,BitBlt 函数会生成空位图

发布于 2024-09-25 17:31:21 字数 3382 浏览 6 评论 0原文

我的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

守护在此方 2024-10-02 17:31:21

这是 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文