先列个标题,争取这2天写完。。。

标题写错了居然,

我们一般要实现某个功能,首先希望能找到对应的DEMO,比如我们做屏幕共享,在WIN10下,首先想到的就是DXGI技术,帧率和效率是非常不错的,这里不讲性能,讲下怎么扩展某些功能:

  1. 鼠标功能:
  2. 数据获取
  3. 多显示器需求(多屏,副显,扩展屏说法很多)

先说第一个:

本人下载的DEMO不含鼠标功能,好的,我们加上,直接上代码就是这么简单粗暴:

     D3D11_MAPPED_SUBRESOURCE mapdesc;HRESULT hRes = m_hContext->Map((ID3D11Texture2D *)hNewDesktopImage, m_Subresource, D3D11_MAP_READ_WRITE, 0, &mapdesc);if (FAILED(hRes)){return m_pBuf;}if (m_bHaveCursor)//画鼠标hRes = DrawCursor2(mapdesc, frameDescriptor, FrameInfo);m_hContext->Unmap(hAcquiredDesktopImage, m_Subresource);

上面这段代码可以控制是否画鼠标,下面是DrawCursor2的实现函数:


HRESULT VideoDXGICaptor::DrawCursor2(D3D11_MAPPED_SUBRESOURCE mapdesc, D3D11_TEXTURE2D_DESC desc, DXGI_OUTDUPL_FRAME_INFO frameInfo)
{HRESULT hRes = S_OK;bool bShowCursor = true;if (mapdesc.pData){CURSORINFO ci;memset(&ci, 0, sizeof(ci));ci.cbSize = sizeof(ci);if (GetCursorInfo(&ci)){memcpy(&m_CursorPos, &ci.ptScreenPos, sizeof(m_CursorPos));if (ci.flags & CURSOR_SHOWING){if (ci.hCursor != m_hCurrentCursor) // re-get cursor data{HICON hIcon = CopyIcon(ci.hCursor);m_hCurrentCursor = ci.hCursor;free(m_CursorData);m_CursorData = NULL;if (hIcon){ICONINFO ii;if (GetIconInfo(hIcon, &ii)){xHotspot = int(ii.xHotspot);yHotspot = int(ii.yHotspot);m_CursorData = GetCursorData(hIcon, ii, m_CursorWidth, m_CursorHeight, m_CursorPitch);DeleteObject(ii.hbmColor);DeleteObject(ii.hbmMask);}DestroyIcon(hIcon);}}}else{bShowCursor = false;}}if (m_CursorData && bShowCursor){// Not supporting mono and masked pointers at the moment//printf("Drawing pointer at %d %d\n", data->PointerPosition.Position.x, data->PointerPosition.Position.y);const int ptrx = m_CursorPos.x - xHotspot;const int ptry = m_CursorPos.y - yHotspot;uint8_t* ptr = m_CursorData;uint8_t* dst;// ### Should really do the blending on the GPU (Using DirectX) rather than using SSE2 on the CPUconst int ptrw = min(m_CursorWidth, desc.Width - ptrx);for (unsigned int y = 0; y < m_CursorHeight; ++y){if (y + ptry >= desc.Height)break;dst = static_cast<uint8_t*>(mapdesc.pData) + (((y + ptry) * mapdesc.RowPitch) + (ptrx * 4));//memcpy(dst, ptr, data->PointerShape.Width * 4);ARGBBlendRow_SSE2(ptr, dst, dst, ptrw);ptr += m_CursorPitch;}}}return hRes;
}

完成!收工!完美!

第二个问题:数据的获取,我们要从GPU获取数据到CPU内存:

原DEMO的例子是直接将数据大小默认为宽X高X4,这样对于大多数分辨率可能没问题,但是对于一些特殊分辨率比如1366X768,这样是有问题的,得到的数据是错位的。这牵涉到数据对齐问题,一定要注意。

原始:memcpy((BYTE*)m_pBuf, mappedRect.pBits, m_dxgiOutDesc.DesktopCoordinates.right * m_dxgiOutDesc.DesktopCoordinates.bottom * 4);

修改为:

int nImagePitch = m_iWidth * 4;

for (int i = 0; i < m_iHeight; i++)
        {
            memcpy(m_pBuf + i * nImagePitch, mappedRect.pBits + i * mapdesc.RowPitch, mapdesc.RowPitch);
        }

OK!最后一个问题,多显示器需求,共享主屏幕都可以的,但是也有接副显的需求啊,这方面的资料比较难找。遇到问题我一般会先思考,能自己解决最好,比如第二个问题,因为接触类似问题多了,闭着眼睛也知道什么原因。第一个问题原来做GDI的时候也遇到过,所以稍微查下资料也可以解决。第3个比较难找,自己也不是很熟悉,但是问题始终还是要解决的,具体解决过程就不说了,反正现在知道了,呵呵。

先贴代码:

//定义一个数据结构,这里面是每个DXGI的输出和对应的适配器(显示器),没理解错的话
struct DxgiData
{IDXGIAdapter* pAdapter;IDXGIOutput *pOutput;
};std::vector<DxgiData>   m_vOutputs;int Enum(){IDXGIFactory1* pFactory1;HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory1));if (FAILED(hr)){return 0;}for (UINT i = 0;; i++){IDXGIAdapter1* pAdapter1 = nullptr;hr = pFactory1->EnumAdapters1(i, &pAdapter1);if (hr == DXGI_ERROR_NOT_FOUND){// no more adaptersbreak;}if (FAILED(hr)){return 0;}DXGI_ADAPTER_DESC1 desc;hr = pAdapter1->GetDesc1(&desc);if (FAILED(hr)){return 0;}desc.Description;for (UINT j = 0;; j++){IDXGIOutput *pOutput = nullptr;HRESULT hr = pAdapter1->EnumOutputs(j, &pOutput);if (hr == DXGI_ERROR_NOT_FOUND){// no more outputsbreak;}if (FAILED(hr)){return 0;}DXGI_OUTPUT_DESC desc;hr = pOutput->GetDesc(&desc);if (FAILED(hr)){return 0;}desc.DeviceName;desc.DesktopCoordinates.left;desc.DesktopCoordinates.top;int width=desc.DesktopCoordinates.right - desc.DesktopCoordinates.left;int height=desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top;DxgiData data;data.pAdapter = pAdapter1;data.pOutput = pOutput;m_vOutputs.push_back(data);}}return m_vOutputs.size();}

上面是枚举显示器适配器信息:

下面贴初始化调用代码:

 HRESULT hr = S_OK;if (m_bInit){return FALSE;}int nCount=Enum();if (nCount <= 0)return FALSE;m_iWidth = m_iHeight = 0;// Driver types supportedD3D_DRIVER_TYPE DriverTypes[] ={D3D_DRIVER_TYPE_HARDWARE,D3D_DRIVER_TYPE_WARP,D3D_DRIVER_TYPE_REFERENCE,};UINT NumDriverTypes = ARRAYSIZE(DriverTypes);// Feature levels supportedD3D_FEATURE_LEVEL FeatureLevels[] ={D3D_FEATURE_LEVEL_11_0,D3D_FEATURE_LEVEL_10_1,D3D_FEATURE_LEVEL_10_0,D3D_FEATURE_LEVEL_9_1};//// Get output//INT nOutput = 0;DxgiData data;IDXGIAdapter *pAdapter = NULL;IDXGIOutput *hDxgiOutput = NULL;int nSize = m_vOutputs.size();if (m_nDisPlay<0||m_nDisPlay >= nSize)m_nDisPlay = 0;data = m_vOutputs.at(m_nDisPlay);hDxgiOutput = data.pOutput;pAdapter = data.pAdapter;hDxgiOutput->GetDesc(&m_dxgiOutDesc);UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);for (int i = 0; i < NumFeatureLevels; i++){D3D_FEATURE_LEVEL FeatureLevel = FeatureLevels[i];hr = D3D11CreateDevice(pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, 0, 0, D3D11_SDK_VERSION, &m_hDevice, &FeatureLevel, &m_hContext);if (SUCCEEDED(hr)){break;}}//// Get DXGI device//IDXGIDevice *hDxgiDevice = NULL;hr = m_hDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&hDxgiDevice));if (FAILED(hr)){return FALSE;}//// Get DXGI adapter//IDXGIAdapter *hDxgiAdapter = NULL;hr = hDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&hDxgiAdapter));RESET_OBJECT(hDxgiDevice);if (FAILED(hr)){return FALSE;}IDXGIOutput1 *hDxgiOutput1 = NULL;hr = hDxgiOutput->QueryInterface(__uuidof(hDxgiOutput1), reinterpret_cast<void**>(&hDxgiOutput1));RESET_OBJECT(hDxgiOutput);if (FAILED(hr)){return FALSE;}//// Create desktop duplication//hr = hDxgiOutput1->DuplicateOutput(m_hDevice, &m_hDeskDupl);RESET_OBJECT(hDxgiOutput1);if (FAILED(hr)){return FALSE;}m_Subresource = D3D11CalcSubresource(0, 0, 0);AttatchToThread();// 初始化成功m_bInit = TRUE;return TRUE;

好了,到此为止,我也无话可说,简直就是完美,没人比我更懂DXGI了(听上去好熟悉,逗逼川普的名言)。。。

m_nDisPlay随意指定,看看效果吧

本人QQ35744025,寻求合作随时骚扰即可

最后附上一个GDI多屏的下载链接:

https://download.csdn.net/download/xjb2006/12570425

这dxgi的抓屏demo(包含捕获数据,实时显示,鼠标,副屏)

https://download.csdn.net/download/xjb2006/16126779

DXGI抓屏优化扩展:鼠标功能+数据获取+多显示器捕获(屏幕共享源码)相关推荐

  1. 如何用DXGI抓屏,并识别视频文件中的数字

    项目内容 DXGI 抓屏,设计定时器,获取数据之后回调函数,多屏 建立数字图片数据库,pytorch 训练模型 回调函数,识别数字框,存取drop位置,copy drop位置内存,存到queue 新建 ...

  2. C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果,滤波,图像截取) 对图片的处理 : 亮度调整 抓屏 翻转 随鼠标画矩形

    C#图像处理(各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果) C#图像处理(各种旋转.改变大小.柔化.锐化.雾化.底片.浮雕.黑白.滤镜效果,滤波,图像截取) 对图片的处理 : 亮 ...

  3. 【风电功率预测】基于matlab帝国殖民竞争算法优化BP神经网络风电功率预测【含Matlab源码 1314期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源: [风电功率预测]基于matlab帝国殖民竞争算法优化BP神经网络风电功率预测[含Matlab源码 1314期] ⛄二.帝国殖民竞争算法简 ...

  4. python 抓取解析接口数据_[干货]用python抓取摩拜单车API数据并做可视化分析(源码)...

    原标题:[干货]用python抓取摩拜单车API数据并做可视化分析(源码) 在APP中能看到很多单车,但走到那里的时候,才发现车并不在那里.有些车不知道藏到了哪里:有些车或许是在高楼的后面,由于有GP ...

  5. 【图像处理】基于matlab GUI多功能图像处理系统【含Matlab源码 1876期】

    ⛄一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[图像处理]基于matlab GUI多功能图像处理系统[含Matlab源码 1876期] 点击上面蓝色字体,直接付费下载,即可. 获取代码 ...

  6. 【Matlab电力负荷预测】粒子群优化支持向量机短期电力负荷预测【含GUI源码 751期】

    一.代码运行视频(哔哩哔哩) [Matlab电力负荷预测]粒子群优化支持向量机短期电力负荷预测[含GUI源码 751期] 二.matlab版本及参考文献 1 matlab版本 2014a 2 参考文献 ...

  7. 分享一款超多功能工具箱组合微信小程序源码_支持流量主,无需服务器和域名!适合小白

    分享一款超多功能工具箱组合微信小程序源码_支持流量主,无需服务器和域名!适合小白操作! 简介: 超多功能工具箱组合微信小程序功能实用性质特别的高,用户还能覆盖的广一些具体功能列表如下: 1.证件照制作 ...

  8. 基于Android Studio实现的功能强大的购物商城APP源码,可做Android Studio毕业设计、大作业

    Android 购物商城app 完整代码下载地址:基于Android Studio实现的功能强大的购物商城APP源码 实现的功能: 注册 登录 修改密码 重置密码(邮箱验证,考核结束将移除授权码) 商 ...

  9. 分享一款超40款多功能工具箱组合微信小程序源码_支持流量主,聚集市面上大部分功能的小程序,无需服务器和域名!源码拿去!

    分享一款超多功能工具箱组合微信小程序源码_支持流量主,无需服务器和域名!适合小白操作! 简介: 超多功能工具箱组合微信小程序功能实用性质特别的高,用户还能覆盖的广一些具体功能列表如下: 1.证件照制作 ...

  10. 2023新版 多功能去水印工具微信小程序源码_带流量主功能(已更新)

    简介: 2023新版 多功能去水印工具微信小程序源码_带流量主功能 自带去水印接口的多功能小程序 支持各大平台短视频去水印 支持保存封面,图集,标题等等 支持本地图片去水印 支持图片拼接 支持九宫格切 ...

最新文章

  1. 五彩进化树与热图更配-ggtree美颜进化树(宏基因组扩增子)
  2. 解决360浏览器兼容模式的页面显示问题
  3. SQL语句统计每天、每月、每年的 数据
  4. QString之arg用法
  5. 基于Bootstrap的网站后台模板Metronic
  6. linux c语言 电子相册,纯C语言开发(电子相册).doc
  7. Python中的分片和索引方法
  8. 人口预测模型及matlab代码
  9. 国外有哪些免费软件可以实现华为的多屏协同功能
  10. 分享个PDF文件签名盖章 DEMO
  11. 股票涨跌和买卖预测计算公式
  12. 应用特征值矩阵对角方法
  13. 阿里云centos7.4安装并部署svn1.10.0版本(配置多仓库,加入开机自启动)
  14. 优化UE4性能 、减少DrawCall——材质中使用自定义基元数据
  15. 怎样在photoshop中把字体加粗并倒影
  16. 机器学习(周志华) 第一章 引言
  17. 吉他C大调和弦高把位图
  18. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 关键字 'user' 附近有语法错误
  19. Windows11、10,安装最新版ENSP和最新版HCL模拟器教程、无脑下一步!带下载链接
  20. stl库的使用——队列queue和优先队列和优先队列小根堆(全家桶哎)

热门文章

  1. Vue进阶-异步动态加载组件
  2. Origin简单绘图
  3. STM32的ADC采集实现的信号抓取,然后通过串口传到上位机中显示
  4. JAVA冒泡排序原理
  5. 关于奈奎斯特图的一些解读
  6. 矩阵卷积运算过程讲解
  7. 解决notepad++ php代码美化
  8. 深入理解JVM - 系统性能优化
  9. 基于51单片机机械臂控制系统
  10. 在线超市系统-PythonGUI Tkinter 图片界面设计案例