Partilhar via


Estender o aplicativo da área de trabalho com componentes UWP modernos

Algumas experiências do Windows (por exemplo, uma página de interface do usuário habilitada para toque) devem ser executadas dentro de um AppContainer. Se você quiser adicionar essas experiências, estenda o aplicativo da área de trabalho com projetos UWP e componentes do Windows Runtime.

Em muitos casos, você pode chamar APIs do Windows Runtime diretamente em seu aplicativo da área de trabalho. Portanto, antes de examinar este guia, confira Aprimorar para o Windows.

Observação

Os recursos descritos neste tópico exigem que o aplicativo seja empacotado (tenha uma identidade de pacote no runtime). Isso inclui aplicativos empacotados (confira Criar um projeto para um aplicativo da área de trabalho do WinUI 3 empacotado) e aplicativos empacotados com localização externa (confira Conceder identidade do pacote empacotando-o com localização externa). Veja também Recursos que exigem a identidade do pacote.

Primeiro, configure sua solução

Adicione um ou mais projetos UWP e componentes de runtime à sua solução.

Comece com uma solução que contenha um Projeto de Empacotamento de Aplicativo do Windows com uma referência ao seu aplicativo da área de trabalho.

Esta imagem mostra um exemplo de solução.

Estender projeto inicial

Caso a sua solução não contenha um projeto de empacotamento, confira Empacotar seu aplicativo da área de trabalho usando o Visual Studio.

Configurar o aplicativo da área de trabalho

Verifique se o aplicativo da área de trabalho tem referências aos arquivos de que você precisa para chamar as APIs do Windows Runtime.

Para fazer isso, confira Chamar APIs do Windows Runtime em aplicativos da área de trabalho.

Adicionar um projeto UWP

Adicionar um Aplicativo em branco (Universal do Windows) à sua solução.

Aqui, você criará uma interface XAML moderna ou usará APIs que são executadas somente dentro de um processo UWP.

Adicionar novo projeto

No seu projeto de empacotamento, clique com botão direito no nó Aplicativos e clique em Adicionar Referência.

Adicionar referência

Depois, adicione uma referência ao projeto UWP.

Selecionar um projeto UWP

A solução terá a seguinte aparência:

Solução com projeto UWP

(Opcional) Adicionar um componente do Windows Runtime

Para realizar alguns cenários, você precisará adicionar código a um componente do Windows Runtime.

serviço de aplicativo de componente de runtime

Em seguida, no projeto UWP, adicione uma referência ao componente de runtime. A solução terá a seguinte aparência:

Referência do componente de runtime

Criar sua solução

Crie sua solução para garantir que nenhum erro seja exibido. Se você receber erros, abra Gerenciador de Configurações e verifique se os projetos se destinam à mesma plataforma.

Gerenciador de Configurações

Vamos dar uma olhada em algumas coisas que você pode fazer com seus projetos UWP e componentes de runtime.

Mostrar uma interface do usuário XAML moderna

Como parte do fluxo de seu aplicativo, você pode incorporar interfaces do usuário modernas baseadas em XAML em seu aplicativo da área de trabalho. Essas interfaces do usuário são naturalmente adaptáveis para diferentes tamanhos de tela e resoluções e dão suporte a modelos interativos modernos, como toque e tinta.

Por exemplo, com uma pequena quantidade de marcação XAML, você pode oferecer aos usuários recursos de visualização de mapa eficientes.

Esta imagem mostra um aplicativo Windows Forms que abre uma interface do usuário moderna baseada em XAML, a qual contém um controle de mapa.

design adaptável

Observação

Esse exemplo mostra uma interface de usuário XAML adicionando um projeto UWP à solução. Essa é a abordagem estável compatível para mostrar interfaces do usuário XAML em um aplicativo da área de trabalho. A alternativa é adicionar os controles do XAML UWP diretamente ao aplicativo da área de trabalho usando uma Ilha XAML. As ilhas XAML estão disponíveis atualmente como uma versão prévia para desenvolvedores. Embora incentivemos você a testá-los em seu próprio código de protótipo, não recomendamos que você os use no código de produção neste momento. Essas APIs e controles continuarão ser aprimorados e estabilizados em versões futuras do Windows. Para saber mais sobre as Ilhas XAML, confira Controles UWP em aplicativos da área de trabalho

O padrão de design

Para mostrar uma interface do usuário baseada em XAML, é preciso:

1️⃣ Configurar sua solução

2️⃣ Criar uma interface do usuário XAML

3️⃣ Adicionar uma extensão de protocolo ao projeto UWP

4️⃣ Iniciar o aplicativo UWP em seu aplicativo da área de trabalho

5️⃣ No projeto UWP, mostrar a página desejada

Configurar sua solução

Para obter diretrizes gerais de como configurar a solução, confira a seção Primeiro, configure sua solução no início deste guia.

A solução terá a seguinte aparência:

Solução da interface do usuário XAML

Nesse exemplo, o projeto do Windows Forms é denominado Landmarks, e o projeto UWP que contém a interface do usuário XAML é denominado MapUI.

Criar uma interface do usuário XAML

Adicione uma interface do usuário XAML a seu projeto UWP. Confira o XAML do mapa básico.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="12,20,12,14">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <maps:MapControl x:Name="myMap" Grid.Column="0" Width="500" Height="500"
                     ZoomLevel="{Binding ElementName=zoomSlider,Path=Value, Mode=TwoWay}"
                     Heading="{Binding ElementName=headingSlider,Path=Value, Mode=TwoWay}"
                     DesiredPitch="{Binding ElementName=desiredPitchSlider,Path=Value, Mode=TwoWay}"
                     HorizontalAlignment="Left"
                     MapServiceToken="<Your Key Goes Here" />
    <Grid Grid.Column="1" Margin="12">
        <StackPanel>
            <Slider Minimum="1" Maximum="20" Header="ZoomLevel" Name="zoomSlider" Value="17.5"/>
            <Slider Minimum="0" Maximum="360" Header="Heading" Name="headingSlider" Value="0"/>
            <Slider Minimum="0" Maximum="64" Header=" DesiredPitch" Name="desiredPitchSlider" Value="32"/>
        </StackPanel>
    </Grid>
</Grid>

Adicionar uma extensão de protocolo

No Gerenciador de Soluções, abra o arquivo package.appxmanifest do projeto de Empacotamento da sua solução e adicione esta extensão.

<Extensions>
  <uap:Extension Category="windows.protocol" Executable="MapUI.exe" EntryPoint="MapUI.App">
    <uap:Protocol Name="xamluidemo" />
  </uap:Extension>
</Extensions>

Dê um nome ao protocolo, forneça o nome do executável produzido pelo projeto UWP e o nome da classe de ponto de entrada.

Você também pode abrir o package.appxmanifest no designer, escolher a guia Declarações e adicionar a extensão ali.

guia declarações

Observação

Os controles de mapa baixam dados da Internet e, se você usar um, também terá que adicionar o recurso "cliente da internet" ao seu manifesto.

Iniciar o aplicativo UWP

Primeiro, em seu aplicativo da área de trabalho, crie um Uri que inclua o nome de protocolo e os parâmetros que você deseja transmitir para o aplicativo UWP. Em seguida, chame o método LaunchUriAsync.


private void Statue_Of_Liberty_Click(object sender, EventArgs e)
{
    ShowMap(40.689247, -74.044502);
}

private async void ShowMap(double lat, double lon)
{
    string str = "xamluidemo://";

    Uri uri = new Uri(str + "location?lat=" +
        lat.ToString() + "&?lon=" + lon.ToString());

    var success = await Windows.System.Launcher.LaunchUriAsync(uri);

}

Analisar parâmetros e mostrar uma página

Na classe App do projeto UWP, substitua o manipulador de eventos OnActivated. Se o aplicativo for ativado pelo seu protocolo, analise os parâmetros e abra a página desejada.

protected override void OnActivated(Windows.ApplicationModel.Activation.IActivatedEventArgs e)
{
    if (e.Kind == ActivationKind.Protocol)
    {
        ProtocolActivatedEventArgs protocolArgs = (ProtocolActivatedEventArgs)e;
        Uri uri = protocolArgs.Uri;
        if (uri.Scheme == "xamluidemo")
        {
            Frame rootFrame = new Frame();
            Window.Current.Content = rootFrame;
            rootFrame.Navigate(typeof(MainPage), uri.Query);
            Window.Current.Activate();
        }
    }
}

No código por trás da página XAML, substitua o método OnNavigatedTo para usar os parâmetros passados para a página. Nesse caso, usaremos a latitude e longitude passadas para essa página a fim de mostrar uma localização em um mapa.

protected override void OnNavigatedTo(NavigationEventArgs e)
 {
     if (e.Parameter != null)
     {
         WwwFormUrlDecoder decoder = new WwwFormUrlDecoder(e.Parameter.ToString());

         double lat = Convert.ToDouble(decoder[0].Value);
         double lon = Convert.ToDouble(decoder[1].Value);

         BasicGeoposition pos = new BasicGeoposition();

         pos.Latitude = lat;
         pos.Longitude = lon;

         myMap.Center = new Geopoint(pos);

         myMap.Style = MapStyle.Aerial3D;

     }

     base.OnNavigatedTo(e);
 }

Tornar seu aplicativo da área de trabalho um destino de compartilhamento

Você pode tornar seu aplicativo da área de trabalho um destino de compartilhamento para que os usuários possam compartilhar com facilidade dados como imagens de outros aplicativos que dão suporte a compartilhamento.

Por exemplo, os usuários podem escolher seu aplicativo para compartilhar fotos do Microsoft Edge, o aplicativo Fotos. Confira um aplicativo WPF de exemplo que tem esse recurso.

destino de compartilhamento.

Confira o exemplo completo aqui

O padrão de design

Para tornar seu aplicativo um destino de compartilhamento, é preciso:

1️⃣ Adicionar uma extensão de destino de compartilhamento

2️⃣ Substituir o manipulador de eventos OnShareTargetActivated

3️⃣ Adicionar extensões de área de trabalho ao projeto UWP

4️⃣ Adicionar a extensão de processo de confiança total

5️⃣ Modificar o aplicativo da área de trabalho para obter o arquivo compartilhado

As etapas a seguir

Adicionar uma extensão de destino de compartilhamento

No Gerenciador de Soluções, abra o arquivo package.appxmanifest do projeto de Empacotamento da sua solução e adicione a extensão de destino de compartilhamento.

<Extensions>
      <uap:Extension
          Category="windows.shareTarget"
          Executable="ShareTarget.exe"
          EntryPoint="App">
        <uap:ShareTarget>
          <uap:SupportedFileTypes>
            <uap:SupportsAnyFileType />
          </uap:SupportedFileTypes>
          <uap:DataFormat>Bitmap</uap:DataFormat>
        </uap:ShareTarget>
      </uap:Extension>
</Extensions>  

Forneça o nome do executável produzido pelo projeto UWP e o nome da classe de ponto de entrada. Essa marcação pressupõe que o nome do executável para seu aplicativo UWP é ShareTarget.exe.

Você também precisará especificar os tipos de arquivos que poderão ser compartilhados com seu aplicativo. Nesse exemplo, estamos tornando o aplicativo da área de trabalho WPF PhotoStoreDemo um destino de compartilhamento para imagens bitmap, portanto, especificamos Bitmap como o tipo de arquivo com suporte.

Substituir o manipulador de eventos OnShareTargetActivated

Substitua o manipulador de eventos OnActivated na classe App do projeto UWP.

Esse manipulador de eventos é chamado quando os usuários escolhem seu aplicativo para compartilhar arquivos.


protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
    shareWithDesktopApplication(args.ShareOperation);
}

private async void shareWithDesktopApplication(ShareOperation shareOperation)
{
    if (shareOperation.Data.Contains(StandardDataFormats.StorageItems))
    {
        var items = await shareOperation.Data.GetStorageItemsAsync();
        StorageFile file = items[0] as StorageFile;
        IRandomAccessStreamWithContentType stream = await file.OpenReadAsync();

        await file.CopyAsync(ApplicationData.Current.LocalFolder);
            shareOperation.ReportCompleted();

        await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
    }
}

Nesse código, salvamos a imagem que está sendo compartilhada pelo usuário em uma pasta de armazenamento local de aplicativos. Em seguida, modificaremos o aplicativo da área de trabalho para extrair imagens da mesma pasta. O aplicativo da área de trabalho pode fazer isso porque ele está incluído no mesmo pacote que o aplicativo UWP.

Adicionar extensões de área de trabalho ao projeto UWP

Adicione a extensão Extensões da área de trabalho do Windows para UWP ao projeto de aplicativo UWP. Você verá mais de uma versão da extensão (por exemplo, 10.0.18362.0 e 10.0.19041.0). Para obter informações sobre como escolher uma versão, confira SDKs de extensão e como referenciá-los.

extensão de área de trabalho

Adicionar a extensão de processo de confiança total

No Explorador de soluções, abra o arquivo package.appxmanifest no projeto de Empacotamento na sua solução e adicione a extensão de processo de confiança total ao lado da extensão de destino de compartilhamento que você adicionou a esse arquivo anteriormente.

<Extensions>
  ...
      <desktop:Extension Category="windows.fullTrustProcess" Executable="PhotoStoreDemo\PhotoStoreDemo.exe" />
  ...
</Extensions>  

Essa extensão permitirá que o aplicativo UWP inicie o aplicativo da área de trabalho com o qual você deseja compartilhar um arquivo. No exemplo, fazemos referência ao executável do aplicativo da área de trabalho WPF PhotoStoreDemo.

Modificar o aplicativo da área de trabalho para obter o arquivo compartilhado

Modifique o aplicativo da área de trabalho para encontrar e processar o arquivo compartilhado. Neste exemplo, o aplicativo UWP armazenou o arquivo compartilhado na pasta de dados do aplicativo local. Portanto, modificaremos o aplicativo da área de trabalho WPF PhotoStoreDemo para extrair fotos dessa pasta.

Photos.Path = Windows.Storage.ApplicationData.Current.LocalFolder.Path;

Para instâncias do aplicativo da área de trabalho já abertas pelo usuário, também podemos manipular o evento FileSystemWatcher e passar o caminho para o local do arquivo. Dessa forma, qualquer instância aberta do aplicativo da área de trabalho mostrará a foto compartilhada.

...

   FileSystemWatcher watcher = new FileSystemWatcher(Photos.Path);

...

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    // new file got created, adding it to the list
    Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
    {
        if (File.Exists(e.FullPath))
        {
            ImageFile item = new ImageFile(e.FullPath);
            Photos.Insert(0, item);
            PhotoListBox.SelectedIndex = 0;
            CurrentPhoto.Source = (BitmapSource)item.Image;
        }
    }));
}

Criar uma tarefa em segundo plano

Adicione uma tarefa em segundo plano para executar o código, mesmo quando o aplicativo estiver suspenso. É ótimo deixar em segundo plano tarefas pequenas que não exigem a interação do usuário. Por exemplo, sua tarefa pode baixar emails, mostrar uma notificação do sistema sobre uma mensagem de chat recebida ou reagir a uma alteração em uma condição do sistema.

Este é um exemplo de aplicativo WPF que registra uma tarefa em segundo plano.

tarefa em segundo plano

A tarefa faz uma solicitação http e mede o tempo que leva para a solicitação retornar uma resposta. As tarefas provavelmente serão muito mais interessantes, mas esse exemplo é ótimo para aprender a mecânica básica de uma tarefa em segundo plano.

Confira o exemplo completo aqui.

O padrão de design

Para criar um serviço em segundo plano, é preciso:

1️⃣ Implementar a tarefa em segundo plano

2️⃣ Configurar a tarefa em segundo plano

3️⃣ Registrar a tarefa em segundo plano

Implementar a tarefa em segundo plano

Implemente a tarefa em segundo plano adicionando código a um projeto de componente do Windows Runtime.

public sealed class SiteVerifier : IBackgroundTask
{
    public async void Run(IBackgroundTaskInstance taskInstance)
    {

        taskInstance.Canceled += TaskInstance_Canceled;
        BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
        var msg = await MeasureRequestTime();
        ShowToast(msg);
        deferral.Complete();
    }

    private async Task<string> MeasureRequestTime()
    {
        string msg;
        try
        {
            var url = ApplicationData.Current.LocalSettings.Values["UrlToVerify"] as string;
            var http = new HttpClient();
            Stopwatch clock = Stopwatch.StartNew();
            var response = await http.GetAsync(new Uri(url));
            response.EnsureSuccessStatusCode();
            var elapsed = clock.ElapsedMilliseconds;
            clock.Stop();
            msg = $"{url} took {elapsed.ToString()} ms";
        }
        catch (Exception ex)
        {
            msg = ex.Message;
        }
        return msg;
    }

Configurar a tarefa em segundo plano

No designer de manifesto, abra o arquivo package.appxmanifest do projeto de Empacotamento em sua solução.

Na guia Declarações, adicione uma declaração Tarefas em segundo plano.

Opção de tarefa em segundo plano

Em seguida, escolha as propriedades desejadas. Nosso exemplo usa a propriedade Timer.

Propriedade Timer

Forneça o nome totalmente qualificado da classe no seu componente do Windows Runtime que implementa a tarefa em segundo plano.

Especificar o ponto de entrada

Registrar a tarefa em segundo plano

Adicione código ao seu projeto de aplicativo da área de trabalho que registra a tarefa em segundo plano.

public void RegisterBackgroundTask(String triggerName)
{
    var current = BackgroundTaskRegistration.AllTasks
        .Where(b => b.Value.Name == triggerName).FirstOrDefault().Value;

    if (current is null)
    {
        BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
        builder.Name = triggerName;
        builder.SetTrigger(new MaintenanceTrigger(15, false));
        builder.TaskEntryPoint = "HttpPing.SiteVerifier";
        builder.Register();
        System.Diagnostics.Debug.WriteLine("BGTask registered:" + triggerName);
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("Task already:" + triggerName);
    }
}

Encontrar respostas para suas dúvidas

Tem dúvidas? Pergunte-nos no Stack Overflow. Nossa equipe monitora estas marcas. Você também pode entrar em contato conosco aqui.