Skip to main content
Hosting legacy Win32 content/window in XAML? Seems impossible, right? NO. The story started when I noticed IDCompositionDevice::CreateSurfaceFromHwnd function in the public docs of DirectComposition. But I realized that we have a problem, this is for DirectComposition while XAML only publicly exposes Windows.UI.Composition objects After some investigations on Windows.UI.Xaml.dll with IDA Pro, I noticed that XAML thankfully creates the Windows.UI.Composition device using InteropCompositor which allows you to cast Windows.UI.Composition objects into DirectComposition objects and vice versa. GREAT!
You can read more about InteropCompositor in this great blogpost by ADeltaX: InteropCompositor (and CoreDispatcher)

So the next problem was that the window has to be a layered (WS_EX_LAYERED) child (WS_CHILD) window for “cloak”ing to work but we can’t set our legacy window as a child window to the ApplicationFrameWindow window because it’s not owned by our process but ApplicationFrameHost.exe. But thankfully (again!) the CoreWindow window is owned by our process so we can use it to be the parent of our legacy child window. GREAT! So let’s create our child window…
Notes:
  • WS_EX_COMPOSITED extended style is required for the window to render
  • ICoreWindowInterop is defined in the public Windows SDK, you can copy the definition from there
  • CreateWindowEx, InitCommonControlsEx, ShowWindow, SendMessage, … are native Windows functions, you can DllImport them from the corresponding dlls for them, I got most of definitions from pinvoke.net, same with structs used in the code
Now, let’s create our Visual…
Now, let’s handle input (the code sucks, I don’t recommend using it)
We can use CoreIndependentInputSource or Windows::UI::Internal::Input::IInputSite to receive input on the Visual itself so we don’t need to use CoreWindow pointer events or transforming the Point, but let’s leave that for another blogpost…
And here’s the result!
Last modified on February 20, 2026