Vortice.Windows开发WinUI时如何正确调用SetSwapChain()方法
问题背景
我正尝试按照官方文档描述的方式,通过调用ISwapChainPanelNative.SetSwapChain()初始化SwapChainPanel。
但始终无法将Microsoft.UI.Xaml.Controls.SwapChainPanel类型转换为ISwapChainPanelNative接口,需要找到从WinUI的SwapChainPanel实例获取ISwapChainPanelNative接口的正确实现方法。
已尝试的错误实现如下:
private void AssociateSwapChainPanel( Microsoft.UI.Xaml.Controls.SwapChainPanel swapChainPanel, Vortice.DXGI.IDXGISwapChain3 swapChain) { IUnknown swapChainPanelUnknown = swapChainPanel as IUnknown; // 返回null IInspectable swapChainPanelInspectable = swapChainPanel as IInspectable; // 返回null var swapChainPanelNative = swapChainPanel as Vortice.WinUI.ISwapChainPanelNative; // 无法编译 var swapChainPanelNative = swapChainPanelInspectable.ObjRef.AsInterface<Vortice.WinUI.ISwapChainPanelNative>(); // 抛出异常 var swapChainPanelNative = WinRT.CastExtensions.As<Vortice.WinUI.ISwapChainPanelNative>(swapChainPanel); // 抛出异常 var swapChainPanelNative = (Vortice.WinUI.ISwapChainPanelNative)(object)swapChainPanel; // 抛出异常 }
失败原因
之前的转换方法全部失效的核心原因是:ISwapChainPanelNative是原生COM接口,不属于WinRT运行时定义的接口,C#/WinRT投影层封装的SwapChainPanel托管对象和底层原生COM对象不是直接对应的实例,直接用WinRT内置的类型转换、强转逻辑都无法穿透投影层拿到原生接口。
正确实现方法
方法1:手动查询COM接口(兼容性最好)
通过Marshal类直接从托管对象获取原生IUnknown指针,再手动查询目标接口,代码如下:
using System.Runtime.InteropServices; using Vortice.WinUI; private void AssociateSwapChainPanel( Microsoft.UI.Xaml.Controls.SwapChainPanel swapChainPanel, Vortice.DXGI.IDXGISwapChain3 swapChain) { IntPtr pPanelUnk = Marshal.GetIUnknownForObject(swapChainPanel); try { Guid iidPanelNative = typeof(ISwapChainPanelNative).GUID; Marshal.QueryInterface(pPanelUnk, ref iidPanelNative, out IntPtr pPanelNative); if (pPanelNative == IntPtr.Zero) throw new InvalidOperationException("ISwapChainPanelNative接口查询失败,请检查WinAppSDK与Vortice版本匹配性"); using var panelNative = new ISwapChainPanelNative(pPanelNative); panelNative.SetSwapChain(swapChain); Marshal.Release(pPanelNative); } finally { Marshal.Release(pPanelUnk); } }
方法2:使用Vortice内置扩展方法(代码更简洁)
如果使用的是Vortice.WinUI 1.9及以上版本,库已经封装了对应的转换逻辑,可以直接调用扩展方法:
using Vortice.WinUI; private void AssociateSwapChainPanel( Microsoft.UI.Xaml.Controls.SwapChainPanel swapChainPanel, Vortice.DXGI.IDXGISwapChain3 swapChain) { // 确保SwapChainPanel已经加载到可视化树后再调用 var panelNative = swapChainPanel.AsISwapChainPanelNative(); panelNative.SetSwapChain(swapChain); }
注意事项
- 不要在SwapChainPanel未挂载到可视化树(即未触发Loaded事件)时调用接口查询,未完成初始化的控件实例无法返回原生接口指针
- 确保安装的
Vortice.WinUI包版本和你项目引用的Windows App SDK版本匹配,版本不匹配会导致接口Guid查询失败 - 手动查询COM接口时必须正确释放指针引用,否则会造成内存泄漏
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

