Problem description
I have a WPF child window and a WPF main window. The main window is set as the owner of the child window. The child window has a transparent background and is positioned on top of the main window.
When I share my entire screen, meeting guests can see the main window and child window and all content of both windows just fine. When I share only the main window, meeting guests see the background of the child window as black instead of transparent.
On my own screen both windows render just fine - regardless of how they are shared.
The issue is reproducable on Microsoft Teams - but not on Zoom.
This is how the application renders on my computer - regardless of how I share my screen:

This is how meeting participants see the application when I share my entire screen (screenshot only illustrating application, but obviously the entire screen is visible to participants):

This is how meeting participants see the application when I share only the main window (the black part is the background of the child window and it should really appear transparent and NOT black):

If I change the background of the child window to e.g. Brushes.Green instead of Brushes.Transparent, it renders correctly as seen by participants:

So clearly there is an issue when transmitting the capture of a transparent child window.
Technologies used
C#, WPF, .NET Framework 4.8 (haven't tested if the same issue appears on other target frameworks, e.g. .NET Core, but changing the target framework is not an option).
Minimal sample code that reproduces the issue
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();
}
}
}
Constraints
- In the real application, the main window is a 3rd party native Win32 application. The child window, however, lives in the same process space as the main window.
- The child window must appear with a transparent background and be able to have fully opaque content.
- I must use WPF/.NET for the child window. The WPF contents could potentially be hosted in a WinForms
Formwith anElementHostor a rawHwndSourceif that solves anything. - I don't care if I have to use PInvoke, Windows hooks, etc. I use that extensively already.
- It could be acceptable to have the child window not appearing (as seen by participants) when screen sharing.
Things I have tried to no avail
I have tried not making the main window the owner of the child window but that removes the nice behavior that you get with an owner relationship: e.g. child window is always on top of owner (without using
TopMost), the child window minimizes, maximizes, restores and closes together with the main window. Also the child window doesn't appear at all when sharing the main window. This could be acceptable as a last resort, as I would rather not have the child window appear on the screen sharing session, than it appearing black.I have tried to PInvoke
SetWindowLongusingGWL_HWNDPARENTto set the owner relationship manually (I guess that is whatwindow.Ownerdoes). Reference: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlonga#remarksI have tried to PInvoke
SetWindowLongand clear theWS_POPUPandWS_OVERLAPPEDflags and setting theWS_CHILD, then followed by a call toSetParentin order to create a 'visual' parent/child relationship instead of the logical owner relationship thatwindow.Ownercreates. This is specified in the documentation toSetParent: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setparent#remarks . This actually solves the issue but instead creates visual glitches in other scenarios.I have tried to PInvoke
SetLayeredWindowAttributeson the child window usingLWA_COLORKEYand then setting the background of the child window to e.g. Magenta and then specify that color code as the transparent color key. This actually fixes the black background but the window renders without content and a weird border. I have read that this could happen because WPF is built on Direct3D andSetLayeredWindowAttributesis actually meant for windows rendered with GDI. According to this blog (however, quite old so may not reflect today's world) it may also be becauseSetLayeredWindowAttributeswill put the window into a so-called 'System-Redirected Content mode', which is not supported by WPF https://dwayneneed.github.io/wpf/2008/09/08/transparent-windows-in-wpf.htmlI have tried to PInvoke
SetWindowDisplayAffinityto set the child window display affinity toWDA_MONITORandWDA_EXCLUDEFROMCAPTURE. Excluding the child window from being captured could be a viable option for my purpose, however, Microsoft Teams seems to capture the window using methods that ignore this setting.I have tried to disable hardware acceleration by setting
RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly.The issue is reproducable when sharing from different machines with different hardware.
To be frank, I'm a bit at a loss as to how to solve this. Probably primarily because I cannot understand why the issue is occuring in the first place. I have scoured the Internet and found no one with a similar issue. I hope that someone can shed a bit of light - if not on a solution, then at least on why the issue may be occuring.