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