Compartilhar via


Introdução ao C++/WinRT

Importante

Para obter informações sobre como configurar o Visual Studio para desenvolvimento com C++/WinRT, incluindo a instalação e o uso da extensão C++/WinRT Visual Studio (VSIX) e o pacote NuGet (que juntos fornecem suporte para modelo de projeto e construção), consulte Suporte do Visual Studio para C++/WinRT.

Para deixá-lo atualizado com o uso de C++/WinRT, este tópico explora um exemplo de código simples baseado em um novo projeto de Aplicativo de Console do Windows (C++/WinRT). Este tópico também mostra como adicionar suporte para C++/WinRT a um projeto de aplicativo da Área de Trabalho do Windows.

Observação

Embora seja recomendável desenvolver com as versões mais recentes do Visual Studio e do SDK do Windows, se você estiver usando o Visual Studio 2017 (versão 15.8.0 ou posterior) e direcionando o SDK do Windows versão 10.0.17134.0 (Windows 10, versão 1803), um projeto C++/WinRT recém-criado poderá falhar ao compilar com o erro "erro C3861: 'from_abi': identificador não encontrado", e com outros erros originados em base.h. A solução é direcionar uma versão posterior (mais conforme) do SDK do Windows ou definir a propriedade do projeto C/C++>Linguagem>modo de conformidade: Não (também, se /permissive- aparecer na propriedade do projeto C/C++>Linguagem>Linha de Comando em Opções Adicionais , em seguida, exclua-o).

Um início rápido do C++/WinRT

Crie um novo projeto Aplicativo de Console do Windows (C++/WinRT).

Edite pch.h e main.cpp para ter esta aparência.

// pch.h
#pragma once
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>
#include <iostream>
// main.cpp
#include "pch.h"

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

int main()
{
    winrt::init_apartment();

    Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
    SyndicationClient syndicationClient;
    syndicationClient.SetRequestHeader(L"User-Agent", L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
    SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();
    for (const SyndicationItem syndicationItem : syndicationFeed.Items())
    {
        winrt::hstring titleAsHstring = syndicationItem.Title().Text();
        
        // A workaround to remove the trademark symbol from the title string, because it causes issues in this case.
        std::wstring titleAsStdWstring{ titleAsHstring.c_str() };
        titleAsStdWstring.erase(remove(titleAsStdWstring.begin(), titleAsStdWstring.end(), L'™'), titleAsStdWstring.end());
        titleAsHstring = titleAsStdWstring;

        std::wcout << titleAsHstring.c_str() << std::endl;
    }
}

Vamos usar o exemplo de código curto acima, peça por peça, e explicar o que está acontecendo em cada parte.

#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>

Com as configurações de projeto padrão, os cabeçalhos incluídos vêm do SDK do Windows, dentro da pasta %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. O Visual Studio inclui esse caminho em sua macro IncludePath. Mas não há nenhuma dependência estrita no SDK do Windows, pois seu projeto (por meio da ferramenta cppwinrt.exe) gera esses mesmos cabeçalhos na pasta $(GeneratedFilesDir) do seu projeto. Eles serão carregados dessa pasta se não puderem ser encontrados em outro lugar ou se você alterar as configurações do projeto.

Os cabeçalhos contêm APIs do Windows projetadas em C++/WinRT. Em outras palavras, para cada tipo do Windows, C++/WinRT define um equivalente amigável ao C++ (chamado tipo projetado do). Um tipo projetado tem o mesmo nome totalmente qualificado que o tipo do Windows, mas é colocado no namespace do C++. Colocar esses includes em seu cabeçalho pré-compilado reduz os tempos de compilação incrementais.

Importante

Sempre que quiser usar um tipo de um namespace do Windows, você deverá #include o arquivo de cabeçalho do namespace do Windows C++/WinRT correspondente, conforme mostrado acima. O cabeçalho correspondente é aquele com o mesmo nome do namespace do tipo. Por exemplo, para utilizar a projeção C++/WinRT da classe de runtime Windows::Foundation::Collections::PropertySet, inclua o cabeçalho winrt/Windows.Foundation.Collections.h.

É comum que um cabeçalho de projeção C++/WinRT inclua automaticamente arquivos de cabeçalho de namespace relacionados. Por exemplo, winrt/Windows.Foundation.Collections.h inclui winrt/Windows.Foundation.h. Mas você não deve confiar nesse comportamento, pois é um detalhe de implementação que muda ao longo do tempo. Você deve incluir explicitamente todos os cabeçalhos necessários.

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

As diretivas using namespace são opcionais, mas convenientes. O padrão mostrado acima para essas diretivas (permitindo a pesquisa de nomes não qualificados para qualquer coisa no winrt namespace) é adequado para quando você está iniciando um novo projeto e C++/WinRT é a única projeção de linguagem que você está usando dentro desse projeto. Se, por outro lado, você estiver misturando código C++/WinRT com código C++/CX e/ou código ABI (interface binária do aplicativo SDK) (você está portando de, ou interoperando com, um ou ambos os modelos), consulte os seguintes tópicos: Interop entre C++/WinRT e C++/CX, Mover para C++/WinRT do C++/CXe Interop entre C++/WinRT e a ABI.

winrt::init_apartment();

A chamada para winrt::init_apartment inicializa o thread no Windows Runtime; por padrão, em um apartamento multithreaded. A chamada também inicializa COM.

Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;

Alocar na pilha dois objetos: eles representam o URI do blog do Windows e um cliente de sindicação. Criamos o uri com um literal de cadeia de caracteres largo simples (consulte Tratamento de cadeia de caracteres em C++/WinRT para obter mais maneiras de trabalhar com cadeias de caracteres).

SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();

SyndicationClient::RetrieveFeedAsync é um exemplo de uma função assíncrona do Windows Runtime. O exemplo de código recebe um objeto de operação assíncrona do RetrieveFeedAsynce invoca get nesse objeto para bloquear o fio de execução chamador e aguardar o resultado (que é um feed de syndicação, nesse caso). Para obter mais informações sobre concorrência e técnicas de não bloqueio, consulte Concorrência e Operações Assíncronas com C++/WinRT.

for (const SyndicationItem syndicationItem : syndicationFeed.Items()) { ... }

SyndicationFeed.Items é um intervalo definido pelos iteradores retornados pelas funções begin e end (ou suas variantes constantes, reversas e constantes-reversas). Por isso, você pode enumerar os itens com uma declaração baseada em intervalo for ou com a função template std::for_each. Sempre que você iterar em uma coleção do Windows Runtime como esta, precisará #include <winrt/Windows.Foundation.Collections.h>.

winrt::hstring titleAsHstring = syndicationItem.Title().Text();

// Omitted: there's a little bit of extra work here to remove the trademark symbol from the title text.

std::wcout << titleAsHstring.c_str() << std::endl;

Obtém o texto do título do feed, como um objeto winrt::hstring (mais detalhes no tratamento de cadeia de caracteres noC++/WinRT). A entrada hstring é então exibida por meio da função c_str, que reflete o padrão usado com strings da Biblioteca Padrão C++.

Como você pode ver, O C++/WinRT incentiva expressões C++ modernas e semelhantes a classes, como syndicationItem.Title().Text(). Esse é um estilo de programação diferente e mais limpo da programação COM tradicional. Você não precisa inicializar diretamente COM nem trabalhar com ponteiros COM.

Também não é necessário lidar com códigos de retorno HRESULT. O C++/WinRT converte HRESULTs de erro em exceções como winrt::hresult-error para um estilo de programação natural e moderno. Para obter mais informações sobre tratamento de erros e exemplos de código, consulte Tratamento de erros com oC++/WinRT.

Modificar um projeto de aplicativo da Área de Trabalho do Windows para adicionar suporte a C++/WinRT

Alguns projetos de área de trabalho (por exemplo, os modelos do WinUI 3 no Visual Studio) têm suporte interno para C++/WinRT.

Mas esta seção mostra como você pode adicionar suporte do C++/WinRT a qualquer projeto de aplicativo da Área de Trabalho do Windows que você possa ter. Se você não tiver um projeto de aplicativo da Área de Trabalho do Windows existente, poderá acompanhar estas etapas criando primeiro uma. Por exemplo, abra o Visual Studio e crie um projeto de Visual C++>Aplicativo da Área de Trabalho do Windows>.

Opcionalmente, você pode instalar o do C++/WinRT Visual Studio Extension (VSIX) e o pacote NuGet. Para obter detalhes, consulte suporte do Visual Studio paraC++/WinRT.

Definir propriedades do projeto

Vá para a propriedade do projeto Geral>Versão do SDK do Windows, e selecione Todas as Configurações e Todas as Plataformas. Verifique se versão do SDK do Windows está definida como 10.0.17134.0 (Windows 10, versão 1803) ou superior.

Confirme que você não está sendo afetado pela Por que meu novo projeto não está compilando?.

Como o C++/WinRT utiliza recursos do padrão C++17, defina a propriedade do projeto C/C++>Linguagem>Padrão de Linguagem C++ para Padrão ISO C++17 (/std:c++17).

O cabeçalho pré-compilado

O modelo de projeto padrão cria um cabeçalho pré-compilado para você, chamado framework.hou stdafx.h. Renomeie-o para pch.h. Se você tiver um arquivo stdafx.cpp, renomeie-o para pch.cpp. Defina a propriedade do projeto C/C++>Cabeçalhos Pré-Compilados>Cabeçalho Pré-Compilado para Criar (/Yc), e Arquivo de Cabeçalho Pré-Compilado para pch.h.

Localizar e substituir todos os #include "framework.h" (ou #include "stdafx.h") por #include "pch.h".

Em pch.h, inclua winrt/base.h.

// pch.h
...
#include <winrt/base.h>

Vinculação

A projeção de linguagem C++/WinRT depende de certas funções livres do Windows Runtime (não-membros) e de pontos de entrada, que exigem vinculação à biblioteca guarda-chuva WindowsApp.lib. Esta seção descreve três maneiras de satisfazer o vinculador.

A primeira opção é adicionar ao seu projeto do Visual Studio todas as propriedades e metas do MSBuild do C++/WinRT. Para fazer isso, instale o pacote NuGet Microsoft.Windows.CppWinRT em seu projeto. Abra o projeto no Visual Studio, clique em Projeto>Gerenciar Pacotes NuGet...>Procurar, digite ou cole Microsoft.Windows.CppWinRT na caixa de pesquisa, selecione o item nos resultados da pesquisa e clique em Instalar para instalar o pacote para esse projeto.

Você também pode usar as configurações de link do projeto para vincular explicitamente WindowsApp.lib. Ou, você pode fazê-lo no código-fonte (em pch.h, por exemplo) assim.

#pragma comment(lib, "windowsapp")

Agora você pode compilar, vincular e adicionar código C++/WinRT ao seu projeto (por exemplo, código semelhante ao mostrado na seção C++/WinRT quick-start, acima).

Os três principais cenários para C++/WinRT

Conforme você usa e se familiariza com o C++/WinRT e trabalha com o restante da documentação aqui, você provavelmente observará que há três cenários principais, conforme descrito nas seções a seguir.

Consumindo APIs e tipos do Windows

Em outras palavras, usandoou chamando APIs. Por exemplo, fazer chamadas à API para se comunicar usando Bluetooth; para transmitir e apresentar vídeo; para integrar com o shell do Windows; e assim por diante. O C++/WinRT dá suporte total e intransigente a essa categoria de cenário. Para obter mais informações, consulte Consumir APIs com C++/WinRT.

Criação de APIs e tipos do Windows

Em outras palavras, produzindo APIs e tipos de. Por exemplo, produzir os tipos de APIs descritos na seção acima; ou as APIs gráficas; as APIs do sistema de arquivos e armazenamento; as APIs de rede e assim por diante. Para obter mais informações, consulte Criar APIs com C++/WinRT.

A criação de APIs com C++/WinRT é um pouco mais envolvida do que consumi-las, pois você deve usar a IDL para definir a forma da API antes de poder implementá-la. Há um passo a passo para fazer isso em controles XAML. Associe a uma propriedade C++/WinRT.

Aplicativos XAML

Esse cenário é sobre a criação de aplicativos e controles na estrutura da interface do usuário XAML. Trabalhar em um aplicativo XAML equivale a uma combinação de consumo e criação. Mas como o XAML é a estrutura de interface do usuário dominante no Windows hoje, e sua influência sobre o Windows Runtime é proporcional a isso, ela merece sua própria categoria de cenário.

Lembre-se de que o XAML funciona melhor com linguagens de programação que oferecem reflexão. No C++/WinRT, às vezes você precisa fazer um trabalho extra para interoperar com a estrutura XAML. Todos esses casos são abordados na documentação. Bons lugares para começar são os controles XAML ; ligar a uma propriedade C++/WinRT e os controles personalizados XAML (modelos) com C++/WinRT.

Aplicativos de exemplo escritos em C++/WinRT

Veja Onde posso encontrar aplicações de exemplo em C++/WinRT?.

APIs importantes