这篇文章主要介绍了C# 抓图服务的实现,帮助大家更好的利用c#处理窗口,进行截图,感兴趣的朋友可以了解下
C#抓图服务首先抽象出抓图接口,然后对接口做基于公共操作的抽象类封装,之后针对不同的抓图方式做差异化处理,最后根据接口实现抓图服务。
注意:Win32封装实现参考C#使用BitBlt进行窗口抓图。
Github示例工程:SimpleWindowCapture。
1、抓图接口
using System;
using Win32Proxy;
namespace CaptureProxy
{
internal interface ICaptureHelper
{
bool Init(string windowName);
bool Init(IntPtr handle);
void Cleanup();
bool RefreshWindow();
bool ChangeWindowHandle(string windowName);
bool ChangeWindowHandle(IntPtr handle);
IntPtr Capture();
bool Capture(out IntPtr bitsPtr, out int bufferSize, out Win32Types.Rect rect);
Win32Types.Rect WindowRect { get; }
Win32Types.Rect ClientRect { get; }
int BitmapDataSize { get; }
IntPtr BitmapPtr { get; }
Win32Types.BitmapInfo BitmapInfo { get; }
}
}
using System.ComponentModel;
namespace CaptureProxy
{
public enum CaptureType
{
[Description("使用CreateDIBSection抓图,速度快,但是无法抓取D3D等渲染的窗口")]
CreateDibSection = 0,
[Description("使用PrintWindow抓图,速度慢(16ms左右),但是可以抓取D3D等渲染的窗口")]
PrintWindow
}
}
2、抓图抽象类
using System;
using Win32Proxy;
namespace CaptureProxy
{
internal abstract class AbsCaptureHelper : ICaptureHelper
{
public Win32Types.Rect WindowRect => _windowRect;
public Win32Types.Rect ClientRect => WinClientRect;
public int BitmapDataSize => _bmpDataSize;
public IntPtr BitmapPtr => HBitmap;
public Win32Types.BitmapInfo BitmapInfo { get; } = new Win32Types.BitmapInfo();
protected IntPtr HWnd = IntPtr.Zero;
protected IntPtr HScrDc = IntPtr.Zero;
protected IntPtr HMemDc = IntPtr.Zero;
protected IntPtr HBitmap = IntPtr.Zero;
protected IntPtr HOldBitmap = IntPtr.Zero;
private Win32Types.Rect _windowRect;
protected Win32Types.Rect WinClientRect;
private int _bmpDataSize;
protected abstract bool CommonInit();
protected abstract IntPtr DoCapture();
protected abstract bool DoCapture(out IntPtr bitsPtr);
public bool Init(string windowName)
{
var handle = Win32Funcs.FindWindowWrapper(null, windowName);
if (handle.Equals(IntPtr.Zero))
{
return false;
}
return Init(handle);
}
public bool Init(IntPtr handle)
{
HWnd = handle;
//获取窗口大小
if (!Win32Funcs.GetWindowRectWrapper(HWnd, out _windowRect)
|| !Win32Funcs.GetClientRectWrapper(HWnd, out WinClientRect))
{
return false;
}
_bmpDataSize = WinClientRect.Width * WinClientRect.Height * 3;
return CommonInit();
}
public void Cleanup()
{
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;
}
public bool RefreshWindow()
{
return ChangeWindowHandle(HWnd);
}
public bool ChangeWindowHandle(string windowName)
{
Cleanup();
return Init(windowName);
}
public bool ChangeWindowHandle(IntPtr handle)
{
Cleanup();
return Init(handle);
}
public IntPtr Capture()
{
if (HBitmap.Equals(IntPtr.Zero) || HMemDc.Equals(IntPtr.Zero) || HScrDc.Equals(IntPtr.Zero))
{
return IntPtr.Zero;
}
return DoCapture();
}
public bool Capture(out IntPtr bitsPtr, out int bufferSize, out Win32Types.Rect rect)
{
bitsPtr = IntPtr.Zero;
bufferSize = _bmpDataSize;
rect = WinClientRect;
if (HBitmap.Equals(IntPtr.Zero) || HMemDc.Equals(IntPtr.Zero) || HScrDc.Equals(IntPtr.Zero))
{
return false;
}
return DoCapture(out bitsPtr);
}
}
}
3、抓图类实现
using System;
using Win32Proxy;
namespace CaptureProxy
{
internal class DibCaptureHelper : AbsCaptureHelper
{
private Win32Types.BitmapInfo _bitmapInfo;
private IntPtr _bitsPtr = IntPtr.Zero;
protected override bool CommonInit()
{
//位图信息
_bitmapInfo = new Win32Types.BitmapInfo {bmiHeader = new Win32Types.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);
return true;
}
protected override IntPtr DoCapture()
{
var ret = Win32Funcs.BitBltWrapper(
HMemDc, 0, 0, WinClientRect.Width, WinClientRect.Height,
HScrDc, 0, 0,
(uint) Win32Consts.RasterOperationMode.SRCCOPY);
return ret ? _bitsPtr : IntPtr.Zero;
}
protected override bool DoCapture(out IntPtr bitsPtr)
{
bitsPtr = _bitsPtr;
var ret = Win32Funcs.BitBltWrapper(
HMemDc, 0, 0, WinClientRect.Width, WinClientRect.Height,
HScrDc, 0, 0,
(uint) Win32Consts.RasterOperationMode.SRCCOPY);
return ret;
}
}
}
using System;
using Win32Proxy;
namespace CaptureProxy
{
internal class PrintCaptureHelper : AbsCaptureHelper
{
protected override bool CommonInit()
{
HScrDc = Win32Funcs.GetWindowDcWrapper(HWnd);
HBitmap = Win32Funcs.CreateCompatibleBitmapWrapper(HScrDc, WinClientRect.Width, WinClientRect.Height);
HMemDc = Win32Funcs.CreateCompatibleDcWrapper(HScrDc);
HOldBitmap = Win32Funcs.SelectObjectWrapper(HMemDc, HBitmap);
return true;
}
protected override IntPtr DoCapture()
{
var ret = Win32Funcs.PrintWindowWrapper(HWnd, HMemDc,
(uint) Win32Consts.PrintWindowMode.PW_CLIENTONLY |
(uint) Win32Consts.PrintWindowMode.PW_RENDERFULLCONTENT);
return ret ? HBitmap : IntPtr.Zero;
}
protected override bool DoCapture(out IntPtr bitsPtr)
{
bitsPtr = HBitmap;
var ret = Win32Funcs.PrintWindowWrapper(HWnd, HMemDc,
(uint) Win32Consts.PrintWindowMode.PW_CLIENTONLY |
(uint) Win32Consts.PrintWindowMode.PW_RENDERFULLCONTENT);
return ret;
}
}
}
4、抓图服务
using System;
using System.Collections.Generic;
using Win32Proxy;
namespace CaptureProxy
{
public class CaptureService
{
private readonly Dictionary<string, ICaptureHelper> _dicCaptureHelper;
/// <summary>
/// 注册抓图服务
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="windowName">窗口名称</param>
/// <param name="type">抓图类型</param>
/// <returns>true成功,false失败</returns>
public bool RegisterCapture(string name, string windowName, CaptureType type = CaptureType.CreateDibSection)
{
if (string.IsNullOrEmpty(name) || _dicCaptureHelper.ContainsKey(name))
{
return false;
}
ICaptureHelper helper;
switch (type)
{
case CaptureType.CreateDibSection:
helper = new DibCaptureHelper();
break;
case CaptureType.PrintWindow:
helper = new PrintCaptureHelper();
break;
default:
return false;
}
if (!helper.Init(windowName))
{
return false;
}
_dicCaptureHelper.Add(name, helper);
return true;
}
/// <summary>
/// 注册抓图服务
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="handle">窗口句柄</param>
/// <param name="type">抓图类型</param>
/// <returns>true成功,false失败</returns>
public bool RegisterCapture(string name, IntPtr handle, CaptureType type = CaptureType.CreateDibSection)
{
if (string.IsNullOrEmpty(name) || _dicCaptureHelper.ContainsKey(name))
{
return false;
}
ICaptureHelper helper;
switch (type)
{
case CaptureType.CreateDibSection:
helper = new DibCaptureHelper();
break;
case CaptureType.PrintWindow:
helper = new PrintCaptureHelper();
break;
default:
return false;
}
if (!helper.Init(handle))
{
return false;
}
_dicCaptureHelper.Add(name, helper);
return true;
}
/// <summary>
/// 获取是否已注册抓图服务
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <returns>true已注册,false未注册</returns>
public bool IsRegister(string name)
{
return !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name);
}
/// <summary>
/// 注销抓图服务
/// </summary>
/// <param name="name">抓图服务名称</param>
public void UnRegisterCapture(string name)
{
if (string.IsNullOrEmpty(name) || !_dicCaptureHelper.ContainsKey(name))
{
return;
}
_dicCaptureHelper[name]?.Cleanup();
_dicCaptureHelper.Remove(name);
}
/// <summary>
/// 清理所有抓图服务
/// </summary>
public void Cleanup()
{
foreach (var helper in _dicCaptureHelper)
{
helper.Value?.Cleanup();
}
_dicCaptureHelper.Clear();
}
public bool RefreshWindow(string name)
{
var ret = !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name);
if (ret)
{
ret = _dicCaptureHelper[name].RefreshWindow();
}
return ret;
}
/// <summary>
/// 修改窗口句柄
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="handle">窗口句柄</param>
public bool ChangeWindowHandle(string name, IntPtr handle)
{
return !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name) &&
_dicCaptureHelper[name].ChangeWindowHandle(handle);
}
/// <summary>
/// 修改窗口句柄
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="windowName">窗口名称</param>
public bool ChangeWindowHandle(string name, string windowName)
{
return !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name) &&
_dicCaptureHelper[name].ChangeWindowHandle(windowName);
}
/// <summary>
/// 获取窗口尺寸
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="winRect">输出的窗口尺寸</param>
/// <returns>true成功,false失败</returns>
public bool GetWindowRect(string name, out Win32Types.Rect winRect)
{
var ret = !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name);
winRect = ret ? _dicCaptureHelper[name].WindowRect : new Win32Types.Rect();
return ret;
}
/// <summary>
/// 获取窗口客户区尺寸
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="clientRect">输出的窗口客户区尺寸</param>
/// <returns>true成功,false失败</returns>
public bool GetClientRect(string name, out Win32Types.Rect clientRect)
{
var ret = !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name);
clientRect = ret ? _dicCaptureHelper[name].ClientRect : new Win32Types.Rect();
return ret;
}
/// <summary>
/// 获取抓图数据大小
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="bmpDataSize">抓图数据大小</param>
/// <returns>true成功,false失败</returns>
public bool GetBitmapDataSize(string name, out int bmpDataSize)
{
var ret = !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name);
bmpDataSize = ret ? _dicCaptureHelper[name].BitmapDataSize : 0;
return ret;
}
public IntPtr GetBitmapPtr(string name)
{
if (string.IsNullOrEmpty(name) || !_dicCaptureHelper.ContainsKey(name))
{
return IntPtr.Zero;
}
return _dicCaptureHelper[name].BitmapPtr;
}
public Win32Types.BitmapInfo GetBitmapInfo(string name)
{
if (string.IsNullOrEmpty(name) || !_dicCaptureHelper.ContainsKey(name))
{
return new Win32Types.BitmapInfo();
}
return _dicCaptureHelper[name].BitmapInfo;
}
/// <summary>
/// 获取抓图
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="bitsPtr">位图指针</param>
/// <returns>true成功,false失败</returns>
public bool Capture(string name, out IntPtr bitsPtr)
{
var ret = !string.IsNullOrEmpty(name) && _dicCaptureHelper.ContainsKey(name);
bitsPtr = ret ? _dicCaptureHelper[name].Capture() : IntPtr.Zero;
return ret && !bitsPtr.Equals(IntPtr.Zero);
}
/// <summary>
/// 获取抓图
/// </summary>
/// <param name="name">抓图服务名称</param>
/// <param name="bitsPtr">位图指针</param>
/// <param name="bufferSize">位图数据大小</param>
/// <param name="texSize">位图尺寸</param>
/// <returns>true成功,false失败</returns>
public bool Capture(string name, out IntPtr bitsPtr, out int bufferSize, out Win32Types.Rect texSize)
{
if (string.IsNullOrEmpty(name) || !_dicCaptureHelper.ContainsKey(name))
{
bitsPtr = IntPtr.Zero;
bufferSize = 0;
texSize = new Win32Types.Rect();
return false;
}
return _dicCaptureHelper[name].Capture(out bitsPtr, out bufferSize, out texSize);
}
#region 单例模式
private static CaptureService _instance;
private static readonly object LockHelper = new object();
private CaptureService()
{
_dicCaptureHelper = new Dictionary<string, ICaptureHelper>();
}
public static CaptureService Instance
{
get
{
if (_instance != null)
{
return _instance;
}
lock (LockHelper)
{
_instance = _instance ?? new CaptureService();
}
return _instance;
}
}
#endregion
}
}
5、使用示例
using System;
using System.Threading;
using CaptureProxy;
using Win32Proxy;
namespace SimpleWindowCapture
{
internal sealed class CaptureHelper
{
public event Action<string, IntPtr, Win32Types.BitmapInfo> CaptureDone =
(captureName, bitmapPtr, bitmapInfo) => { };
public int Fps { get; set; } = 15;
private double TimerInterval => 1000.0 / Fps;
private string _captureName;
private Timer _timer;
public bool Start(string captureName, IntPtr handle, CaptureType type = CaptureType.CreateDibSection)
{
if (!CaptureService.Instance.RegisterCapture(captureName, handle, type))
{
return false;
}
_captureName = captureName;
//创建守护定时器,马上执行
_timer = new Timer(CaptureFunc, null,
TimeSpan.FromMilliseconds(0), Timeout.InfiniteTimeSpan);
return true;
}
public void Stop()
{
//移除定时器
_timer?.Dispose();
_timer = null;
CaptureService.Instance.UnRegisterCapture(_captureName);
_captureName = string.Empty;
}
private void CaptureFunc(object state)
{
Capture();
//执行下次定时器
_timer?.Change(TimeSpan.FromMilliseconds(TimerInterval), Timeout.InfiniteTimeSpan);
}
private void Capture()
{
IntPtr bitsPtr;
if (!CaptureService.Instance.Capture(_captureName, out bitsPtr))
{
return;
}
var bitmapPtr = CaptureService.Instance.GetBitmapPtr(_captureName);
var bitmapInfo = CaptureService.Instance.GetBitmapInfo(_captureName);
CaptureDone.Invoke(_captureName, bitmapPtr, bitmapInfo);
}
}
}
以上就是C# 抓图服务的实现的详细内容,更多关于c# 抓图服务的资料请关注得得之家其它相关文章!
沃梦达教程
本文标题为:C# 抓图服务的实现
基础教程推荐
猜你喜欢
- C#类和结构详解 2023-05-30
- C# 调用WebService的方法 2023-03-09
- ZooKeeper的安装及部署教程 2023-01-22
- 一个读写csv文件的C#类 2022-11-06
- C# windows语音识别与朗读实例 2023-04-27
- unity实现动态排行榜 2023-04-27
- winform把Office转成PDF文件 2023-06-14
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- C# List实现行转列的通用方案 2022-11-02
- C#控制台实现飞行棋小游戏 2023-04-22