C# 抓图服务的实现
C#抓图服务首先抽象出抓图接口,然后对接口做基于公共操作的抽象类封装,之后针对不同的抓图方式做差异化处理,最后根据接口实现抓图服务。
注意:Win32封装实现参考C#使用BitBlt进行窗口抓图。
Github示例工程:SimpleWindowCapture。
1、抓图接口
usingSystem;
usingWin32Proxy;
namespaceCaptureProxy
{
internalinterfaceICaptureHelper
{
boolInit(stringwindowName);
boolInit(IntPtrhandle);
voidCleanup();
boolRefreshWindow();
boolChangeWindowHandle(stringwindowName);
boolChangeWindowHandle(IntPtrhandle);
IntPtrCapture();
boolCapture(outIntPtrbitsPtr,outintbufferSize,outWin32Types.Rectrect);
Win32Types.RectWindowRect{get;}
Win32Types.RectClientRect{get;}
intBitmapDataSize{get;}
IntPtrBitmapPtr{get;}
Win32Types.BitmapInfoBitmapInfo{get;}
}
}
usingSystem.ComponentModel;
namespaceCaptureProxy
{
publicenumCaptureType
{
[Description("使用CreateDIBSection抓图,速度快,但是无法抓取D3D等渲染的窗口")]
CreateDibSection=0,
[Description("使用PrintWindow抓图,速度慢(16ms左右),但是可以抓取D3D等渲染的窗口")]
PrintWindow
}
}
2、抓图抽象类
usingSystem;
usingWin32Proxy;
namespaceCaptureProxy
{
internalabstractclassAbsCaptureHelper:ICaptureHelper
{
publicWin32Types.RectWindowRect=>_windowRect;
publicWin32Types.RectClientRect=>WinClientRect;
publicintBitmapDataSize=>_bmpDataSize;
publicIntPtrBitmapPtr=>HBitmap;
publicWin32Types.BitmapInfoBitmapInfo{get;}=newWin32Types.BitmapInfo();
protectedIntPtrHWnd=IntPtr.Zero;
protectedIntPtrHScrDc=IntPtr.Zero;
protectedIntPtrHMemDc=IntPtr.Zero;
protectedIntPtrHBitmap=IntPtr.Zero;
protectedIntPtrHOldBitmap=IntPtr.Zero;
privateWin32Types.Rect_windowRect;
protectedWin32Types.RectWinClientRect;
privateint_bmpDataSize;
protectedabstractboolCommonInit();
protectedabstractIntPtrDoCapture();
protectedabstractboolDoCapture(outIntPtrbitsPtr);
publicboolInit(stringwindowName)
{
varhandle=Win32Funcs.FindWindowWrapper(null,windowName);
if(handle.Equals(IntPtr.Zero))
{
returnfalse;
}
returnInit(handle);
}
publicboolInit(IntPtrhandle)
{
HWnd=handle;
//获取窗口大小
if(!Win32Funcs.GetWindowRectWrapper(HWnd,out_windowRect)
||!Win32Funcs.GetClientRectWrapper(HWnd,outWinClientRect))
{
returnfalse;
}
_bmpDataSize=WinClientRect.Width*WinClientRect.Height*3;
returnCommonInit();
}
publicvoidCleanup()
{
if(HBitmap.Equals(IntPtr.Zero))
{
return;
}
//删除用过的对象
Win32Funcs.SelectObjectWrapper(HMemDc,HOldBitmap);
Win32Funcs.DeleteObjectWrapper(HBitmap);
Win32Funcs.DeleteDcWrapper(HMemDc);
Win32Funcs.ReleaseDcWrapper(HWnd,HScrDc);
HWnd=IntPtr.Zero;
HScrDc=IntPtr.Zero;
HMemDc=IntPtr.Zero;
HBitmap=IntPtr.Zero;
HOldBitmap=IntPtr.Zero;
//_bitsPtr=IntPtr.Zero;
}
publicboolRefreshWindow()
{
returnChangeWindowHandle(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;
}
returnDoCapture();
}
publicboolCapture(outIntPtrbitsPtr,outintbufferSize,outWin32Types.Rectrect)
{
bitsPtr=IntPtr.Zero;
bufferSize=_bmpDataSize;
rect=WinClientRect;
if(HBitmap.Equals(IntPtr.Zero)||HMemDc.Equals(IntPtr.Zero)||HScrDc.Equals(IntPtr.Zero))
{
returnfalse;
}
returnDoCapture(outbitsPtr);
}
}
}
3、抓图类实现
usingSystem;
usingWin32Proxy;
namespaceCaptureProxy
{
internalclassDibCaptureHelper:AbsCaptureHelper
{
privateWin32Types.BitmapInfo_bitmapInfo;
privateIntPtr_bitsPtr=IntPtr.Zero;
protectedoverrideboolCommonInit()
{
//位图信息
_bitmapInfo=newWin32Types.BitmapInfo{bmiHeader=newWin32Types.BitmapInfoHeader()};
_bitmapInfo.bmiHeader.Init();
_bitmapInfo.bmiHeader.biWidth=WinClientRect.Width;
_bitmapInfo.bmiHeader.biHeight=WinClientRect.Height;
_bitmapInfo.bmiHeader.biPlanes=1;
_bitmapInfo.bmiHeader.biBitCount=24;
_bitmapInfo.bmiHeader.biSizeImage=(uint)(WinClientRect.Width*WinClientRect.Height);
_bitmapInfo.bmiHeader.biCompression=(uint)Win32Consts.BitmapCompressionMode.BI_RGB;
HScrDc=Win32Funcs.GetWindowDcWrapper(HWnd);
HMemDc=Win32Funcs.CreateCompatibleDcWrapper(HScrDc);
HBitmap=Win32Funcs.CreateDibSectionWrapper(HMemDc,ref_bitmapInfo,
(uint)Win32Consts.DibColorMode.DIB_RGB_COLORS,
out_bitsPtr,IntPtr.Zero,0);
HOldBitmap=Win32Funcs.SelectObjectWrapper(HMemDc,HBitmap);
returntrue;
}
protectedoverrideIntPtrDoCapture()
{
varret=Win32Funcs.BitBltWrapper(
HMemDc,0,0,WinClientRect.Width,WinClientRect.Height,
HScrDc,0,0,
(uint)Win32Consts.RasterOperationMode.SRCCOPY);
returnret?_bitsPtr:IntPtr.Zero;
}
protectedoverrideboolDoCapture(outIntPtrbitsPtr)
{
bitsPtr=_bitsPtr;
varret=Win32Funcs.BitBltWrapper(
HMemDc,0,0,WinClientRect.Width,WinClientRect.Height,
HScrDc,0,0,
(uint)Win32Consts.RasterOperationMode.SRCCOPY);
returnret;
}
}
}
usingSystem;
usingWin32Proxy;
namespaceCaptureProxy
{
internalclassPrintCaptureHelper:AbsCaptureHelper
{
protectedoverrideboolCommonInit()
{
HScrDc=Win32Funcs.GetWindowDcWrapper(HWnd);
HBitmap=Win32Funcs.CreateCompatibleBitmapWrapper(HScrDc,WinClientRect.Width,WinClientRect.Height);
HMemDc=Win32Funcs.CreateCompatibleDcWrapper(HScrDc);
HOldBitmap=Win32Funcs.SelectObjectWrapper(HMemDc,HBitmap);
returntrue;
}
protectedoverrideIntPtrDoCapture()
{
varret=Win32Funcs.PrintWindowWrapper(HWnd,HMemDc,
(uint)Win32Consts.PrintWindowMode.PW_CLIENTONLY|
(uint)Win32Consts.PrintWindowMode.PW_RENDERFULLCONTENT);
returnret?HBitmap:IntPtr.Zero;
}
protectedoverrideboolDoCapture(outIntPtrbitsPtr)
{
bitsPtr=HBitmap;
varret=Win32Funcs.PrintWindowWrapper(HWnd,HMemDc,
(uint)Win32Consts.PrintWindowMode.PW_CLIENTONLY|
(uint)Win32Consts.PrintWindowMode.PW_RENDERFULLCONTENT);
returnret;
}
}
}
4、抓图服务
usingSystem;
usingSystem.Collections.Generic;
usingWin32Proxy;
namespaceCaptureProxy
{
publicclassCaptureService
{
privatereadonlyDictionary_dicCaptureHelper;
///
///注册抓图服务
///
///抓图服务名称
///窗口名称
///抓图类型
///true成功,false失败
publicboolRegisterCapture(stringname,stringwindowName,CaptureTypetype=CaptureType.CreateDibSection)
{
if(string.IsNullOrEmpty(name)||_dicCaptureHelper.ContainsKey(name))
{
returnfalse;
}
ICaptureHelperhelper;
switch(type)
{
caseCaptureType.CreateDibSection:
helper=newDibCaptureHelper();
break;
caseCaptureType.PrintWindow:
helper=newPrintCaptureHelper();
break;
default:
returnfalse;
}
if(!helper.Init(windowName))
{
returnfalse;
}
_dicCaptureHelper.Add(name,helper);
returntrue;
}
///
///注册抓图服务
///
///抓图服务名称
///窗口句柄
///抓图类型
///true成功,false失败
publicboolRegisterCapture(stringname,IntPtrhandle,CaptureTypetype=CaptureType.CreateDibSection)
{
if(string.IsNullOrEmpty(name)||_dicCaptureHelper.ContainsKey(name))
{
returnfalse;
}
ICaptureHelperhelper;
switch(type)
{
caseCaptureType.CreateDibSection:
helper=newDibCaptureHelper();
break;
caseCaptureType.PrintWindow:
helper=newPrintCaptureHelper();
break;
default:
returnfalse;
}
if(!helper.Init(handle))
{
returnfalse;
}
_dicCaptureHelper.Add(name,helper);
returntrue;
}
///
///获取是否已注册抓图服务
///
///抓图服务名称
///true已注册,false未注册
publicboolIsRegister(stringname)
{
return!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name);
}
///
///注销抓图服务
///
///抓图服务名称
publicvoidUnRegisterCapture(stringname)
{
if(string.IsNullOrEmpty(name)||!_dicCaptureHelper.ContainsKey(name))
{
return;
}
_dicCaptureHelper[name]?.Cleanup();
_dicCaptureHelper.Remove(name);
}
///
///清理所有抓图服务
///
publicvoidCleanup()
{
foreach(varhelperin_dicCaptureHelper)
{
helper.Value?.Cleanup();
}
_dicCaptureHelper.Clear();
}
publicboolRefreshWindow(stringname)
{
varret=!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name);
if(ret)
{
ret=_dicCaptureHelper[name].RefreshWindow();
}
returnret;
}
///
///修改窗口句柄
///
///抓图服务名称
///窗口句柄
publicboolChangeWindowHandle(stringname,IntPtrhandle)
{
return!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name)&&
_dicCaptureHelper[name].ChangeWindowHandle(handle);
}
///
///修改窗口句柄
///
///抓图服务名称
///窗口名称
publicboolChangeWindowHandle(stringname,stringwindowName)
{
return!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name)&&
_dicCaptureHelper[name].ChangeWindowHandle(windowName);
}
///
///获取窗口尺寸
///
///抓图服务名称
///输出的窗口尺寸
///true成功,false失败
publicboolGetWindowRect(stringname,outWin32Types.RectwinRect)
{
varret=!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name);
winRect=ret?_dicCaptureHelper[name].WindowRect:newWin32Types.Rect();
returnret;
}
///
///获取窗口客户区尺寸
///
///抓图服务名称
///输出的窗口客户区尺寸
///true成功,false失败
publicboolGetClientRect(stringname,outWin32Types.RectclientRect)
{
varret=!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name);
clientRect=ret?_dicCaptureHelper[name].ClientRect:newWin32Types.Rect();
returnret;
}
///
///获取抓图数据大小
///
///抓图服务名称
///抓图数据大小
///true成功,false失败
publicboolGetBitmapDataSize(stringname,outintbmpDataSize)
{
varret=!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name);
bmpDataSize=ret?_dicCaptureHelper[name].BitmapDataSize:0;
returnret;
}
publicIntPtrGetBitmapPtr(stringname)
{
if(string.IsNullOrEmpty(name)||!_dicCaptureHelper.ContainsKey(name))
{
returnIntPtr.Zero;
}
return_dicCaptureHelper[name].BitmapPtr;
}
publicWin32Types.BitmapInfoGetBitmapInfo(stringname)
{
if(string.IsNullOrEmpty(name)||!_dicCaptureHelper.ContainsKey(name))
{
returnnewWin32Types.BitmapInfo();
}
return_dicCaptureHelper[name].BitmapInfo;
}
///
///获取抓图
///
///抓图服务名称
///位图指针
///true成功,false失败
publicboolCapture(stringname,outIntPtrbitsPtr)
{
varret=!string.IsNullOrEmpty(name)&&_dicCaptureHelper.ContainsKey(name);
bitsPtr=ret?_dicCaptureHelper[name].Capture():IntPtr.Zero;
returnret&&!bitsPtr.Equals(IntPtr.Zero);
}
///
///获取抓图
///
///抓图服务名称
///位图指针
///位图数据大小
///位图尺寸
///true成功,false失败
publicboolCapture(stringname,outIntPtrbitsPtr,outintbufferSize,outWin32Types.RecttexSize)
{
if(string.IsNullOrEmpty(name)||!_dicCaptureHelper.ContainsKey(name))
{
bitsPtr=IntPtr.Zero;
bufferSize=0;
texSize=newWin32Types.Rect();
returnfalse;
}
return_dicCaptureHelper[name].Capture(outbitsPtr,outbufferSize,outtexSize);
}
#region单例模式
privatestaticCaptureService_instance;
privatestaticreadonlyobjectLockHelper=newobject();
privateCaptureService()
{
_dicCaptureHelper=newDictionary();
}
publicstaticCaptureServiceInstance
{
get
{
if(_instance!=null)
{
return_instance;
}
lock(LockHelper)
{
_instance=_instance??newCaptureService();
}
return_instance;
}
}
#endregion
}
}
5、使用示例
usingSystem;
usingSystem.Threading;
usingCaptureProxy;
usingWin32Proxy;
namespaceSimpleWindowCapture
{
internalsealedclassCaptureHelper
{
publiceventActionCaptureDone=
(captureName,bitmapPtr,bitmapInfo)=>{};
publicintFps{get;set;}=15;
privatedoubleTimerInterval=>1000.0/Fps;
privatestring_captureName;
privateTimer_timer;
publicboolStart(stringcaptureName,IntPtrhandle,CaptureTypetype=CaptureType.CreateDibSection)
{
if(!CaptureService.Instance.RegisterCapture(captureName,handle,type))
{
returnfalse;
}
_captureName=captureName;
//创建守护定时器,马上执行
_timer=newTimer(CaptureFunc,null,
TimeSpan.FromMilliseconds(0),Timeout.InfiniteTimeSpan);
returntrue;
}
publicvoidStop()
{
//移除定时器
_timer?.Dispose();
_timer=null;
CaptureService.Instance.UnRegisterCapture(_captureName);
_captureName=string.Empty;
}
privatevoidCaptureFunc(objectstate)
{
Capture();
//执行下次定时器
_timer?.Change(TimeSpan.FromMilliseconds(TimerInterval),Timeout.InfiniteTimeSpan);
}
privatevoidCapture()
{
IntPtrbitsPtr;
if(!CaptureService.Instance.Capture(_captureName,outbitsPtr))
{
return;
}
varbitmapPtr=CaptureService.Instance.GetBitmapPtr(_captureName);
varbitmapInfo=CaptureService.Instance.GetBitmapInfo(_captureName);
CaptureDone.Invoke(_captureName,bitmapPtr,bitmapInfo);
}
}
}
以上就是C#抓图服务的实现的详细内容,更多关于c#抓图服务的资料请关注毛票票其它相关文章!