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#窗口抓图的资料请关注毛票票其它相关文章!