UpdateI found a better way to achieve this than the method described in this article, I recommend using that way instead.
Backstory
I was exploring XAML’s Handoff Visual implementation and how it’s created, clipped, wrapped, etc… and found out that the function responsible for creating that visual isCUIElement::EnsureHandOffVisual and when I looked at this function I noticed that it has a bool createLayerVisual parameter:

CUIElement::GetHandOffLayerVisual in the xrefs:

DirectUI::UIElementFactory::GetElementLayerVisual


DirectUI namespace are usually exposed via interfaces, and that was the case here too!
Xrefs showed that it’s exposed through the Windows::UI::Xaml::IUIElementStaticsPrivate interface:

LayerVisual is a visual type that allows you to apply effects and attach shadows to its child visuals.Experimentation
Now that we have the interface and the function signature, the only thing missing is the interface IID, checking theUIElementFactory constructor reveals that the interface is stored at offset 0x50 of the factory class object:

QueryInterface implementation, we can see that it wraps/calls another QueryInterface function but with a pointer to the object at offset 0x10 passed as a this parameter:

QueryInterface function.
If we look at that function we see that IDA mistyped the this parameter and also wasn’t able to detect that it’s the this parameter and showed it as a regular register variable:

void*, this way we can see the offsets more clearly, and here we go, we found our IID!

But what about Windows 10?
This function we just used doesn’t exist in the Windows 10 version of that interface, but looking at howcreateLayerVisual is used inside CUIElement::EnsureHandOffVisual we can see that the LayerVisual and the normal visual paths are very similar, so similar that we can hook IDCompositionDevice2::CreateVisual and redirect it to Windows.UI.Compositor.CreateLayerVisual and it will just work.



As you might have noticed I’m using
CompositionEasingFunctionEx instead of CompositionEasingFunction to create easing functions in the **Windows 10 **code, that’s because the latter only got the support for creating easing functions in Windows 11, so I created a CompositionEasingFunctionEx helper class to allow creating such easing functions under Windows 10, but that’s a story for another article.But what about WinUI 3?
Unfortunately WinUI 3 doesn’t have that interface method at all, neither in latest version or older ones, **BUT **we can use the same trick we used for Windows 10, so lets take a look at theCUIElement::EnsureHandOffVisual function in WinUI 3:


Microsoft.UI.Composition API for both cases, so we need to copy the C++ implementation code we wrote before and make few changes to accommodate that (previous comments are omitted, so check them in the UWP/WUX code if you haven’t)
Update
I accidentally found a better and easier way to achieve this without hooking or any complex stuff at all while working on another thing. So basically I found out thatCompositionVisualSurface completely ignores the Opacity property of the source Visual, so you can just get the Visual of the target UIElement, make its Opacity 0, then create a CompositionSurfaceBrush over a CompositionVisualSurface of the Visual then use that to create a SpriteVisual with CompositionEffectBrush or CompositionMaskBrush (with the source brush set to the CompositionSurfaceBrush) on top of it!
Special thanks to Dongle for proofreading the article