在 Microsoft Teams 上共享屏幕主窗口时,透明子窗口呈现为黑色

问题描述

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

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

在我自己的屏幕上,两个窗口都呈现得很好 - 无论它们是如何共享的。

该问题可在 Microsoft Teams 上重现 - 但在 Zoom 上无法重现。

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

Transparent window renders fine

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

Child window with transparent window renders fine on my computer

当我只共享主窗口时,与会者看到应用程序的方式是这样的(黑色部分是子窗口的背景,它应该真正显示为透明而不是黑色):

Child window with transparent window renders with black background

如果我将子窗口的背景更改为例如Brushes.Green 而不是 Brushes.Transparent,它在参与者看到的情况下正确呈现:

Child window with green background renders fine

很明显,在传输透明子窗口的捕获时存在问题。

使用的技术
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>

MainWindow.xaml.cs

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();
        }
    }
}

约束

  • 在实际应用中,主窗口是 3rd 方原生 Win32 应用程序。但是,子窗口与主窗口位于同一进程空间中。
  • 子窗口必须以透明背景显示,并且能够包含完全不透明的内容
  • 我必须为子窗口使用 WPF/.NET。如果可以解决任何问题,WPF 内容可能会托管在带有 Form 或原始 ElementHost 的 WinForms HwndSource 中。
  • 我不在乎是否必须使用 PInvoke、Windows 钩子等。我已经广泛使用了。
  • 在屏幕共享时不显示子窗口(如参与者所见)是可以接受的。

我尝试过无济于事的事情

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

  • 我尝试使用 SetwindowLong 手动设置所有者关系来 PInvoke GWL_HWNDPARENT(我猜这就是 window.Owner 所做的)。参考:https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlonga#remarks

  • 我尝试 PInvoke SetwindowLong 并清除 WS_POPUPWS_OVERLAPPED 标志并设置 WS_CHILD,然后调用 {{1} } 以创建“视觉”父/子关系,而不是 SetParent 创建的逻辑所有者关系。这在 window.Owner: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent#remarks 的文档中指定。这实际上解决了问题,但在其他情况下会产生视觉故障。

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

  • 我尝试通过 PInvoke SetwindowdisplayAffinity 将子窗口显示关联设置为 WDA_MONITORWDA_EXCLUDEFROMCAPTURE。为了我的目的,排除子窗口可能是一个可行的选择,但是,Microsoft Teams 似乎使用忽略此设置的方法来捕获窗口。

  • 我尝试通过设置 RenderOptions.ProcessRenderMode = RenderMode.softwareOnly 来禁用硬件加速。

  • 从具有不同硬件的不同机器共享时,该问题可重现。

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

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)