.net 在Microsoft团队上共享主窗口时,透明子窗口呈现为黑色

.net 在Microsoft团队上共享主窗口时,透明子窗口呈现为黑色,.net,wpf,windows,pinvoke,microsoft-teams,.net,Wpf,Windows,Pinvoke,Microsoft Teams,问题描述 我有一个WPF子窗口和一个WPF主窗口。主窗口被设置为子窗口的所有者。子窗口具有透明背景,位于主窗口顶部 当我共享整个屏幕时,会议来宾可以看到主窗口和子窗口以及两个窗口的所有内容。 当我只共享主窗口时,会议来宾会看到子窗口的背景为黑色而不是透明 在我自己的屏幕上,两个窗口都呈现得很好——不管它们是如何共享的 该问题可在Microsoft团队中重现,但在Zoom上无法重现 这就是应用程序在我的计算机上呈现的方式—无论我如何共享屏幕: 这就是当我分享我的整个屏幕时,会议参与者看到应用程序

问题描述
我有一个WPF子窗口和一个WPF主窗口。主窗口被设置为子窗口的所有者。子窗口具有透明背景,位于主窗口顶部

当我共享整个屏幕时,会议来宾可以看到主窗口和子窗口以及两个窗口的所有内容。 当我只共享主窗口时,会议来宾会看到子窗口的背景为黑色而不是透明

在我自己的屏幕上,两个窗口都呈现得很好——不管它们是如何共享的

该问题可在Microsoft团队中重现,但在Zoom上无法重现

这就是应用程序在我的计算机上呈现的方式—无论我如何共享屏幕:

这就是当我分享我的整个屏幕时,会议参与者看到应用程序的方式(屏幕截图仅说明应用程序,但显然整个屏幕对参与者可见):

这就是当我只共享主窗口时,会议参与者对应用程序的看法(黑色部分是子窗口的背景,应该是透明的而不是黑色):

如果我将子窗口的背景更改为例如
画笔.绿色
,而不是
画笔.透明
,它将正确呈现参与者看到的:

因此,在传输透明子窗口的捕获时,显然存在一个问题

使用的技术
C#,WPF,.NET Framework 4.8(如果相同的问题出现在其他目标框架上,例如.NET Core,则尚未测试,但无法更改目标框架)

复制问题的最小示例代码
MainWindow.xaml

<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="600"
        Background="LightBlue"
        WindowStartupLocation="CenterScreen">
    <Grid Height="500" Width="500" Background="CornflowerBlue" />
</Window>
约束

  • 在实际应用程序中,主窗口是第三方本机Win32应用程序。但是,子窗口与主窗口位于同一进程空间中
  • 子窗口必须以透明背景显示,并且能够包含完全不透明的内容
  • 我必须对子窗口使用WPF/.NET。WPF内容可能托管在WinForms
    表单中,并带有
    ElementHost
    或原始
    HwndSource
    ,如果这样可以解决任何问题的话
  • 我不在乎我是否必须使用PInvoke、Windows挂钩等,我已经广泛使用了
  • 在屏幕共享时,不显示子窗口(如参与者所见)是可以接受的
我尝试过但没有成功的事情

  • 我尝试过不让主窗口成为子窗口的所有者,但这会消除所有者关系中的良好行为:例如,子窗口始终位于所有者之上(不使用
    最上面的
    ),子窗口与主窗口一起最小化、最大化、恢复和关闭。此外,共享主窗口时,子窗口根本不显示。作为最后的手段,这是可以接受的,因为我不希望子窗口出现在屏幕共享会话上,也不希望它显示为黑色

  • 我曾尝试使用PInvoke
    SetWindowLong
    手动设置所有者关系(我猜这就是
    window.owner
    所做的)。参考:

  • 我已尝试PInvoke
    SetWindowLong
    并清除
    WS\u弹出窗口
    WS\u重叠
    标志,并设置
    WS\u子项
    ,然后调用
    SetParent
    ,以创建“可视”父/子关系,而不是
    window.owner
    创建的逻辑所有者关系。这在
    SetParent
    的文档中指定:。这实际上解决了问题,但在其他场景中会产生视觉故障

  • 我尝试使用
    LWA_COLORKEY
    在子窗口上PInvoke
    SetLayeredWindowAttributes
    ,然后将子窗口的背景设置为洋红色,然后将该颜色代码指定为透明颜色键。这实际上修复了黑色背景,但窗口渲染时没有内容和奇怪的边框。我已经读到,这可能发生,因为WPF是在Direct3D上构建的,
    SetLayeredWindowAttributes
    实际上是用于使用GDI渲染的窗口。根据这篇博客(然而,相当古老,因此可能无法反映当今世界),这也可能是因为
    SetLayeredWindowAttributes
    将窗口置于所谓的“系统重定向内容模式”,这是WPF不支持的

  • 我已尝试PInvoke
    SetWindowDisplayAffinity
    将子窗口显示affinity设置为
    WDA\u监视器
    WDA\u EXCLUDEFROMCAPTURE
    。对于我来说,排除子窗口捕获可能是一个可行的选择,但是,Microsoft团队似乎使用忽略此设置的方法来捕获窗口

  • 我试图通过设置
    RenderOptions.ProcessRenderMode=RenderMode.SoftwareOnly
    来禁用硬件加速

  • 当从具有不同硬件的不同机器共享时,该问题是可复制的


坦率地说,对于如何解决这个问题,我有点不知所措。可能主要是因为我不明白为什么这个问题首先会发生。我在互联网上搜索了一下,发现没有人有类似的问题。我希望有人能透露一些信息-如果没有解决方案,那么至少可以说明问题发生的原因。

您是否尝试过更新图形驱动程序或更改硬件加速设置?也许这些建议中的一些会有所帮助,尽管所提到的问题并不完全相同,但这并不是你的错。一个进程可以有多个窗口,每个窗口
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MyApp
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            ContentRendered += delegate { CreateChildWindow(); };
        }

        private void CreateChildWindow()
        {
            var childWindow = new Window
            {
                WindowStyle = WindowStyle.None,
                AllowsTransparency = true,
                Background = Brushes.Transparent,
                WindowStartupLocation = WindowStartupLocation.CenterScreen,
                Height = 400,
                Width = 400,
                ShowInTaskbar = false,
                Content = new Grid {Background = Brushes.Red, Height = 100, Width = 100},
                Owner = this
            };

            childWindow.Show();
        }
    }
}