You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何启动UWP应用并隐藏窗口,实现WPF调用无线投屏功能?

解决WPF调用UWP投屏功能并隐藏UWP窗口的思路

1. 采用WinUI 3嵌入WPF(XAML Islands),避免独立UWP进程

直接在WPF项目中嵌入WinUI控件,在同一个进程内调用WinRT的ProjectionManager API,无需单独启动UWP进程,自然解决窗口隐藏问题。

实现步骤:

  • 在WPF项目中添加Microsoft.Toolkit.Wpf.UI.XamlHost和Microsoft.UI.Xaml NuGet包。
  • 在WPF窗口的XAML中添加WindowsXamlHost控件,承载WinUI环境:
    <xamlHost:WindowsXamlHost InitialTypeName="Microsoft.UI.Xaml.Controls.Grid" x:Name="WinUIHost"/>
    
  • 在后台代码中获取WinUI对应的CoreWindow和ApplicationView,调用投屏API后隐藏WinUI窗口:
    using Windows.UI.ViewManagement;
    using Windows.Media.Casting;
    using Microsoft.Toolkit.Wpf.UI.XamlHost;
    
    private async void StartProjection_Click(object sender, RoutedEventArgs e)
    {
        // 获取WinUI对应的CoreWindow实例
        var coreWindow = WinUIHost.WindowHandle.GetCoreWindow();
        if (coreWindow == null) return;
    
        // 获取当前WinUI环境的ApplicationView
        var appView = ApplicationView.GetForCurrentView();
    
        // 隐藏WinUI窗口(无需显示给用户)
        coreWindow.Visibility = Windows.UI.Core.CoreWindowVisibility.Collapsed;
    
        // 选择投屏设备并启动投射
        var picker = new CastDevicePicker();
        var selectedDevice = await picker.PickDeviceAsync();
        if (selectedDevice != null)
        {
            // 传入当前ApplicationView的ID作为源和目标视图ID
            await ProjectionManager.StartProjectingAsync(appView.Id, appView.Id);
        }
    }
    

2. 独立UWP进程+IPC通信,启动时隐藏UWP窗口

若必须保留独立UWP进程,可让UWP启动时自动隐藏窗口,通过进程间通信(IPC)接收WPF的投屏指令。

UWP端实现:

  • 在App.xaml.cs的OnLaunched方法中直接隐藏主窗口:
    protected override async void OnLaunched(LaunchActivatedEventArgs e)
    {
        // 不显示UWP主窗口
        Window.Current.Hide();
    
        // 注册App Service,接收WPF的投屏请求
        var appServiceConnection = new AppServiceConnection();
        appServiceConnection.AppServiceName = "com.wpf.projection.service";
        appServiceConnection.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
        appServiceConnection.RequestReceived += OnProjectionRequestReceived;
    
        await appServiceConnection.OpenAsync();
    }
    
    private async void OnProjectionRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
    {
        var requestData = args.Request.Message;
        if (requestData.ContainsKey("StartProjection"))
        {
            var appView = ApplicationView.GetForCurrentView();
            // 启动投屏
            await ProjectionManager.StartProjectingAsync(appView.Id, appView.Id);
            // 回复WPF请求结果
            await args.Request.SendResponseAsync(new Windows.Foundation.Collections.ValueSet { { "Status", "Success" } });
        }
    }
    
  • 在UWP的Package.appxmanifest中声明App Service扩展:
    <Extensions>
      <uap:Extension Category="windows.appService">
        <uap:AppService Name="com.wpf.projection.service"/>
      </uap:Extension>
    </Extensions>
    

WPF端实现:

  • 通过App Service连接到UWP进程,发送投屏指令:
    using Windows.ApplicationModel.AppService;
    using Windows.Foundation.Collections;
    
    private async void TriggerProjection_Click(object sender, RoutedEventArgs e)
    {
        var connection = new AppServiceConnection();
        connection.AppServiceName = "com.wpf.projection.service";
        // 替换为你的UWP包家族名(可在UWP项目的Package.appxmanifest中查看)
        connection.PackageFamilyName = "YourUwpPackageFamilyName";
    
        var connectionStatus = await connection.OpenAsync();
        if (connectionStatus == AppServiceConnectionStatus.Success)
        {
            var response = await connection.SendMessageAsync(new ValueSet { { "StartProjection", "" } });
            if (response.Status == AppServiceResponseStatus.Success)
            {
                // 投屏指令已发送
            }
        }
    }
    

3. 用Desktop Bridge打包WPF与UWP,优化进程协同

将WPF和UWP打包为同一个MSIX包,两者共享权限、资源,UWP可作为后台辅助进程启动,进一步降低用户感知。

关键优势:

  • UWP进程启动时不会在任务栏显示图标(需隐藏主窗口,注意ProjectionManager依赖UI线程,不能用纯后台任务)。
  • 进程间通信更稳定,无需额外配置防火墙规则。

通用注意事项:

  • UWP需声明privateNetworkClientServer权限(用于发现投屏设备),若需捕获桌面屏幕,还需添加screenCapture权限。
  • ProjectionManager.StartProjectingAsync的两个参数:第一个是要投射的目标视图ID,第二个是源视图ID;若需投射桌面而非UWP内容,需结合ScreenCapture API捕获桌面画面后再投射。

内容的提问来源于stack exchange,提问作者Tom Xue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 03:23:22