使用Bitblt截图

时间:2014-03-22 04:36:04

标签: vb.net winapi

我正在寻找最快的打印方式,我发现使用Bitblt是我更好的选择,但是,它只适用于设备上下文句柄,这对我来说意味着要从中检索位图,我必须使用多个API,包括CreateCompatibleBitmap,最终它可能需要与使用托管方式相同的时间,如graphics.CopyFromScreen(这有点慢)对我来说也消耗了大量CPU,在2.3ghz四核处理器上占7-10%......)

但是,我仍在搜索从中检索位图的更简洁方法,所以我想出了这段代码:

<DllImport("user32.dll")> _
Public Shared Function GetDC(ByVal hWnd As IntPtr) As IntPtr
End Function

<DllImport("user32.dll")> _
Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Integer
End Function

<DllImport("gdi32.dll")> _
Public Shared Function BitBlt(ByVal hdcDest As IntPtr, ByVal xDest As Integer, ByVal yDest As Integer, ByVal wDest As Integer, ByVal hDest As Integer, ByVal hdcSource As IntPtr, _
ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal rop As TernaryRasterOperations) As Boolean
End Function

    Dim hwNd As IntPtr = Nothing

    hwNd = GetDC(GetDesktopWindow)

    picHandle = GetDC(Me.PictureBox1.Handle)

    BitBlt(picHandle, 0, 0, PictureBox1.Width, PictureBox1.Height, hwNd, 0, 0, TernaryRasterOperations.SRCCOPY)

    ReleaseDC(hwNd, picHandle)

我可以达到~30 fps ......但它有两个问题,如上所述:

即使将它显示在图片框上,因为我在上面完成了我想要的操作,它也不会调整到图片框控件的大小,即使我改变了那些&#34; 0&#34;图片框x和y坐标的值。 我进一步搜索并找到了StretchBit API,它确实拉伸,但它也降低了质量,(即使必须使用参数&#34调用SetStretchBltMode; HALFTONE&#34;所以它没有&#39; t&#34;腐败&#34;像素),它还会降低性能至少10+ fps ......

但是因为我需要将它作为位图对象,以及其他必要的API,我最终得到了几乎一半的性能(15~fps),这相当于graphics.CopyFromScreen。

所以,我问,是否有另一种方法可以在不丢失性能的情况下使用Bitblt或类似方法从屏幕上获取位图?

如果没有.Net方式,我恳请任何语言方式。

2 个答案:

答案 0 :(得分:0)

如果您想要原始性能,则必须远离托管代码。使用C ++和Visual Studio很容易。您可以直接调用Windows API,绕过.NET运行时,应用程序的托管代码以及.NET中p / invokes的开销。

如果您熟悉C#,可以使用C#代码,将其转换为C ++(这应该很简单,需要大量工作来替换CLI)。

答案 1 :(得分:0)

Private Declare Function BitBlt Lib "GDI32" ( _
    ByVal hdcDest As Integer, _
    ByVal nXDest As Integer, _
    ByVal nYDest As Integer, _
    ByVal nWidth As Integer, _
    ByVal nHeight As Integer, _
    ByVal hdcSrc As Integer, _
    ByVal nXSrc As Integer, _
    ByVal nYSrc As Integer, _
    ByVal dwRop As System.Int32) As Boolean

Declare Function QueryPerformanceCounter Lib "Kernel32" (ByRef X As Long) As Short
Declare Function QueryPerformanceFrequency Lib "Kernel32" (ByRef X As Long) As Short

Const SRCCOPY As Integer = &HCC0020

使用仅包含图片框和标签的表单。相应地设置picbox的锚点。在picbox down事件中:

Private Sub PictureBox1_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    Dim Ctr1, Ctr2, Freq As Long
    Dim dbl As Double

    QueryPerformanceCounter(Ctr1)


    Dim desktopDC As IntPtr = Nothing
    Dim picboxDC As IntPtr = Nothing

    desktopDC = GetDC(New IntPtr(0))

    picboxDC = GetDC(PictureBox1.Handle)

    BitBlt(picboxDC, 0, 0, PictureBox1.Width, PictureBox1.Height, desktopDC, 0, 0, SRCCOPY)

    QueryPerformanceCounter(Ctr2)
    QueryPerformanceFrequency(Freq)

    dbl = (Ctr2 - Ctr1) / Freq

    dbl *= 1000000

    Label1.Text = dbl.ToString 'it is in microseconds

    ReleaseDC(New IntPtr(0), desktopDC)
    ReleaseDC(PictureBox1.Handle, picboxDC)

End Sub 

最大化您的表单并点击图片框。