惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyberwarzone
Cyberwarzone
Help Net Security
Help Net Security
L
LINUX DO - 最新话题
Security Archives - TechRepublic
Security Archives - TechRepublic
A
About on SuperTechFans
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Attack and Defense Labs
Attack and Defense Labs
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The GitHub Blog
The GitHub Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Webroot Blog
Webroot Blog
T
Tenable Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Microsoft Security Blog
Microsoft Security Blog
人人都是产品经理
人人都是产品经理
Simon Willison's Weblog
Simon Willison's Weblog
D
Docker
爱范儿
爱范儿
AI
AI
宝玉的分享
宝玉的分享
PCI Perspectives
PCI Perspectives
The Register - Security
The Register - Security
Project Zero
Project Zero
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
S
Securelist
Scott Helme
Scott Helme
B
Blog
Forbes - Security
Forbes - Security
Google DeepMind News
Google DeepMind News
T
The Blog of Author Tim Ferriss
月光博客
月光博客
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
F
Fortinet All Blogs
H
Help Net Security
Last Week in AI
Last Week in AI
N
News and Events Feed by Topic
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
MyScale Blog
MyScale Blog
I
InfoQ
P
Privacy International News Feed
V
V2EX
有赞技术团队
有赞技术团队
G
Google Developers Blog
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
Schneier on Security
T
Tailwind CSS Blog

博客园 - wuty007

C# 范围运算符 C# 调用WGC 实现桌面屏幕的捕获 完善基于WPF开发的标尺控件(含实例代码) C# 依赖注入 Microsoft.Extensions.DependencyInjection 实现 控制反转(IOC) C# 获取Windows系统的设备名称 记录 Windows系统开启hyper-v ,部分端口被保留,导致端口不能使用而报错的问题 记录WPF 在清单列表设置了UIACESS为true,没有签名的报错“从服务器返回了一个参照” WPF 的ListBox 去除默认的Item项的 鼠标hover的背景颜色 WPF 调用 ChangeWindowMessageFilterEx 修改指定窗口 (UIPI) 消息筛选器的用户界面特权隔离 记录一下 WPF进程 SendMessage 发送窗口消息进行进程间通信,存在进程权限无法接受消息的问题 记录 使用PsExec启动System权限的WPF 程序 记录 命令行的 findstr 的使用 排查Windows 下的内存使用率过高,但是任务管理器看不到进程 Everything 支持 多实例 运行 指定应用 在 控制面板或者 设置的安装应用 置灰或隐藏卸载按钮 WPF 通过RawInput 获取 系统全局触摸事件 C# 定时任务 Quartz.NET 的使用 记录一下Windows系统下的命令行参数的字符个数限制 WPF 实现支持动态调整高度的文本显示控件
WPF 调用 Win32的SetWindowDisplayAffinity 函数 实现捕获屏幕时,过滤指定的窗口
wuty007 · 2025-12-04 · via 博客园 - wuty007

一、背景

最近在开发互动传屏的需求,使用了WGC捕获桌面屏幕的方式,实现屏幕的捕获和录制。在验收阶段,产品的验收的建议是:需要过滤自身的窗口,跟腾讯会议一样,进行互动传屏。

1、腾讯会议共享屏幕的窗口如下图

腾讯会议的发起者的主窗口在其他设备端,是看不到的,直接透明下去。还有会议的录屏的全屏四个边角的绿框也是看不到的

image

2、我们自己开发的屏幕捕获的效果如下图:

窗口在捕获之后,都是层层传递下去,类似直播的效果一样。

image

 二、介绍SetWindowDisplayAffinity 函数 

其实微软的Win32 API 有函数 实现:SetWindowDisplayAffinity 函数 (winuser.h) - Win32 apps | Microsoft Learn,支持 Windows 7 中新增的窗口内容保护功能。

此功能使应用程序能够保护自己的屏幕窗口内容,使其免受通过一组特定的公共操作系统功能和 API 捕获或复制

SetWindowDisplayAffinity 函数 (winuser.h)

指定窗口内容的显示位置。

语法

BOOL SetWindowDisplayAffinity(
  [in] HWND  hWnd,
  [in] DWORD dwAffinity
);

参数

[in] hWnd

类型:HWND

顶级窗口的句柄。 窗口必须属于当前进程。

[in] dwAffinity

类型:DWORD

指定窗口内容的显示位置的显示相关性设置。

此参数的取值可为下列值之一:

含义
WDA_NONE
0x00000000
对窗口的显示位置没有限制。
WDA_MONITOR
0x00000001
窗口内容仅显示在监视器上。 在其他任何位置,窗口都会显示,其中不显示任何内容。
WDA_EXCLUDEFROMCAPTURE
0x00000011
窗口仅显示在监视器上。 在其他任何位置,窗口根本不显示。

此相关性的一个用途是用于显示视频录制控件的窗口,以便控件不包括在捕获中。

Windows 10版本 2004 中引入。 请参阅有关以前版本的 Windows 兼容性的备注。

返回值

类型: BOOL

如果函数成功,则返回 TRUE;例如,在非顶级窗口上进行函数调用时,它将返回 FALSE 。 要获得更多的错误信息,请调用 GetLastError。

此函数和 GetWindowDisplayAffinity 旨在支持 Windows 7 中新增的窗口内容保护功能。 此功能使应用程序能够保护自己的屏幕窗口内容,使其免受通过一组特定的公共操作系统功能和 API 捕获或复制。 但是,仅当桌面窗口管理器 (DWM) 组合桌面时,它才有效。

请务必注意,与安全功能或数字版权管理 (DRM) 实现不同,无法保证使用 SetWindowDisplayAffinity 和 GetWindowDisplayAffinity 以及其他必要功能(如 DwmIsCompositionEnabled)将严格保护窗口内容,例如有人拍摄屏幕照片。

从 Windows 10 版本 2004 开始,WDA_EXCLUDEFROMCAPTURE 是受支持的值。 在以前版本的 Windows 上将显示相关性设置为WDA_EXCLUDEFROMCAPTURE的行为就像应用了WDA_MONITOR一样。

要求

要求
最低受支持的客户端 Windows 7 [仅限桌面应用]
最低受支持的服务器 Windows Server 2008 R2 [仅限桌面应用]
目标平台 Windows
标头 winuser.h (包括 Windows.h)
Library User32.lib
DLL User32.dll
API 集 在 Windows 8.1) 中引入的 ext-ms-win-ntuser-window-l1-1-1 (

另请参阅

SetWindowDisplayAffinity, Windows

三、使用SetWindowDisplayAffinity 函数 

1、定义 SetWindowDisplayAffinity 函数 

 private const uint WDA_NONE = 0x00000000;
 private const uint WDA_MONITOR = 0x00000001;
 private const uint WDA_EXCLUDEFROMCAPTURE = 0x00000011;

 [DllImport("user32.dll")]
 public static extern uint SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);

2、在MainWindows 的 SourceInitialized 事件调用(只要能获取得到窗口的句柄即可),由于我的需求是在捕获屏幕的时候,不需要显示,所以我这边调用的是:WDA_EXCLUDEFROMCAPTURE(0x00000011)

 public MainWindow()
 {
     InitializeComponent();

     SourceInitialized += MainWindow_SourceInitialized;
 }

 private IntPtr currentWindowHandle;

 private void MainWindow_SourceInitialized(object sender, EventArgs e)
 {
     currentWindowHandle = new WindowInteropHelper(this).Handle;
     var result =  SetWindowDisplayAffinity(currentWindowHandle, WDA_EXCLUDEFROMCAPTURE);
 }

 private const uint WDA_NONE = 0x00000000;
 private const uint WDA_MONITOR = 0x00000001;
 private const uint WDA_EXCLUDEFROMCAPTURE = 0x00000011;

 [DllImport("user32.dll")]
 public static extern uint SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);

3、调用的效果如下:

捕获的窗口已经没有显示主窗口了

image

 参考资料:

1、SetWindowDisplayAffinity 函数 (winuser.h) - Win32 apps | Microsoft Learn