C# 使用BitBlt进行窗口抓图的示例
本文和C++使用BitBlt进行窗口抓图对应,使用C#实现。
这种方式对1920*1080大小的窗口,一次抓图的时间参考(VS2015+i59400F):低至2~3ms(平均4.3ms)。
参见:C#抓图服务。
1、Win32封装
Win32Consts
usingSystem.ComponentModel; namespaceCaptureSharp { publicsealedclassWin32Consts { publicenumDibColorMode:uint { DIB_RGB_COLORS=0x00, DIB_PAL_COLORS=0x01, DIB_PAL_INDICES=0x02 } publicenumBitmapCompressionMode:uint { BI_RGB=0, BI_RLE8=1, BI_RLE4=2, BI_BITFIELDS=3, BI_JPEG=4, BI_PNG=5 } publicenumRasterOperationMode:uint { SRCCOPY=0x00CC0020, SRCPAINT=0x00EE0086, SRCAND=0x008800C6, SRCINVERT=0x00660046, SRCERASE=0x00440328, NOTSRCCOPY=0x00330008, NOTSRCERASE=0x001100A6, MERGECOPY=0x00C000CA, MERGEPAINT=0x00BB0226, PATCOPY=0x00F00021, PATPAINT=0x00FB0A09, PATINVERT=0x005A0049, DSTINVERT=0x00550009, BLACKNESS=0x00000042, WHITENESS=0x00FF0062, CAPTUREBLT=0x40000000//onlyifWinVer>=5.0.0(seewingdi.h) } publicenumPrintWindowMode:uint { [Description( "OnlytheclientareaofthewindowiscopiedtohdcBlt.Bydefault,theentirewindowiscopied.")] PW_CLIENTONLY=0x00000001, [Description("worksonwindowsthatuseDirectXorDirectComposition")] PW_RENDERFULLCONTENT=0x00000002 } } }
Win32Types
usingSystem.Runtime.InteropServices; namespaceCaptureSharp { publicsealedclassWin32Types { [StructLayout(LayoutKind.Sequential)] publicstructPoint { publicintx; publicinty; publicPoint(intx,inty) { this.x=x; this.y=y; } } [StructLayout(LayoutKind.Sequential)] publicstructRect { publicintLeft;//最左坐标 publicintTop;//最上坐标 publicintRight;//最右坐标 publicintBottom;//最下坐标 publicintWidth=>Right-Left; publicintHeight=>Bottom-Top; } [StructLayout(LayoutKind.Sequential,Pack=2)] publicstructBitmapFileHeader { publicushortbfType; publicuintbfSize; publicushortbfReserved1; publicushortbfReserved2; publicuintbfOffBits; } [StructLayout(LayoutKind.Sequential)] publicstructBitmapInfoHeader { publicuintbiSize; publicintbiWidth; publicintbiHeight; publicushortbiPlanes; publicushortbiBitCount; publicuintbiCompression; publicuintbiSizeImage; publicintbiXPelsPerMeter; publicintbiYPelsPerMeter; publicuintbiClrUsed; publicuintbiClrImportant; publicvoidInit() { biSize=(uint)Marshal.SizeOf(this); } } [StructLayout(LayoutKind.Sequential,Pack=1)] publicstructRgbQuad { publicbytergbBlue; publicbytergbGreen; publicbytergbRed; publicbytergbReserved; } [StructLayout(LayoutKind.Sequential,Pack=1)] publicstructBitmapInfo { publicBitmapInfoHeaderbmiHeader; publicRgbQuadbmiColors; } } }
Win32Funcs
usingSystem; usingSystem.Runtime.InteropServices; namespaceCaptureSharp { publicsealedclassWin32Funcs { [DllImport("User32.dll",SetLastError=true)] publicstaticexternIntPtrFindWindow(stringlpClassName,stringlpWindowName); [DllImport("user32.dll")] [return:MarshalAs(UnmanagedType.Bool)] publicstaticexternboolGetWindowRect(IntPtrhWnd,outWin32Types.RectlpRect); [DllImport("user32.dll")] publicstaticexternboolGetClientRect(IntPtrhWnd,outWin32Types.RectlpRect); [DllImport("user32.dll",EntryPoint="GetWindowDC")] publicstaticexternIntPtrGetWindowDC(IntPtrhWnd); [DllImport("gdi32.dll")] publicstaticexternIntPtrCreateCompatibleDC(IntPtrhDc); [DllImport("gdi32.dll")] publicstaticexternIntPtrCreateCompatibleBitmap(IntPtrhDc,intnWidth,intnHeight); [DllImport("gdi32.dll")] publicstaticexternboolDeleteDC(IntPtrhDc); [DllImport("user32.dll")] publicstaticexternIntPtrReleaseDC(IntPtrhwnd,IntPtrhdc); [DllImport("gdi32.dll")] publicstaticexternIntPtrCreateDIBSection(IntPtrhdc,refWin32Types.BitmapInfobmi, uintusage,outIntPtrppvBits,IntPtrhSection,uintdwOffset); [DllImport("gdi32.dll")] publicstaticexternIntPtrSelectObject(IntPtrhDc,IntPtrhObject); [DllImport("gdi32.dll")] publicstaticexternboolDeleteObject(IntPtrhObject); [DllImport("gdi32.dll",SetLastError=true)] publicstaticexternboolBitBlt( IntPtrhObject,intnXDest,intnYDest,intnWidth,intnHeight, IntPtrhObjectSource,intnXSrc,intnYSrc,uintdwRop); [DllImport("user32.dll")] publicstaticexternboolPrintWindow(IntPtrhwnd,IntPtrhdcBlt,uintnFlags); } }
2、DibCaptureHelper.cs
usingSystem; namespaceCaptureSharp { internalclassDibCaptureHelper { publicIntPtrBitmapPtr=>_hBitmap; publicWin32Types.BitmapInfoBitmapInfo=>_bitmapInfo; publicWin32Types.RectWindowRect=>_windowRect; publicWin32Types.RectClientRect=>_clientRect; publicintBitmapDataSize=>_bmpDataSize; privateIntPtr_hWnd=IntPtr.Zero; privateIntPtr_hScrDc=IntPtr.Zero; privateIntPtr_hMemDc=IntPtr.Zero; privateIntPtr_hBitmap=IntPtr.Zero; privateIntPtr_hOldBitmap=IntPtr.Zero; privateIntPtr_bitsPtr=IntPtr.Zero; privateWin32Types.BitmapInfo_bitmapInfo; privateWin32Types.Rect_windowRect; privateWin32Types.Rect_clientRect; privateint_bmpDataSize; publicboolInit(stringwindowName) { varhandle=Win32Funcs.FindWindow(null,windowName); if(handle.Equals(IntPtr.Zero)) { returnfalse; } returnInit(handle); } publicboolInit(IntPtrhandle) { _hWnd=handle; //获取窗口大小 if(!Win32Funcs.GetWindowRect(_hWnd,out_windowRect) ||!Win32Funcs.GetClientRect(_hWnd,out_clientRect)) { returnfalse; } _bmpDataSize=_clientRect.Width*_clientRect.Height*3; //位图信息 _bitmapInfo=newWin32Types.BitmapInfo{bmiHeader=newWin32Types.BitmapInfoHeader()}; _bitmapInfo.bmiHeader.Init(); _bitmapInfo.bmiHeader.biWidth=_clientRect.Width; _bitmapInfo.bmiHeader.biHeight=_clientRect.Height; _bitmapInfo.bmiHeader.biPlanes=1; _bitmapInfo.bmiHeader.biBitCount=24; _bitmapInfo.bmiHeader.biSizeImage=(uint)(_clientRect.Width*_clientRect.Height); _bitmapInfo.bmiHeader.biCompression=(uint)Win32Consts.BitmapCompressionMode.BI_RGB; _hScrDc=Win32Funcs.GetWindowDC(_hWnd); _hMemDc=Win32Funcs.CreateCompatibleDC(_hScrDc); _hBitmap=Win32Funcs.CreateDIBSection(_hMemDc,ref_bitmapInfo, (uint)Win32Consts.DibColorMode.DIB_RGB_COLORS, out_bitsPtr,IntPtr.Zero,0); _hOldBitmap=Win32Funcs.SelectObject(_hMemDc,_hBitmap); returntrue; } publicvoidCleanup() { if(_hBitmap.Equals(IntPtr.Zero)) { return; } //删除用过的对象 Win32Funcs.SelectObject(_hMemDc,_hOldBitmap); Win32Funcs.DeleteObject(_hBitmap); Win32Funcs.DeleteDC(_hMemDc); Win32Funcs.ReleaseDC(_hWnd,_hScrDc); _hWnd=IntPtr.Zero; _hScrDc=IntPtr.Zero; _hMemDc=IntPtr.Zero; _hBitmap=IntPtr.Zero; _hOldBitmap=IntPtr.Zero; _bitsPtr=IntPtr.Zero; } publicboolRefreshWindow() { varhWnd=_hWnd; Cleanup(); returnInit(hWnd); } publicboolChangeWindowHandle(stringwindowName) { Cleanup(); returnInit(windowName); } publicboolChangeWindowHandle(IntPtrhandle) { Cleanup(); returnInit(handle); } publicIntPtrCapture() { if(_hBitmap.Equals(IntPtr.Zero)||_hMemDc.Equals(IntPtr.Zero)||_hScrDc.Equals(IntPtr.Zero)) { returnIntPtr.Zero; } varret=Win32Funcs.BitBlt( _hMemDc,0,0,_clientRect.Width,_clientRect.Height, _hScrDc,0,0, (uint)Win32Consts.RasterOperationMode.SRCCOPY); returnret?_bitsPtr:IntPtr.Zero; } publicboolCapture(outIntPtrbitsPtr,outintbufferSize,outWin32Types.Rectrect) { bitsPtr=_bitsPtr; bufferSize=_bmpDataSize; rect=_clientRect; if(_hBitmap.Equals(IntPtr.Zero)||_hMemDc.Equals(IntPtr.Zero)||_hScrDc.Equals(IntPtr.Zero)) { returnfalse; } varret=Win32Funcs.BitBlt( _hMemDc,0,0,_clientRect.Width,_clientRect.Height, _hScrDc,0,0, (uint)Win32Consts.RasterOperationMode.SRCCOPY); returnret; } } }
以上就是C#使用BitBlt进行窗口抓图的示例的详细内容,更多关于c#窗口抓图的资料请关注毛票票其它相关文章!