提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
Microsoft DirectX 图形基础结构 (DXGI) 处理枚举图形适配器、枚举显示模式、选择缓冲区格式、在进程之间共享资源 (,例如,应用程序与桌面窗口管理器 (DWM) ) 之间,以及向窗口或监视器显示呈现的帧。
本文章,主要是介绍C#使用封装好的 DXGI 采集桌面,比起传统的GDI方式,要强大很多。
一、DXGI
1.微软官方资源(都是C++语言)
2.github示例(都是C++语言)
二、基于github示例封装的dll文件
DesktopDuplication.dll下载
C++能力有限,封装的dll功能和性能都不及原github示例,测试截图正常,有能力的同学可以参考官网和github示例DIY。
三、C#调用DesktopDuplication.dll文件
1.使用流程:
将DesktopDuplication.dll下载到输出文件同级目录下,再把GXDI录屏相关代码复制到你的项目中,直接调用screenShotGXDI()方法即可。
2.封装屏幕采集大致流程:
C#通过线程初始化DesktopDuplication.dll进行屏幕采集再通过委托将DXGI采集的屏幕数据传给C#(多屏幕时通过屏幕号辨别数据是哪块屏幕)
3.C#调用示例:
#region GXDI录屏相关代码
public static int dxgifps = 0;
public delegate void CallbackDelegate(IntPtr Image, int width, int height, int RowPitch, int ScreenNumber);//声明委托
//接口定义
[DllImport("DesktopDuplication.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern void SetRegisterFunctionCallback(CallbackDelegate callback);
public CallbackDelegate callbackDelegate = new CallbackDelegate(CallBackFunction);
[DllImport("DesktopDuplication.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern int Initialize();
[DllImport("DesktopDuplication.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
private static extern int SetSwitch(int type);
[DllImport("DesktopDuplication.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
private static extern bool IsSessionLocked();
[HandleProcessCorruptedStateExceptions]
public static void CallBackFunction(IntPtr Image, int width, int height, int RowPitch, int ScreenNumber)
{
#if DEBUG
//DataView.PublicHandle.log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, ScreenNumber + "同屏数据");
#endif
#if false
//if (Image == IntPtr.Zero && width == 0 && height == 0)
//{
// SetSwitch(0);
// Thread.Sleep(10);
// Task task = new Task(() =>
// {
// Initialize();
// });
// task.Start();
// return;
//}
#else
if (Image != IntPtr.Zero || width != 0 || height != 0)
{
GXGIMonitorTime = 5;//使用五秒检测是否需要重新初始化GXDI,回调判断可能出现睡眠循环调用
}
#endif
try
{
Bitmap bitmap = new Bitmap(width, height, RowPitch, PixelFormat.Format32bppRgb, Image);//通过指针得到指定图片
Bitmap thumbnailimage = ThumbnailImage(bitmap, 100, 100);//计算缩量图
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
#region 屏幕数据处理
#endregion
bitmap.UnlockBits(bitmapData);//不加此代码内存一直加
bitmap.Dispose();
}
catch (Exception ex)
{
#if DEBUG
DataView.PublicHandle.log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, "DXGI CallBackFunction Error:" + ex.Message);
#endif
}
Thread.Sleep(20);
}
private static int GXGIMonitorTime = 5;//秒为单位
public ManualResetEvent GXGIMonitorAre = new ManualResetEvent(true);
private void GXDIMonitorThread()
{
while (true)
{
Thread.Sleep(1000);
try
{
GXGIMonitorAre.WaitOne();
GXGIMonitorTime--;
if (GXGIMonitorTime < 0)//规定时间内没有接受到屏幕数据
{
if (!IsSessionLocked())
{
///系统非锁定状态下
SetIfon(0);//结束截屏
SetIfon(1);//开始截屏
GXGIMonitorTime = 5;
}
else
{
keyValuePairs.Clear();
}
}
}
catch (Exception)
{
}
}
}
private void screenShotGXDI()
{
try
{
SetRegisterFunctionCallback(callbackDelegate);
Task task = new Task(() =>
{
Initialize();
});
task.Start();
Thread thread = new Thread(GXDIMonitorThread);
thread.Start();
/单独用一个线程发送队列数据
//queue = new Queue<Buffer>();
//Thread thread1 = new Thread(screenImageThreadHandler);
//thread1.Start();
}
catch (Exception ex)
{
DataView.PublicHandle.log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name, "DXGI Load Error:" + ex.Message);
}
}
Task task;
public void SetIfon(int type)
{
if (type == 0)
{
SetSwitch(type);
if (task != null) task.Dispose();
}
else
{
task = new Task(() =>
{
try
{
Initialize();
}
catch (Exception)
{
}
});
task.Start();
}
}
#endregion
总结
从 Windows 8 开始,微软引入了一套新技术叫 Desktop Duplication API,应用程序可以通过这套 API 请求桌面的图形数据。
优点:由于 Desktop Duplication API 是通过 DirectX Graphics Infrastructure(简称 DXGI)来提供桌面图像的,竞争的是 GPU 流水线资源,所以 CPU 占用率很低,采集性能非常高。
缺点:不支持Windows8前的系统。
参考资料:
【技术分享】Windows桌面端录屏采集实现教程