Compartilhar via


Uma migração do SDK do Aplicativo Windows do aplicativo de exemplo Photo Editor da UWP (C++/WinRT)

Este tópico é um estudo de caso de como usar o aplicativo UWP de exemplo Photo Editor em C++/WinRT e migrá-lo para o SDK do Aplicativo Windows.

Importante

Para considerações e estratégias para abordar o processo de migração e como configurar seu ambiente de desenvolvimento para migração, consulte Estratégia geral de migração.

Instalar ferramentas para o SDK do Aplicativo Windows

Para configurar o ambiente de desenvolvimento, confira Instalar ferramentas para o SDK do Aplicativo Windows.

Importante

Você encontrará tópicos de notas de versão com o tópico Canais de versão do SDK do Aplicativo Windows. Há notas de versão para cada canal. Verifique as limitações e os problemas conhecidos nas notas de versão, pois eles podem afetar os resultados de acompanhar este estudo de caso e/ou executar o aplicativo migrado.

Crie um novo projeto

  • No Visual Studio, crie um projeto C++/WinRT do modelo de projeto Aplicativo em branco, empacotado (WinUI 3 na Área de Trabalho). Dê o nome PhotoEditor e demsarque a opção Colocar a solução e o projeto no mesmo diretório. Você pode ter como alvo a versão mais recente (não a versão prévia) do sistema operacional cliente.

Observação

Faremos referência à versão UWP do projeto de amostra (aquela que você clonou de seu repositório) como a solução/projeto de origem. Faremos referência à versão do SDK do Aplicativo Windows como a solução/projeto de destino.

A ordem em que migraremos o código

MainPage é uma peça importante e proeminente do aplicativo. No entanto, se fôssemos começar por essa migração, perceberíamos logo que MainPage tem uma dependência na visualização DetailPage e que DetailPage tem uma dependência no modelo Foto. Portanto, para este passo a passo, adotaremos essa abordagem.

  • Começaremos copiando os arquivos de ativos.
  • Em seguida, migraremos o modelo Foto.
  • Em seguida, migraremos a classe App (pois ela precisa de alguns membros adicionando a ela que dependerão de DetailPage e MainPage).
  • Em seguida, começaremos a migrar exibições, começando com DetailPage.
  • E terminaremos migrando a visualização MainPage.

Copiaremos arquivos de código-fonte inteiros

Nesse passo a passo, copiaremos arquivos de código-fonte usando o Explorador de Arquivos. Se você preferir copiar o conteúdo do arquivo, consulte a seção Apêndixe: como copiar o conteúdo dos arquivos do modelo Foto no final deste tópico para obter um exemplo de como poderia fazer isso no modelo Foto (e então aplicar um procedimento semelhante a outros tipos no projeto). No entanto, essa opção envolve muito mais etapas.

Copiar arquivos de ativo

  1. No clone do projeto de origem, no Explorador de Arquivos, localize a pasta Windows-appsample-photo-editor>PhotoEditor>Ativos. Você encontrará oito arquivos de ativos nessa pasta. Selecione esses oito arquivos e copie-os para a área de transferência.

  2. Também no Explorador de Arquivos, agora localize a pasta correspondente no projeto de destino que você criou. O caminho para a pasta é PhotoEditor>PhotoEditor>Ativos. Cole nessa pasta os arquivos de ativos que você acabou de copiar e aceite o prompt para substituir os sete arquivos que já existem no destino.

  3. No projeto de destino no Visual Studio, no Gerenciador de Soluções, expanda a pasta Ativos. Adicione a essa pasta o arquivo de ativo existente bg1.png que você acabou de colar. É possível passar o ponteiro do mouse sobre os arquivos de ativos. Uma visualização em miniatura será exibida para cada um, confirmando que você os substituiu/adicionou corretamente.

Migrar o Modelo de Foto

Foto é uma classe de runtime que representa uma foto. Trata-se de um modelo (no sentido de modelos, exibições e modelos de exibição).

Copiar arquivos de código-fonte de Foto

  1. No clone do projeto de origem, no Explorador de Arquivo, localize a pasta Windows-appsample-photo-editor>PhotoEditor. Nessa pasta, você encontrará os três arquivos de código-fonte de origem Photo.idl, Photo.h e Photo.cpp. Esses arquivos juntos implementam a classe de runtime Foto. Selecione esses três arquivos e copie-os para a área de transferência.

  2. No Visual Studio, clique com o botão direito do mouse no nó do projeto de destino e clique em Abrir Pasta no Explorador de Arquivos. Isso abre a pasta do projeto no Explorador de Arquivos. Cole nessa pasta os três arquivos que acabou de copiar.

  3. De volta ao Gerenciador de Soluções, com o nó do projeto selecionado, certifique-se de que a opção Mostrar Todos os Arquivos esteja ativada. Clique com o botão direito do mouse nos três arquivos copiados e clique em Incluir no Projeto. Desative a opção Mostrar Todos os Arquivos.

  4. No projeto de origem, no Gerenciador de Soluções, Photo.h e .cpp estão aninhados em Photo.idl para indicar que são gerados a partir dele (sendo dependente dele). Se gostar dessa organização, você poderá fazer a mesma coisa no projeto de destino editando manualmente \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj (primeiro você precisará Salvar Tudo no Visual Studio). Localize o seguinte:

    <ClInclude Include="Photo.h" />
    

    Em seguida, substitua-o por:

    <ClInclude Include="Photo.h">
      <DependentUpon>Photo.idl</DependentUpon>
    </ClInclude>
    

    Repita o processo para Photo.cpp e salve e feche o arquivo de projeto. Quando você definir o foco de volta para o Visual Studio, clique em Recarregar.

Migrar o código-fonte de Foto

  1. Em Photo.idl, pesquise o nome do namespace Windows.UI.Xaml (que é o namespace para UWP XAML) e altere-o para Microsoft.UI.Xaml (que é o namespace para WinUI XAML).

Observação

O tópico Mapeando APIs UWP para o SDK do Aplicativo Windows fornece um mapeamento de APIs UWP para seus equivalentes no SDK do Aplicativo Windows. A alteração que fizemos acima é um exemplo de alteração em nome de namespace necessária durante o processo de migração.

  1. Em Photo.cpp, adicione #include "Photo.g.cpp" às diretivas de inclusão existentes, imediatamente após #include "Photo.h". Essa é uma das diferenças de nome de pasta e arquivo (C++/WinRT) a estar ciente entre os projetos de UWP e SDK do Aplicativo Windows.

  2. Faça a seguinte localização/substituição (correspondência entre maiúsculas e minúsculas e palavra inteira) no conteúdo de todo o código-fonte nos arquivos que você acabou de copiar e colar.

    • Windows::UI::Xaml =>Microsoft::UI::Xaml
  3. Em pch.h no projeto de origem, copie as seguintes inclusões e cole-as em pch.h no projeto de destino. Esse é um subconjunto dos arquivos de cabeçalho incluídos no projeto de origem. Eles são apenas os cabeçalhos de que precisamos para dar suporte ao código que migramos até agora.

    #include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
    #include <winrt/Windows.Storage.h>
    #include <winrt/Windows.Storage.FileProperties.h>
    #include <winrt/Windows.Storage.Streams.h>
    
  4. Agora, confirme que você pode criar a solução de destino (mas não a execute ainda).

Migrar a classe App

Nenhuma alteração é necessária para o App.idl e o App.xaml do projeto de destino. Porém, precisamos editar App.xaml.h e Aplicativo.xaml.cpp para adicionar alguns novos membros à classe Aplicativo. Faremos isso de uma forma que nos permita compilar após cada seção (com exceção da última seção, que envolve App::OnLaunched).

Disponibilização do objeto da janela principal

Nessa etapa, faremos a alteração explicada em Alterar Windows.UI.Xaml.Window.Current para App.Window.

No projeto de destino, Aplicativo armazena o objeto da janela principal na janela de membro de dados privados. Mais tarde, no processo de migração (quando migramos o uso de Window.Current pelo projeto de origem), será conveniente se o membro de dados da janela for estático. Isso também é permitido por meio de uma função de acessador. Em seguida, faremos as mudanças a seguir.

  • Como estamos tornando a janela estática, precisaremos inicializá-la em App.xaml.cpp em vez de por meio do inicializador de membro padrão que o código está usando no momento. Veja como são essas mudanças em App.xaml.h e App.xaml.cpp.

    // App.xaml.h
    ...
    struct App : AppT<App>
    {
         ...
         static winrt::Microsoft::UI::Xaml::Window Window(){ return window; };
    
    private:
         static winrt::Microsoft::UI::Xaml::Window window;
    };
    ...
    
    // App.xaml.cpp
    ...
    winrt::Microsoft::UI::Xaml::Window App::window{ nullptr };
    ...
    

App::OnNavigationFailed

O aplicativo de exemplo Photo Editor usa a lógica de navegação para navegar entre MainPage e DetailPage. Para saber mais sobre aplicativos do SDK do Aplicativo Windows que precisam de navegação (e os que não precisam), consulte Preciso implementar a navegação de página?.

Assim, os membros que migraremos nas próximas seções existem para dar suporte à navegação dentro do aplicativo.

  1. Vamos começar migrando o manipulador de eventos OnNavigationFailed. Copie a declaração e a definição dessa função de membro do projeto de origem e cole-a no projeto de destino (em App.xaml.h e App.xaml.cpp).

  2. No código colado em App.xaml.h, altere Windows::UI::Xaml para Microsoft::UI::Xaml.

App::CreateRootFrame

  1. O projeto de origem contém uma função auxiliar chamada App::CreateRootFrame. Copie a declaração e a definição dessa função auxiliar do projeto de origem e cole-a no projeto de destino (em App.xaml.h e App.xaml.cpp).

  2. No código colado em App.xaml.h, altere Windows::UI::Xaml para Microsoft::UI::Xaml.

  3. No código que você colou em App.xaml.cpp, altere as duas ocorrências de Window::Current() para window (que é o nome do membro de dados da classe Aplicativo que vimos anteriormente).

App::OnLaunched

O projeto de destino já contém uma implementação do manipulador de eventos OnLaunched. Seu parâmetro é uma referência constante a um Microsoft::UI::Xaml::LaunchActivatedEventArgs, que é a correta para o SDK do Aplicativo Windows (em contraposição ao projeto de origem, que usa Windows::ApplicationModel::Activation::LaunchActivatedEventArgs, que é a opção correta para UWP).

  • Só precisamos mesclar as duas definições (origem e destino) de OnLaunched para que App::OnLaunched no App.xaml.cpp no projeto de destino fique como a listagem abaixo. Observe que ele usa window (em vez de Window::Current(), como a versão UWP faz).

    void App::OnLaunched(LaunchActivatedEventArgs const&)
    {
         window = make<MainWindow>();
    
         Frame rootFrame = CreateRootFrame();
         if (!rootFrame.Content())
         {
             rootFrame.Navigate(xaml_typename<PhotoEditor::MainPage>());
         }
    
         window.Activate();
    }
    

O código acima oferece a Aplicativo uma dependência em MainPage, então não conseguiremos compilar a partir desse ponto até migrarmos DetailPage e MainPage. Quando for possível compilar novamente, avisaremos.

Migrar o modo de exibição de DetailPage

DetailPage é a classe que representa a página do editor de fotos, na qual efeitos Win2D são alternados, definidos e encadeados. Você acessa a página do editor de fotos selecionando uma miniatura de foto em MainPage. DetailPage é uma exibição (no sendo de modelos, exibições e modelos de exibição).

Referenciar o pacote NuGet Win2D

Para oferecer suporte ao código em DetailPage, o projeto de origem tem uma dependência em Microsoft.Graphics.Win2D. Por isso, também precisaremos de uma dependência por Win2D em nosso projeto de destino.

  • Na solução de destino no Visual Studio, clique em Ferramentas>Gerenciador de Pacotes do NuGet>Gerenciar Pacotes do NuGet para solução...>Procurar. Verifique se a opção Incluir pré-lançamento está desmarcada e digite ou cole Microsoft.Graphics.Win2D na caixa de pesquisa. Selecione o item correto nos resultados da pesquisa, verifique o projeto PhotoEditor e clique em Instalar para instalar o pacote.

Copiar arquivos de código-fonte de DetailPage

  1. No clone do projeto de origem, no Explorador de Arquivo, localize a pasta Windows-appsample-photo-editor>PhotoEditor. Nessa pasta, você encontrará os quatro arquivos de código-fonte DetailPage.idl, DetailPage.xaml, DetailPage.h e DetailPage.cpp. Juntos, eles implementam a exibição DetailPage. Selecione esses quatro arquivos e copie-os para a área de transferência.

  2. No Visual Studio, clique com o botão direito do mouse no nó do projeto de destino e clique em Abrir Pasta no Explorador de Arquivos. Isso abre a pasta do projeto no Explorador de Arquivos. Cole nessa pasta os quatro arquivos que acabou de copiar.

  3. Ainda no Explorador de Arquivos, altere os nomes de DetailPage.h e DetailPage.cpp para DetailPage.xaml.h e DetailPage.xaml.cpp, respectivamente. Essa é uma das diferenças de nome de pasta e arquivo (C++/WinRT) a estar ciente entre os projetos de UWP e SDK do Aplicativo Windows.

  4. De volta ao Gerenciador de Soluções, com o nó do projeto selecionado, certifique-se de que a opção Mostrar Todos os Arquivos esteja ativada. Clique com o botão direito do mouse nos quatro arquivos que você acabou de colar (e renomear) e clique em Incluir no Projeto. Desative a opção Mostrar Todos os Arquivos.

  5. No projeto de origem, no Gerenciador de Soluções, DetailPage.idl está aninhado em DetailPage.xaml. Se gostar dessa organização, você poderá fazer a mesma coisa no projeto de destino editando manualmente \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj (primeiro você precisará Salvar Tudo no Visual Studio). Localize o seguinte:

    <Midl Include="DetailPage.idl" />
    

    Em seguida, substitua-o por:

    <Midl Include="DetailPage.idl">
      <DependentUpon>DetailPage.xaml</DependentUpon>
    </Midl>
    

Salve e feche o arquivo de projeto. Quando você definir o foco de volta para o Visual Studio, clique em Recarregar.

Migrar o código-fonte de DetailPage

  1. No DetailPage.idl, pesquise Windows.UI.Xaml, e altere para Microsoft.UI.Xaml.

  2. Em DetailPage.xaml.cpp, altere #include "DetailPage.h" para #include "DetailPage.xaml.h".

  3. Logo abaixo, adicione #include "DetailPage.g.cpp".

  4. Para que a chamada compile o método App::Window (que estamos prestes a adicionar), ainda em DetailPage.xaml.cpp, adicione #include "App.xaml.h" imediatamente antes de #include "Photo.h".

  5. Faça as seguintes localizações/substituições (correspondência entre maiúsculas e minúsculas e palavra inteira) no conteúdo do código-fonte nos arquivos que você acabou de copiar e colar.

    • Em DetailPage.xaml.h e .xaml.cpp, Windows::UI::Composition =>Microsoft::UI::Composition
    • Em DetailPage.xaml.h e .xaml.cpp, Windows::UI::Xaml =>Microsoft::UI::Xaml
    • Em DetailPage.xaml.cpp, Window::Current() =>App::Window()
  6. Em pch.h no projeto de origem, copie as seguintes inclusões e cole-as em pch.h no projeto de destino.

    #include <winrt/Windows.Graphics.Effects.h>
    #include <winrt/Microsoft.Graphics.Canvas.Effects.h>
    #include <winrt/Microsoft.Graphics.Canvas.UI.Xaml.h>
    #include <winrt/Microsoft.UI.Composition.h>
    #include <winrt/Microsoft.UI.Xaml.Input.h>
    #include <winrt/Windows.Graphics.Imaging.h>
    #include <winrt/Windows.Storage.Pickers.h>
    
  7. Além disso, na parte superior de pch.h, imediatamente após #pragma once, adicione:

    // This is required because we are using std::min and std::max, otherwise 
    // we have a collision with min and max macros being defined elsewhere.
    #define NOMINMAX
    

Ainda não podemos compilar, mas poderemos depois de migrar MainPage (que é a próxima).

Migrar o modo de exibição MainPage

A página principal do aplicativo representa a exibição que você vê primeiro quando executa o aplicativo. É a página que carrega as fotos da Biblioteca de Imagens e mostra uma exibição em miniatura lado a lado.

Copiar arquivos de código-fonte de MainPage

  1. De modo semelhante ao que você fez com DetailPage, agora copie MainPage.idl, MainPage.xaml, MainPage.h e MainPage.cpp.

  2. Renomeie os arquivos .h e .cpp como .xaml.h e .xaml.cpp, respectivamente.

  3. Inclua todos os quatro arquivos no projeto de destino como antes.

  4. No projeto de origem, no Gerenciador de Soluções, MainPage.idl está aninhado em MainPage.xaml. Se você gosta dessa organização, então pode fazer a mesma coisa no projeto de destino editando \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj manualmente. Localize o seguinte:

    <Midl Include="MainPage.idl" />
    

    E substitua por:

    <Midl Include="MainPage.idl">
      <DependentUpon>MainPage.xaml</DependentUpon>
    </Midl>
    

Migrar o código-fonte de MainPage

  1. Em MainPage.idl, pesquise Windows.UI.Xaml, e altere ambas as ocorrências para Microsoft.UI.Xaml.

  2. Em MainPage.xaml.cpp, altere #include "MainPage.h" para #include "MainPage.xaml.h".

  3. Logo abaixo, adicione #include "MainPage.g.cpp".

  4. Para que a chamada compile o método App::Window (que estamos prestes a adicionar), ainda em MainPage.xaml.cpp, adicione #include "App.xaml.h" imediatamente antes de #include "Photo.h".

Para a próxima etapa, faremos a alteração explicada em ContentDialog e Popup.

  1. Então, ainda em MainPage.xaml.cpp, no método MainPage::GetItemsAsync, imediatamente após a linha ContentDialog unsupportedFilesDialog{};, adicione a linha de código.

    unsupportedFilesDialog.XamlRoot(this->Content().XamlRoot());
    
  2. Faça as seguintes localizações/substituições (correspondência entre maiúsculas e minúsculas e palavra inteira) no conteúdo do código-fonte nos arquivos que você acabou de copiar e colar.

    • Em MainPage.xaml.h e .xaml.cpp, Windows::UI::Composition =>Microsoft::UI::Composition
    • Em MainPage.xaml.h e .xaml.cpp, Windows::UI::Xaml =>Microsoft::UI::Xaml
    • Em MainPage.xaml.cpp, Window::Current() =>App::Window()
  3. Em pch.h no projeto de origem, copie as seguintes inclusões e cole-as em pch.h no projeto de destino.

    #include <winrt/Microsoft.UI.Xaml.Hosting.h>
    #include <winrt/Microsoft.UI.Xaml.Media.Animation.h>
    #include <winrt/Windows.Storage.Search.h>
    

Confirme que você pode criar a solução de destino (mas não a execute ainda).

Atualizar MainWindow

  1. Em MainWindow.xaml, exclua StackPanel e seu conteúdo, pois não precisamos de uma interface de usuário na MainWindow. Isso deixa apenas o elemento Window vazio.

  2. Em MainWindow.idl, exclua o espaço reservado Int32 MyProperty;, deixando somente o construtor.

  3. Em MainWindow.xaml.h e MainWindow.xaml.cpp, exclua as declarações e definições do espaço reservado MyProperty e myButton_Click, deixando somente o construtor.

Alterações de migração necessárias para a diferença de modelo de threading

As duas alterações nesta seção são necessárias devido a uma diferença de modelo de threading entre a UWP e o SDK do Aplicativo Windows, conforme descrito no modelo de threading ASTA para STA. Veja breves descrições das causas dos problemas e, em seguida, uma maneira de resolver cada um.

MainPage

O MainPage carrega arquivos de imagem da pasta Imagens, chama StorageItemContentProperties.GetImagePropertiesAsync para obter as propriedades do arquivo de imagem, cria um objeto de modelo Foto para cada arquivo de imagem (salvando as mesmas propriedades em um membro de dados) e adiciona esse objeto Foto a uma coleção. A coleção de objetos Foto é vinculada a dados a um GridView na interface do usuário. Em nome do GridView, MainPage processa o evento ContainerContentChanging e, para a fase 1 que o manipulador chama em uma corrotina que chama StorageFile.GetThumbnailAsync. Essa chamada para GetThumbnailAsync resulta em mensagens sendo bombeadas (ela não retorna imediatamente e faz todo o trabalho assíncrono), causando reentrância. O resultado é que o GridView tem sua coleção de Itens alterada, embora o layout ocorra, e isso causa uma falha.

Se comentarmos a chamada de StorageItemContentProperties::GetImagePropertiesAsync, não obteremos a falha. Mas a correção real é fazer com que a chamada StorageFile.GetThumbnailAsync seja explicitamente assíncrona, aguardando cooperativamente wil::resume_foreground logo antes de chamar GetThumbnailAsync. Isso funciona porque wil::resume_foreground programa o código que o segue como a tarefa no DispatcherQueue.

Aqui está o código a ser alterado:

// MainPage.xaml.cpp
IAsyncAction MainPage::OnContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
    ...
    if (args.Phase() == 1)
    {
        ...
        try
        {
            co_await wil::resume_foreground(this->DispatcherQueue());
            auto thumbnail = co_await impleType->GetImageThumbnailAsync(this->DispatcherQueue());
            image.Source(thumbnail);
        }
        ...
    }
}

Foto

A propriedade Photo::ImageTitle é vinculada a dados à interface do usuário, então a interface do usuário chama a função do acessador para a propriedade sempre que precisa de um valor. Mas quando tentamos acessar ImageProperties.Title a partir dessa função de acessador no thread da interface do usuário, obtemos uma violação de acesso.

Então, em vez disso, podemos simplesmente acessar esse Título uma vez, a partir do construtor de Foto, e armazená-lo no membro de dados m_imageName caso não esteja vazio. Em seguida, na função de acessador Photo::ImageTitle, precisamos somente acessar o membro de dados m_imageName.

Aqui está o código a ser alterado:

// Photo.h
...
Photo(Photo(Windows::Storage::FileProperties::ImageProperties const& props,
    ...
    ) : ...
{
    if (m_imageProperties.Title() != L"")
    {
        m_imageName = m_imageProperties.Title();
    }
}
...
hstring ImageTitle() const
{
    return m_imageName;
}
...

Essas são as últimas alterações que precisamos fazer para migrar o aplicativo de exemplo Photo Editor. Na seção Teste o aplicativo migrado, confirmaremos que seguimos as etapas corretamente.

Problemas conhecidos

Problema de tipo de aplicativo (afeta apenas Preview 3)

Se você acompanhou o estudo de caso usando o modelo de projeto do VSIX para SDK do Aplicativo Windows versão 1.0 Preview 3, será necessário fazer uma pequena correção no PhotoEditor.vcxproj. Veja a seguir como fazer isso.

No Visual Studio, no Gerenciador de Soluções, clique com o botão direito do mouse no nó do projeto e clique em Descarregar Projeto. Agora PhotoEditor.vcxproj está aberto para edição. Como o primeiro filho do Projeto, adicione um elemento PropertyGroup como este:

<Project ... >
    <PropertyGroup>
        <EnableWin32Codegen>true</EnableWin32Codegen>
    </PropertyGroup>
    <Import ... />
...

Salve e feche PhotoEditor.vcxproj. Clique com o botão direito do mouse no nó do projeto e clique em Recarregar Projeto. Agora recompile o projeto.

Testar o aplicativo migrado

Agora, crie o projeto e execute o aplicativo para testá-lo. Selecione uma imagem, defina um nível de zoom, escolha efeitos e configure-os.

Apêndice: copiar o conteúdo dos arquivos do modelo de Foto

Como discutimos anteriormente, você tem a opção de copiar os próprios arquivos de código-fonte ou o conteúdo desses arquivos. Já mostramos como copiar os próprios arquivos de código-fonte. Portanto, esta seção dá um exemplo de como copiar o conteúdo do arquivo.

No projeto de origem no Visual Studio, localize a pasta PhotoEditor (Universal Windows)>Models. Essa pasta contém os arquivos Photo.idl, Photo.h e Photo.cpp, que, juntos, implementam a classe runtime Foto.

Adicione o IDL e gere stubs

No projeto de destino no Visual Studio, adicione um novo item Midl File (.idl) ao projeto. Dê ao novo item o nome Photo.idl. Exclua o conteúdo padrão de Photo.idl.

No projeto de origem no Visual Studio, copie o conteúdo de Modelos>Photo.idl e cole-o no arquivo Photo.idl que você acabou de adicionar ao projeto de destino. No código que você colou, procure Windows.UI.Xaml e altere-o para Microsoft.UI.Xaml.

Salve o arquivo.

Importante

Estamos prestes a executar uma compilação da solução de destino. A compilação não será concluída neste momento, mas chegará longe o suficiente para fazer o trabalho necessário para nós.

Agora compile a solução de destino. Mesmo que não seja concluída, a compilação será necessária agora porque gerará os arquivos de código-fonte (stubs) de que precisamos para começar a implementar o modelo Foto.

No Visual Studio, clique com o botão direito do mouse no nó do projeto de destino e clique em Abrir Pasta no Explorador de Arquivos. Isso abre a pasta do projeto no Explorador de Arquivos. Nesse ponto, navegue até a Generated Files\sources pasta (para que você esteja em \PhotoEditor\PhotoEditor\PhotoEditor\Generated Files\sources). Copie os arquivos stub Photo.h e .cpp e cole-os na pasta do projeto, que agora está a dois níveis de pasta acima em \PhotoEditor\PhotoEditor\PhotoEditor.

De volta ao Gerenciador de Soluções, com o nó do projeto selecionado, certifique-se de que a opção Mostrar Todos os Arquivos esteja ativada. Clique com o botão direito do mouse nos arquivos de stub que acabou de colar (Photo.h e .cpp) e clique em Incluir no Projeto. Desative a opção Mostrar Todos os Arquivos.

Você verá um static_assert na parte superior do conteúdo de Photo.h e .cpp, que você precisará excluir.

Confirme se você pode compilar novamente (mas ainda não pode executar).

Migrar o código para os stubs

Copie o conteúdo de Photo.h e .cpp do projeto de origem para o projeto de destino.

A partir daqui, as etapas restantes para migrar o código que você copiou serão as mesmas fornecidas na seção Migrar código-fonte de Foto.