WinUI3+C#初始化MPV.Net时无法提供控件句柄的问题
在WinUI3中初始化MPV.Net的解决方案
由于WinUI3的XAML控件没有直接暴露HWND,你可以通过创建Win32宿主窗口承载MPV,再将该窗口嵌入WinUI3页面的方式解决问题,具体步骤如下:
1. 确认项目类型
使用桌面打包的WinUI3应用(而非UWP版),这类项目对Win32互操作支持更完善。
2. 添加Win32窗口相关P/Invoke声明
在项目中添加用于创建和管理宿主窗口的P/Invoke代码:
using System.Runtime.InteropServices; public static class Win32Native { [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr CreateWindowEx( uint dwExStyle, string lpClassName, string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam); [DllImport("user32.dll", SetLastError = true)] public static extern bool DestroyWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] public static extern uint RegisterClassW([In] ref WNDCLASS lpWndClass); public const uint WS_CHILD = 0x40000000; public const uint WS_VISIBLE = 0x10000000; public const int CW_USEDEFAULT = 0x80000000; public struct WNDCLASS { public uint style; public IntPtr lpfnWndProc; public int cbClsExtra; public int cbWndExtra; public IntPtr hInstance; public IntPtr hIcon; public IntPtr hCursor; public IntPtr hbrBackground; public string lpszMenuName; public string lpszClassName; } [DllImport("user32.dll")] public static extern IntPtr DefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); }
3. 在HomePage中实现初始化逻辑
3.1 声明核心变量
在HomePage类中添加以下字段:
private IntPtr _mpvHostHwnd; private MpvPlayer _mpvPlayer; private Windows.UI.Xaml.Hosting.DesktopWindowXamlSource _desktopSource;
3.2 初始化宿主窗口与MPV
在HomePage的Loaded事件中编写初始化代码:
private void HomePage_Loaded(object sender, RoutedEventArgs e) { // 注册Win32窗口类 var wc = new Win32Native.WNDCLASS { lpszClassName = "MPVHostWindow", lpfnWndProc = Marshal.GetFunctionPointerForDelegate(new WndProcDelegate(DefWndProc)), hInstance = System.Diagnostics.Process.GetCurrentProcess().Handle, hbrBackground = IntPtr.Zero }; Win32Native.RegisterClassW(ref wc); // 创建子窗口作为MPV的宿主 _mpvHostHwnd = Win32Native.CreateWindowEx( 0, "MPVHostWindow", "", Win32Native.WS_CHILD | Win32Native.WS_VISIBLE, Win32Native.CW_USEDEFAULT, Win32Native.CW_USEDEFAULT, (int)MPVHostGrid.ActualWidth, (int)MPVHostGrid.ActualHeight, IntPtr.Zero, IntPtr.Zero, wc.hInstance, IntPtr.Zero); // 初始化MPVPlayer _mpvPlayer = new MpvPlayer(_mpvHostHwnd, "path/to/libmpv-2.dll"); // 将Win32窗口嵌入WinUI3页面 _desktopSource = new Windows.UI.Xaml.Hosting.DesktopWindowXamlSource(); _desktopSource.Navigate(_mpvHostHwnd); MPVHostGrid.Children.Add(_desktopSource); } // 窗口过程委托 private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); private IntPtr DefWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { return Win32Native.DefWindowProc(hWnd, msg, wParam, lParam); }
3.3 清理资源避免泄漏
在HomePage的Unloaded事件中释放资源:
private void HomePage_Unloaded(object sender, RoutedEventArgs e) { _mpvPlayer?.Dispose(); if (_mpvHostHwnd != IntPtr.Zero) { Win32Native.DestroyWindow(_mpvHostHwnd); } _desktopSource?.Dispose(); }
4. 配置XAML布局
在HomePage的XAML中添加用于承载Win32窗口的Grid:
<Grid x:Name="MPVHostGrid" Loaded="HomePage_Loaded" Unloaded="HomePage_Unloaded"/>
替代方案:修复WindowsFormsHost使用问题
若你坚持使用WinFormsHost,需完成以下配置:
- 安装
Microsoft.WindowsAppSDK和System.Windows.FormsNuGet包 - 在项目文件中启用Windows Forms兼容:
<PropertyGroup> <UseWindowsForms>true</UseWindowsForms> </PropertyGroup>
- 在XAML中添加WindowsFormsHost及承载控件:
<WindowsFormsHost x:Name="WinFormsHost"> <wf:Panel x:Name="MPVPanel"/> </WindowsFormsHost>
- 初始化时传入Panel的句柄:
_mpvPlayer = new MpvPlayer(MPVPanel.Handle, "path/to/libmpv-2.dll");
内容的提问来源于stack exchange,提问作者PigeonMuyz
相关产品推荐
相关产品推荐

