屏幕共享是目前线上会议系统的一个基本功能,在屏幕共享的实际应用过程中,我们经常会遇到这样的实际需求:我只想共享PPT内容,不想共享桌面或者微信等其他应用程序。为了满足这个需求,我们实现了只共享单个应用程序的程序共享功能。
本文从基础背景知识,主要技术点和实际应用过程中的扩展点三大块来详细介绍单个应用程序的程序共享功能的实现。
首先来介绍基础知识,分为以下3点:
1. Windows的窗口站windowstation
一个窗口站对象包含了一个剪贴板、一张原子表以及一个或多个桌面(desktop)对象。当用户登录时,系统会自动创建交互的窗口站(winsta0),并将交互窗口站与登录会话相关联。WinSta0 是唯一的一个可以显示用户界面和接收用户输入的窗口站,其他窗口站都是非交互的,也就说它们不能显示用户界面,也不能接收用户输入。
2. Windows桌面desktop
默认情况下,交互窗口站有三个桌面: Default,ScreenSaver,Winlogon。同一时刻,每交互窗口站只有一个活动的桌面(用来显示用户界面和接收用户输入)。用户会话期间,当用户按下CTRL+ALT+DEL或者用户帐号控制(UAC)对话框打开,系统切换到winlogon桌面。我们应用软件运行在Default桌面,通常情况下我们访问不到另外两个桌面,这也就是当用户切换到屏保桌面时,我们暂停了共享的原因。
3. 桌面窗口管理器
桌面窗口管理器最是以DWM技术为分界点的,最初在没有DWM时,我们应用程序是一个窗口一个窗口渲染到显示器的,结构如下图。
那么引入DWM后,我们应用程序界面是先合成到DWM,再由DWM统一渲染到显示器。
这样的架构有什么好处呢?
(1)减少重绘,当窗户被另一个窗户阻挡时,被遮挡的窗户不需要重新绘制。
(2)由于DWM负责合成屏幕,因此可以渲染窗口的半透明和模糊的区域。
(3)DWM可以以各种有趣的方式使用离屏表面。例如Flip 3D,缩略图和动画过渡。
了解完基础知识,我们再来看具体用到的技术点。
1. Windows下抓屏技术
我们在上期分享了windows抓屏技术,文章见https://mp.weixin.qq.com/s/5C...
(音视频PaaS平台基于Windows的抓屏技术)
本文再回顾一下几种技术的优缺点。
D3D HOOK: Windows8及以上操作系统,CPU占用较低,使用复杂。支持过滤窗口(win10下最多24个),20帧左右。
MAG API callback : Win7下采用,需要开启桌面合成。使用方便,支持过滤窗口(最大13个)。帧率在20帧左右。
DXGI: 支持windows8及以上操作系统,抓屏效率极高,CPU占用率最低。不支持过滤。
GDI: 兼容性最好,CPU占用率高,效率低,采集帧率在20帧左右。
我们程序共享是基于上述的技术抓取整个屏幕的内容,再根据应用程序在桌面的相对位置裁剪出需要的内容。下面来看看我们采集一帧数据的流程。
2. 程序共享的数据采集流程
从整个流程图上我们可以看到首先要计算共享的应用程序的窗口区域,通过枚举窗口统计过滤和不能过滤的窗口,分别处理过滤和不能过滤的窗口,特别是对不能过滤的窗口需要计算遮挡区域并进行填充,最后拷贝窗口区域的数据。那么接下来介绍计算窗口区域和枚举窗口这两个最重要的部分。
3. 窗口区域计算
程序共享其实是屏幕共享中的一种区域共享,它最关键在于准确计算共享的窗口在屏幕上位置以及它上面遮挡窗口的位置。
我们需要注意以下几点:
(1)所见即所得:很多窗口有透明属性,所以很多时候我们共享的区域大于我们所看到的程序界面的大小。
(2)确定多窗口程序区域:如果共享的程序应用,会有多个窗口时,我们需要计算这些窗口的并集后最大的一个区域,然后再这个区域内把不需要共享的位置进行遮挡。
(3)任务栏:注意任务栏是否对应用程序有遮挡情况。
(4)GetWindowRgn:可以获得更准确的窗口显示区域。
4. 窗口枚举
通过枚举窗口来计算需要过滤和不过滤的窗口,为了能准确枚举到窗口,需要考虑
以下几点因素:
(1) 与采集窗口同进程的窗口不应该被过滤
(2)窗口不可见、最小化或者被遮盖
(3)纯透明窗口
(4)有共同区域
(5)除应用层设置的过滤窗口外,额外支持5个窗口过滤
5. 监听窗口的状态变化-SetWinEventHook
在共享应用程序过程中如果应用程序的窗口发生了变化,我们是如何应对的呢?就是使用SetWinEventHook来监听窗口的状态变化。
我们注意监听如下几个事件:
(1)EVENT_SYSTEM_MINIMIZESTART/EVENT_SYSTEM_MINIMIZEEND
(2)EVENT_SYSTEM_MOVESIZESTART/EVENT_SYSTEM_MOVESIZEEND
(3)EVENT_OBJECT_LOCATIONCHANGE
(4)EVENT_SYSTEM_DESKTOPSWITCH
(5)EVENT_OBJECT_SHOW/EVENT_OBJECT_HIDE
到这里为止介绍完基础知识和主要技术点,整个功能就基本实现了。但是在我们的实际应用中会还会有一些具体问题,需要特殊处理。常见的几种情况:
- 不同的DPI
- 程序在扩展屏上
- Win8metroui
- 虚拟桌面
小结:
以上我们了解了windows平台的桌面、窗口相关知识和DWM的特性和程序共享的数据采集的整个流程,以及整个流程中最关键的计算窗口区域和枚举窗口的部分。当然,我们还可以根据系统的属性,应用程序的窗口特性来实现其他需求,不断提升用户体验。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。