0

I was trying to port a C# code from .NET 4.8 to .NET 5, older version of .NET was using Microsoft.Windows.SDK.Contracts, In .NET 5 Microsoft.Windows.SDK.Contracts is replaced by Target Framework Monikers (TFMs) I used the same code an tried to cast the compositor to ICompositorDesktopInterop but it throws exception :

System.PlatformNotSupportedException: 'Marshalling as IInspectable is not supported in the .NET runtime.'

Here is the code:

private readonly object _dispatcherQueue;
private readonly ICompositorDesktopInterop _compositorDesktopInterop;
private ICompositionTarget compositionTarget;
public Compositor compositor;

private void InitComposition(IntPtr hwnd) 
{
  ICompositorDesktopInterop interop;
  compositor = new Compositor();
  interop = compositor.As < ICompositorDesktopInterop > ();
  interop.CreateDesktopWindowTarget(hwnd, true, out compositionTarget);
  compositionTarget.Root = compositor.CreateSpriteVisual();
}

This is the Com Interface definition that i have used:

[ComImport]
[Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ICompositorDesktopInterop 
{
  void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out ICompositionTarget test);
}

[ComImport]
[Guid("A1BEA8BA-D726-4663-8129-6B5E7927FFA6")]
[InterfaceType(ComInterfaceType.InterfaceIsIInspectable)]
public interface ICompositionTarget 
{
  Windows.UI.Composition.Visual Root 
  {
    get;
    set;
  }
}

Why is it not working with TFM ? Is there something I missed ?

trickymind
  • 557
  • 5
  • 21
  • How do you define ICompositorDesktopInterop in your C# code? – Simon Mourier Aug 15 '21 at 16:55
  • You are casting things (and using `As<>` without checking to see if they're really what you're casting them to. Try looking at them in the debugger and see what the real underlying type is – Joe Aug 16 '21 at 00:40
  • i will update the code once – trickymind Aug 16 '21 at 05:22
  • @SimonMourier i have added the definition for ICompositorDesktopInterop – trickymind Aug 16 '21 at 05:24
  • @Joe i Actually checked the type,the Compositor object can be casted to ICompositorDesktopInterop, and i have been using this code before and it was working fine,until .NET 5 screwed it. – trickymind Aug 16 '21 at 05:26
  • CreateDesktopWindowTarget should be `CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IDesktopWindowTarget result);` – Simon Mourier Aug 16 '21 at 05:57
  • let me change it and try once – trickymind Aug 16 '21 at 05:59
  • I Checked it and another exception occurs: `System.InvalidCastException: 'Unable to cast object of type 'System.__ComObject' to type 'Windows.UI.Composition.Desktop.DesktopWindowTarget'.'` – trickymind Aug 16 '21 at 06:30
  • the IDesktopWindowTarget from abi was not having Root – trickymind Aug 16 '21 at 06:30
  • could you share any c# sample, i think some of these functionalities are not available in TFM – trickymind Aug 16 '21 at 06:31
  • I have used IDesktopWindowTarget in c++ winRT versions, but in C# this interface is not shown, i tried to get guid from header file but it only shows one line `typedef interface IDesktopWindowTarget IDesktopWindowTarget;` – trickymind Aug 16 '21 at 06:42
  • I belive the problem is with `interop = (ICompositorDesktopInterop)iunknown;` – trickymind Aug 16 '21 at 06:53
  • please check the new updated code i have added – trickymind Aug 16 '21 at 07:14
  • Unfortunately, I had to redefine some parts in C# (IDesktopWindowTarget, ICompositionTarget https://pastebin.com/raw/NKHnFh7L), as, like you say, they completely screwed up COM/WinRT support in .NET 5. Because it's cross platform, it's only half-baked for the Windows platform..., IInspectable is not really supported by C#/WinRT. https://github.com/microsoft/CsWinRT/issues/799, etc – Simon Mourier Aug 16 '21 at 07:39
  • they always screwup some things wile fixing others – trickymind Aug 16 '21 at 08:28
  • @SimonMourier can you have a look at this, it's some sort of InteropCompositor, https://blog.adeltax.com/interopcompositor-and-coredispatcher/ , will it be possible to use in c# to create a DesktopWindowTarget – trickymind Aug 25 '21 at 05:54
  • yes, the application that I was referring to is now public (still a work in progress): https://github.com/aelyo-softworks/Wice it's 100% C# it's a bit tricky to make it work for .NET Fx and .NET 5 but it's possible. – Simon Mourier Aug 25 '21 at 06:03
  • Thankyou so much i was able to create ICompositorInterop and render a visual – trickymind Aug 25 '21 at 11:45
  • I Will post an answer and close the Question – trickymind Aug 25 '21 at 11:50

1 Answers1

1

The issue with TFM can be solved by using DirectN or by using InteropCompositor

For InteropCompositor:

Set the TargetFramework in the project file

<TargetFramework>net5.0-windows10.0.19041.0</TargetFramework>

and in your code use

Compositor compositor = new Compositor();
ICompositorDesktopInterop interop = compositor.TryAs<ICompositorDesktopInterop>();
interop.CreateDesktopWindowTarget(hwnd, true, out var target).ThrowOnError();
ICompositionTarget compositionTarget = (ICompositionTarget)target;

Note: Don't forget to create DispatcherQueueController on MainWindow Constructor.

All Credits to : Simon Mourier

trickymind
  • 557
  • 5
  • 21