Chamar APIs do Windows Runtime em aplicativos da área de trabalho

Este tópico descreve como configurar seus projetos de aplicativo da área de trabalho para usar as APIs do WinRT (Windows Runtime) fornecidas pelo sistema operacional Windows e adicionar experiências modernas do Windows 10 e 11 nos aplicativos da área de trabalho.

Algumas APIs do WinRT (Windows Runtime) não são compatíveis com aplicativos da área de trabalho. Para saber mais, confira APIs do Windows Runtime sem suporte em aplicativos da área de trabalho.

Modificar um projeto .NET para usar APIs do Windows Runtime

Há várias opções para projetos .NET:

  • A partir do .NET 6 em diante, é possível especificar o TFM (Moniker da Estrutura de Destino) no arquivo de projeto para acessar as APIs do WinRT. Essa opção tem suporte em projetos direcionados para o Windows 10, versão 1809 ou posteriores.
  • Para versões anteriores do .NET, você pode instalar o pacote NuGet Microsoft.Windows.SDK.Contracts para adicionar todas as referências necessárias ao seu projeto. Essa opção tem suporte em projetos direcionados para o Windows 10, versão 1803 ou posteriores.
  • Se o projeto tiver vários destinos no .NET 6 (ou posterior) e em versões anteriores do .NET, será possível configurar o arquivo de projeto para usar ambas as opções.

.NET 6 e posterior: use a opção do Moniker da Estrutura de Destino

Essa opção só tem suporte em projetos que usam o .NET 6 (ou posterior) e são destinados ao Windows 10, versão 1809 ou a uma versão posterior do sistema operacional. Quando você especifica um TFM específico da versão do sistema operacional Windows no arquivo de projeto, uma referência é adicionada ao pacote de direcionamento do SDK do Windows apropriado. Para obter mais informações sobre esse cenário, confira a postagem no blog Como chamar APIs do Windows no .NET.

  1. Com o projeto aberto no Visual Studio, clique com o botão direito do mouse no seu projeto no Gerenciador de Soluções e escolha Editar o Arquivo de Projeto. O seu arquivo de projeto será semelhante a este.

    Observação

    O exemplo a seguir mostra um OutputType do WinExe, que especifica um executável de GUI do Windows (e impede que uma janela do console seja aberta quando o aplicativo é executado). Se seu aplicativo não tiver uma GUI, o OutputType terá um valor diferente. Você pode chamar APIs do WinRT em aplicativos de GUI do Windows, aplicativos de console e bibliotecas. Além disso, o valor de TargetFramework pode não corresponder exatamente ao exemplo abaixo.

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
      </PropertyGroup>
    </Project>
    
  2. Deixe todas as outras configurações como estão, substitua o valor do elemento TargetFramework por uma das seguintes cadeias de caracteres:

    • net6.0-windows10.0.17763.0: se o seu aplicativo for direcionado para o Windows 10, versão 1809.
    • net6.0-windows10.0.18362.0: se o seu aplicativo for direcionado para o Windows 10, versão 1903.
    • net6.0-windows10.0.19041.0: se o seu aplicativo for direcionado para o Windows 10, versão 2004.
    • net6.0-windows10.0.22000.0: se o seu aplicativo for direcionado para o Windows 11.

    Por exemplo, o elemento a seguir é usado em um projeto direcionado para o Windows 10, versão 2004.

    <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
    

    Em versões posteriores do .NET, você pode substituir o valor pela versão relevante, por exemplo net6.0-windows10.0.19041.0.

  3. Salve as suas alterações e feche o arquivo de projeto.

APIs do WinRT sem suporte no .NET 6 ou posterior

No .NET 6 e posterior, há várias APIs do WinRT (Windows Runtime) no namespace Windows.UI que não têm suporte. No namespace da WinUI (Microsoft.UI), há versões equivalentes para as APIs listadas abaixo, por exemplo, Microsoft.UI.Text. As seguintes APIs do WinRT não têm suporte no .NET 6 e posterior:

Suporte a várias versões do sistema operacional Windows

A propriedade TargetFramework específica do Windows determina a versão do SDK do Windows com a qual seu aplicativo será compilado. Essa propriedade determina o conjunto de APIs acessíveis no tempo de build e fornece valores padrão para TargetPlatformVersion e TargetPlatformMinVersion (se não definido explicitamente). A propriedade TargetPlatformVersion não precisa ser definida explicitamente no arquivo de projeto, pois ela é definida automaticamente pela versão do sistema operacional de TargetFramework.

A TargetPlatformMinVersion pode ser substituída para ser menor que TargetPlatformVersion (determinada pela versão na propriedade TargetFramework). Isso permite que um aplicativo seja executado em versões anteriores do sistema operacional. Por exemplo, você pode definir o código a seguir no arquivo de projeto para dar suporte a versão anterior do aplicativo para Windows 10, versão 1809.

<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
   <OutputType>WinExe</OutputType>
   <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
   <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
 </PropertyGroup>
</Project>

Observe que definir TargetPlatformMinVersion como uma versão abaixo de TargetPlatformVersion cria o potencial para chamar APIs não disponíveis. Ao chamar APIs do WinRT que não estão disponíveis em todas as versões do sistema operacional com suporte, é recomendado proteger essas chamadas com verificações de ApiInformation. Para obter mais informações, confira Aplicativos de versão adaptável.

Versões anteriores do .NET: Instalar o pacote NuGet do Microsoft.Windows.SDK.Contracts

Use essa opção se o aplicativo usar o .NET Core 3.x ou o .NET Framework. Essa opção tem suporte em projetos direcionados para o Windows 10, versão 1803 ou posteriores.

  1. Verifique se as referências de pacote estão habilitadas:

    1. No Visual Studio, clique em Ferramentas > Gerenciador de Pacotes NuGet > Configurações do Gerenciador de Pacotes.
    2. Verifique se PackageReference está selecionado para Formato de gerenciamento de pacotes padrão.
  2. Com o projeto aberto no Visual Studio, clique com o botão direito do mouse no seu projeto no Gerenciador de Soluções e escolha Gerenciar Pacotes NuGet.

  3. Na janela do Gerenciador de Pacotes NuGet, selecione a guia Procurar e procure por Microsoft.Windows.SDK.Contracts.

  4. Depois que o pacote Microsoft.Windows.SDK.Contracts for encontrado, no painel direito da janela do Gerenciador de Pacotes NuGet, selecione a Versão do pacote que você quer instalar com base na versão do Windows 10 que você deseja:

    • 10.0.19041.xxxx: Escolha essa opção para o Windows 10, versão 2004.
    • 10.0.18362.xxxx: escolha essa opção para o Windows 10, versão 1903.
    • 10.0.17763.xxxx: escolha essa opção para o Windows 10, versão 1809.
    • 10.0.17134.xxxx: escolha essa opção para o Windows 10, versão 1803.
  5. Clique em Instalar.

Configurar projetos que têm vários destinos em diferentes versões do .NET

Se o projeto tiver vários destinos no .NET 6 (ou posterior) e em versões anteriores (incluindo o .NET Core 3.x e o .NET Framework), será possível configurar o arquivo de projeto para usar o TFM (Moniker da Estrutura de Destino) para efetuar pull automaticamente nas referências de API do WinRT para o .NET 6 e usar o pacote NuGet Microsoft.Windows.SDK.Contracts para versões anteriores.

  1. Com o projeto aberto no Visual Studio, clique com o botão direito do mouse no seu projeto no Gerenciador de Soluções e escolha Editar o Arquivo de Projeto. O exemplo a seguir demonstra um arquivo de projeto de um aplicativo que usa o .NET Core 3.1.

    Observação

    O exemplo a seguir mostra um OutputType do WinExe, que especifica um executável de GUI do Windows (e impede que uma janela do console seja aberta quando o aplicativo é executado). Se seu aplicativo não tiver uma GUI, o OutputType terá um valor diferente. Você pode chamar APIs do WinRT em aplicativos de GUI do Windows, aplicativos de console e bibliotecas. Além disso, o valor de TargetFramework pode não corresponder exatamente ao exemplo abaixo.

    <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>netcoreapp3.1</TargetFramework>
        <UseWindowsForms>true</UseWindowsForms>
      </PropertyGroup>
    </Project>
    
  2. Substitua o elemento TargetFramework no arquivo por um elemento TargetFrameworks (observe o plural). Nesse elemento, especifique os TFMs (Monikers da Estrutura de Destino) de todas as versões do .NET para as quais você deseja direcionar, separando-os com ponto e vírgula.

    • Para o .NET 6 ou posterior, use um dos seguintes TFMs (Monikers da Estrutura de Destino):
      • net6.0-windows10.0.17763.0: se o seu aplicativo for direcionado para o Windows 10, versão 1809.
      • net6.0-windows10.0.18362.0: se o seu aplicativo for direcionado para o Windows 10, versão 1903.
      • net6.0-windows10.0.19041.0: se o seu aplicativo for direcionado para o Windows 10, versão 2004.
    • Para o .NET Core 3.x, use netcoreapp3.0 ou netcoreapp3.1.
    • Para o .NET Framework, use net46.

    O exemplo a seguir demonstra como aplicar vários destinos ao .NET Core 3.1 e ao .NET 6 (para Windows 10, versão 2004).

    <TargetFrameworks>netcoreapp3.1;net6.0-windows10.0.19041.0</TargetFrameworks>
    
  3. Após o elemento PropertyGroup, adicione um elemento PackageReference que inclui uma instrução condicional que instala o pacote NuGet Microsoft.Windows.SDK.Contracts em qualquer versão do .NET Core 3.x ou o .NET Framework que o seu aplicativo direciona. O elemento PackageReference precisa ser um filho de um elemento ItemGroup. O exemplo a seguir demonstra como fazer isso no .NET Core 3.1.

    <ItemGroup>
      <PackageReference Condition="'$(TargetFramework)' == 'netcoreapp3.1'"
                        Include="Microsoft.Windows.SDK.Contracts"
                        Version="10.0.19041.0" />
    </ItemGroup>
    

    Quando tiver concluído, o seu arquivo de projeto deve ser semelhante a este.

    <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFrameworks>netcoreapp3.1;net6.0-windows10.0.19041.0</TargetFrameworks>
        <UseWPF>true</UseWPF>
      </PropertyGroup>
      <ItemGroup>
        <PackageReference Condition="'$(TargetFramework)' == 'netcoreapp3.1'"
                         Include="Microsoft.Windows.SDK.Contracts"
                         Version="10.0.19041.0" />
      </ItemGroup>
    </Project>
    
  4. Salve as suas alterações e feche o arquivo de projeto.

Modificar um projeto da área de trabalho C++ (Win32) para usar as APIs do Windows Runtime

Use C++/WinRT para consumir as APIs dos WinRT. O C++/WinRT é uma projeção totalmente moderna e padrão da linguagem C++17 para as APIs do WinRT, implementado como uma biblioteca baseada em um arquivo de cabeçalho e projetado para fornecer acesso de primeira classe à API moderna do Windows.

Para configurar o projeto para C++/WinRT:

Para obter mais detalhes sobre essas opções, confira Suporte do Visual Studio para C++/WinRT e o VSIX.

Adicionar experiências do Windows 10

Agora você está pronto para adicionar experiências modernas que se destacam quando os usuários executam seu aplicativo no Windows 10. Use este fluxo de design.

Primeiro, decida quais experiências você deseja adicionar

Há muitas opções. Por exemplo, você pode simplificar o fluxo de ordem de compra usando APIs de monetização ou atenção direta ao seu aplicativo quando você tiver algo interessante para compartilhar, como uma nova foto que outro usuário postou.

Notificação do sistema

Mesmo que os usuários ignorem a mensagem, eles poderão vê-la novamente na central de ações e clicar na mensagem para abrir seu aplicativo. Isso aumenta o envolvimento com seu aplicativo e tem o bônus agregado de fazer o aplicativo aparecer profundamente integrado com o sistema operacional. Mostraremos o código para essa experiência um pouco mais tarde neste artigo.

Visite a Documentação da UWP para obter mais ideias.

Decida entre aprimorar ou estender

Frequentemente, você nos ouvirá usar os termos aprimorar e estender e, portanto, vamos parar um momento para explicar exatamente o que cada um deles significa.

Usamos o termo aprimorar para descrever as APIs do WinRT que você pode chamar diretamente do aplicativo da área de trabalho, seja ele empacotado ou não. Quando você tiver escolhido uma experiência do Windows 10, identifique as APIs de que precisa para criá-la e veja se essa API aparece nesta lista. Essa é uma lista de APIs que você pode chamar diretamente do seu aplicativo de de área de trabalho. Caso sua API não apareça nessa lista, significa que a funcionalidade associada a essa API só pode ser executada em um processo da UWP. Muitas vezes, isso inclui APIs que processam XAML UWP, como um controle de mapa UWP ou um prompt de segurança do Windows Hello.

Observação

Embora as APIs que processam XAML UWP normalmente não possam ser chamadas de forma direta da área de trabalho, você pode usar abordagens alternativas. Se você quiser hospedar controles XAML UWP ou outras experiências visuais personalizadas, poderá usar Ilhas XAML (a partir do Windows 10, versão 1903) e a Camada visual (a partir do Windows 10, versão 1803). Esses recursos podem ser usados em aplicativos da área de trabalho empacotados ou não.

Se você optou por empacotar o aplicativo da área de trabalho, outra opção é estender o aplicativo adicionando um projeto UWP à solução. O projeto da área de trabalho ainda é o ponto de entrada do seu aplicativo, mas o projeto UWP oferece acesso a todas as APIs que não aparecem nesta lista. O aplicativo da área de trabalho pode se comunicar com o processo UWP usando um serviço de aplicativo, e temos muitas diretrizes sobre como configurar isso. Se você quiser adicionar uma experiência que exija um projeto UWP, confira Estender com componentes UWP.

Faça referência a contratos de API

Se você puder chamar a API diretamente do seu aplicativo da área de trabalho, abra um navegador e pesquise o tópico de referência dessa API. Abaixo do resumo da API, você encontrará uma tabela que descreve o contrato dessa API. Confira um exemplo dessa tabela:

Tabela de contrato de API

Se você tiver um aplicativo da área de trabalho baseado em .NET, adicione uma referência a esse contrato de API e defina a propriedade Copiar Local desse arquivo como False. Se você tiver um projeto baseado em C++, adicione aos seus Diretórios de Inclusão Adicionais, um caminho para a pasta que contém esse contrato.

Chame as APIs para adicionar sua experiência

Aqui está o código que você usaria para mostrar a janela de notificação que vimos anteriormente. Essas APIs aparecem nesta lista e, portanto, você pode adicionar este código ao seu aplicativo da área de trabalho e executá-lo imediatamente.

using Windows.Foundation;
using Windows.System;
using Windows.UI.Notifications;
using Windows.Data.Xml.Dom;
...

private void ShowToast()
{
    string title = "featured picture of the day";
    string content = "beautiful scenery";
    string image = "https://picsum.photos/360/180?image=104";
    string logo = "https://picsum.photos/64?image=883";

    string xmlString =
    $@"<toast><visual>
       <binding template='ToastGeneric'>
       <text>{title}</text>
       <text>{content}</text>
       <image src='{image}'/>
       <image src='{logo}' placement='appLogoOverride' hint-crop='circle'/>
       </binding>
      </visual></toast>";

    XmlDocument toastXml = new XmlDocument();
    toastXml.LoadXml(xmlString);

    ToastNotification toast = new ToastNotification(toastXml);

    ToastNotificationManager.CreateToastNotifier().Show(toast);
}
#include <sstream>
#include <winrt/Windows.Data.Xml.Dom.h>
#include <winrt/Windows.UI.Notifications.h>

using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Notifications;
using namespace winrt::Windows::Data::Xml::Dom;

void UWP::ShowToast()
{
    std::wstring const title = L"featured picture of the day";
    std::wstring const content = L"beautiful scenery";
    std::wstring const image = L"https://picsum.photos/360/180?image=104";
    std::wstring const logo = L"https://picsum.photos/64?image=883";

    std::wostringstream xmlString;
    xmlString << L"<toast><visual><binding template='ToastGeneric'>" <<
        L"<text>" << title << L"</text>" <<
        L"<text>" << content << L"</text>" <<
        L"<image src='" << image << L"'/>" <<
        L"<image src='" << logo << L"'" <<
        L" placement='appLogoOverride' hint-crop='circle'/>" <<
        L"</binding></visual></toast>";

    XmlDocument toastXml;

    toastXml.LoadXml(xmlString.str().c_str());

    ToastNotificationManager::CreateToastNotifier().Show(ToastNotification(toastXml));
}
using namespace Windows::Foundation;
using namespace Windows::System;
using namespace Windows::UI::Notifications;
using namespace Windows::Data::Xml::Dom;

void UWP::ShowToast()
{
    Platform::String ^title = "featured picture of the day";
    Platform::String ^content = "beautiful scenery";
    Platform::String ^image = "https://picsum.photos/360/180?image=104";
    Platform::String ^logo = "https://picsum.photos/64?image=883";

    Platform::String ^xmlString =
        L"<toast><visual><binding template='ToastGeneric'>" +
        L"<text>" + title + "</text>" +
        L"<text>"+ content + "</text>" +
        L"<image src='" + image + "'/>" +
        L"<image src='" + logo + "'" +
        L" placement='appLogoOverride' hint-crop='circle'/>" +
        L"</binding></visual></toast>";

    XmlDocument ^toastXml = ref new XmlDocument();

    toastXml->LoadXml(xmlString);

    ToastNotificationManager::CreateToastNotifier()->Show(ref new ToastNotification(toastXml));
}

Para saber mais sobre notificações, confira Notificações do sistema interativas e adaptáveis.

Dar suporte às bases de instalação do Windows XP, Windows Vista e Windows 7/8

Você pode modernizar seu aplicativo para Windows 10 sem precisar criar um novo branch e manter bases de código separadas.

Se você quiser compilar binários separados para usuários do Windows 10, use a compilação condicional. Se você preferir criar um conjunto de binários implantado para todos os usuários do Windows, use as verificações de runtime.

Vamos dar uma rápida olhada em cada opção.

Compilação condicional

Você pode manter um código de base e compilar um conjunto de binários apenas para usuários do Windows 10.

Primeiro, adicione uma nova configuração de build ao seu projeto.

Configuração de build

Para essa configuração de build, crie uma constante que identifique o código que chama as APIs do WinRT.

Em projetos baseados em .NET, a constante é chamada de Constante de Compilação Condicional.

Constante de Compilação Condicional

Em projetos baseados em C++, a constante é chamada de Definição de Pré-processador.

Constante de Definição de Pré-processador

Adicione essa constante antes de qualquer bloco de código UWP.

[System.Diagnostics.Conditional("_UWP")]
private void ShowToast()
{
 ...
}
#if _UWP
void UWP::ShowToast()
{
 ...
}
#endif

O compilador só compilará esse código se essa constante for definida em sua configuração de build ativa.

verificações de runtime

Você pode compilar um conjunto de binários para todos os usuários do Windows, independentemente da versão do Windows executada. O aplicativo chama as APIs do WinRT apenas quando o usuário o executa como um aplicativo empacotado no Windows 10.

A maneira mais fácil de adicionar verificações de runtime ao código é instalar este pacote Nuget: Auxiliares de Ponte de Desktop e usar o método IsRunningAsUWP() para identificar todo o código que chama as APIs do WinRT. Para obter mais informações, confira esta postagem no blog: Ponte de Desktop – Identificar o contexto do aplicativo.

Encontrar respostas para suas dúvidas

Tem dúvidas? Pergunte-nos no Stack Overflow. Nossa equipe monitora estas marcas. Você também pode perguntar em nossos fóruns.