我正在寻找获取打印屏幕的最快方法,我发现使用Bitblt是我更好的选择,然而,它只适用于设备上下文句柄,这意味着对我来说,要从中检索位图,我必须使用包括CreateCompatibleBitmap在内的多个API,最终这可能与使用托管方式的时间相同,比如graphics.CopyFromScreen (对我来说有点慢,而且在2.3 the四核处理器上消耗了7-10%的CPU…)
然而,我仍然在寻找一种更干净的方法来从其中检索位图,所以我想出了这个代码:
<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帧/秒。但正如我上面所说的,它有两个问题:
即使我在上面做的那样在picturebox上显示它完成了我想要的事情,它也不会调整到picturebox控件的大小,即使我将那些"0“值更改为picturebox的x和y坐标。我进一步搜索,发现有一个StretchBit应用程序接口,它确实会拉伸,但它也会降低质量,(即使使用参数“半色调”对SetStretchBltMode进行必要的调用,这样它也不会“破坏”像素),它也会降低性能,至少在10+ fps中是这样的。
但由于我需要将其作为位图对象,加上其他必要的应用程序接口,我最终获得了几乎一半的性能(15~ fps),这相当于graphics.CopyFromScreen。
所以,我在问,有没有其他方法可以在不损失性能的情况下使用Bitblt或类似的方法从屏幕上获取位图?
如果没有.Net的方式,我很乐意请求任何语言的方式来实现。
发布于 2014-03-22 13:00:45
如果你想要原始的性能,你必须远离托管代码。在Visual Studio中使用C++非常容易。您可以直接调用Windows API,从而绕过.NET运行时、应用程序的托管代码以及.NET中p/调用的开销。
如果您熟悉C#,您可以将您的C#代码转换为C++ (这应该很简单,需要做很多工作来取代C#)。
发布于 2014-03-23 02:27:48
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使用只有一个picturebox和一个标签的窗体。相应地设置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 最大化表单并在picturebox中单击。
https://stackoverflow.com/questions/22573522
复制相似问题