Partilhar via


Introdução ao C++/WinRT

Importante

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

Para você se familiarizar com o uso doC++/WinRT , este tópico percorre um exemplo de código simples baseado em um novo projeto Aplicativo de Console do Windows (C++/WinRT) do . Este tópico também mostra como adicionar suporte a C++/WinRT a um projeto de aplicação da área de trabalho do Windows.

Observação

Embora seja recomendável que você desenvolva 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 pode falhar ao compilar com o erro "erro C3861: 'from_abi': identificador não encontrado" e com outros erros originários de base.h. A solução é direcionar uma versão posterior (mais conforme) do SDK do Windows, ou definir a propriedade do projeto C/C++>Language>Modo de Conformidade: Não (também, se /permissive- aparecer na propriedade do projeto C/C++>Language>Command Line em Opções Adicionais, apague-o).

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

Crie um novo projeto de aplicação de consola do Windows (C++/WinRT), .

Edite pch.h e main.cpp tenha 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 pegar o pequeno exemplo de código 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 padrão do projeto, 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á dependência estrita do SDK do Windows, porque seu projeto (por meio da cppwinrt.exe ferramenta) gera esses mesmos cabeçalhos na pasta $(GeneratedFilesDir) do 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 de Windows, C++/WinRT define um equivalente amigável ao C++ (chamado de tipo projetado). Um tipo projetado tem o mesmo nome totalmente qualificado que o tipo do Windows, mas é colocado no namespace Winrt C++. Colocar essas inclusões em seu cabeçalho pré-compilado reduz os tempos de compilação incrementais.

Importante

Sempre que quiser usar um tipo de namespaces do Windows, você deve #include o arquivo de cabeçalho de namespace do Windows C++/WinRT correspondente, conforme mostrado acima. O cabeçalho correspondente é aquele que tem o mesmo nome que o namespace do tipo. Por exemplo, para usar a projeção C++/WinRT para a classe de tempo de execução 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 com o tempo. Você deve incluir explicitamente todos os cabeçalhos necessários.

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

As using namespace diretivas são facultativas, mas convenientes. O padrão mostrado acima para essas diretivas (permitindo a pesquisa de nome não qualificado para qualquer coisa no winrt namespace) é adequado para quando você está começando 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++/CX e/ou código de interface binária de aplicativo (ABI) SDK (você está portando ou interoperando com, um ou ambos os modelos), consulte os tópicos Interoperabilidade entre C++/WinRT e C++/CX, Mover para C++/WinRT de C++/CX, e Interoperabilidade entre C++/WinRT e oABI.

winrt::init_apartment();

A chamada para winrt::init_apartment inicializa o tópico no Windows Runtime; por padrão, num apartamento multi-fios. A chamada também inicializa COM.

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

Alocar dois objetos na pilha: eles representam o URI do blog do Windows e um cliente de sindicância. Construímos o uri com um literal de cadeia de caracteres larga simples (consulte Tratamento de cadeias 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 Tempo de Execução do Windows. O exemplo de código recebe um objeto de operação assíncrona de RetrieveFeedAsynce chama obter nesse objeto para bloquear o thread de chamada e aguardar o resultado (que é um feed de distribuição, neste caso). Para obter mais informações sobre simultaneidade e técnicas sem bloqueio, consulte Simultaneidade e operações assíncronas com C++/WinRT.

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

SyndicationFeed.Items é um intervalo, definido pelos iteradores retornados das funções de início e de final (ou das suas variantes constante, reversa e constante-reversa). Por isso, pode enumerar Itens com uma instrução baseada em intervalo for ou com a função modelo std::for_each. Sempre que iterar sobre uma coleção do Tempo de Execução do Windows como esta, você 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 em manipulação de string em C++/WinRT). O hstring é então produzido, através da função c_str, que reflete o padrão usado com cadeias de caracteres da Biblioteca Standard C++.

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

Também não é necessário lidar com códigos de retorno HRESULT. 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 C++/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 WinUI 3 no Visual Studio) têm suporte a C++/WinRT integrado.

Mas esta seção mostra como você pode adicionar suporte a 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 de área de trabalho do Windows existente, poderá seguir essas etapas criando primeiro um. Por exemplo, abra o Visual Studio e crie um projeto Visual C++>de Aplicação de Ambiente de Trabalho do Windows>.

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

Definir propriedades do projeto

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

Assegure-se de que não está a ser afetado por Por que é que o meu novo projeto não compila?.

Como o C++/WinRT usa recursos do padrão C++17, defina a propriedade do projeto C/C++>Language>C++ Language Standard como ISO C++17 Standard (/std:c++17).

O cabeçalho pré-compilado

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

Localize e substitua tudo #include "framework.h" (ou #include "stdafx.h") por #include "pch.h".

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

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

Ligação

A projeção da linguagem C++/WinRT depende de determinadas funções livres (não membros) do Tempo de Execução do Windows e 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 destinos do MSBuild C++/WinRT. Para fazer isso, instale o pacote NuGet Microsoft.Windows.CppWinRT em seu projeto. Abra o projeto no Visual Studio, clique em Project>Manage NuGet Packages...>Navegue, 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 em código-fonte (em pch.h, por exemplo) como este.

#pragma comment(lib, "windowsapp")

Agora você pode compilar e vincular e adicionar código C++/WinRT ao seu projeto (por exemplo, código semelhante ao mostrado na seção de início rápido A C++/WinRT , acima).

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

À medida que você usa e se familiariza com C++/WinRT e trabalha com o restante da documentação aqui, provavelmente notará 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 as APIs. Por exemplo, fazer chamadas de API para se comunicar usando Bluetooth; para transmitir e apresentar vídeo; para integrar com o shell do Windows; e assim por diante. C++/WinRT suporta total e intransigentemente esta categoria de cenário. Para obter mais informações, consulte Utilizar APIs com C++/WinRT.

Criação de APIs e tipos do Windows

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

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

Aplicativos XAML

Este cenário trata da 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 atualmente e sua influência sobre o Tempo de Execução do Windows é proporcional a isso, ele 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. Em C++/WinRT, às vezes você precisa fazer um pouco de trabalho extra para interoperar com a estrutura XAML. Todos esses casos são cobertos pela documentação. Bons lugares para começar são controles XAML; vincular a uma propriedade C++/WinRT e controles personalizados (modelos) XAML com C++/WinRT.

Aplicativos de exemplo escritos em C++/WinRT

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

APIs importantes