I have a WinUI3 application where I need to host an OpenGL window from a legacy SDK of which I have no control. OpenGL requires the Windows handle and device context to work. Those are properties available in WindowsForms controls but not in WinUI3. As a work around I'm trying to use a WindowsFormsHost to host a WindowsForms UserControl that works fine on a WPF application. But when I try to use the same solution in the WinUI3 app I get the following error:
Error XLS0503 A value of type 'WindowsFormsHost' cannot be added to a collection or dictionary of type 'UIElementCollection'.
I added the necessary assembly references and the namespaces resolve correctly. Here is the XAML file:
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="WinUI3OpenGLApp.OpenGLView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUI3OpenGLApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:int="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:oglc="clr-namespace:OpenGLManagedLib;assembly=OpenGLManagedDll"
mc:Ignorable="d">
<Grid>
<int:WindowsFormsHost x:Name="windowsFormsHost1">
<oglc:OpenGLUserControl x:Name="openGLUserControl1" />
</int:WindowsFormsHost>
</Grid>
</Window>
I know that WinUI3 handles graphics in a completely different way than WPF and WindowsForms, so, that must be root of the problem. Is there a way around this to host an OpenGL window in WinUI3?
After much delving in documentation and googling, I foud the way around the problem. In simple terms I created a CHILD window of the WinUI3 window to overlay it on the desired location. I choosed to fit it inside the a Border control.
Step 1 - Grab a handle of the underlying WindowCore of the hosting window.
Step 2 - Create a CHILD Win32 window with the desired size and position on the host window.
Step 3 - Initialize the OpenGL enviroment using the hchild handle (your own code).
Do this in the host window constructor, otherwise (for reasons unknown to me at this time) if you create the child window outside the constructor it won't showup until the host window is moved or resized.
The final result