Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Importante
Este tópico usa ou menciona tipos do repositório CommunityToolkit/Microsoft.Toolkit.Win32 GitHub. Para obter informações importantes sobre o suporte às Ilhas XAML UWP, consulte o Aviso sobre XAML Islands nesse repositório.
Este artigo demonstra como usar a API de hospedagem XAML UWP para hospedar um controle XAML UWP padrão (ou seja, um controle fornecido pelo SDK Windows) em um novo aplicativo de área de trabalho C++. O código baseia-se no exemplo simple XAML Island e esta seção discute algumas das partes mais importantes do código. Se você tiver um projeto de aplicativo para desktop em C++ existente, poderá adaptar essas etapas e exemplos de código para seu projeto.
Observação
O cenário demonstrado neste artigo não dá suporte à edição direta da marcação XAML para controles XAML UWP hospedados em seu aplicativo. Esse cenário impede você de modificar a aparência e o comportamento de controles hospedados por meio de código. Para obter instruções que permitem editar diretamente a marcação XAML ao hospedar controles XAML UWP, consulte Hospedar um controle XAML UWP personalizado em um aplicativo de área de trabalho C++.
Criar um projeto de aplicativo de desktop
No Visual Studio 2019 com o Windows 10, versão 1903 SDK (build 10.0.18362) ou uma versão posterior instalada, crie um novo Windows Desktop Application project e nomeie-o MyDesktopWin32App. Este tipo de projeto está disponível nos filtros de projeto C++, Windows e Desktop.
Em Gerenciador de Soluções, Clique com o botão direito do mouse no nó da solução, clique em Retarget solution, selecione o 10.0.18362.0 ou uma versão posterior do SDK e clique em OK.
Instale o pacote NuGet Microsoft.Windows.CppWinRT para habilitar o suporte para C++/WinRT em seu project:
- Clique com o botão direito do mouse no projeto em Gerenciador de Soluções e escolha Gerenciar Pacotes NuGet.
- Selecione a guia Procurar, procure o pacote Microsoft.Windows.CppWinRT e instale a última versão desse pacote.
Observação
Para novos projetos, você pode, como alternativa, instalar o C++/WinRT Visual Studio Extension (VSIX) e usar um dos modelos de project C++/WinRT incluídos nessa extensão. Para obter mais detalhes, consulte Visual Studio suporte para C++/WinRT e o VSIX.
Na guia Browse da janela NuGet Gerenciador de Pacotes, pesquise o pacote NuGet Microsoft.Toolkit.Win32.UI.SDK e instale a versão estável mais recente. Esse pacote fornece vários ativos de build e tempo de execução que permitem que as XAML Islands do UWP operem corretamente em seu aplicativo.
Defina o valor
maxversiontestedno manifesto application para especificar que seu aplicativo é compatível com Windows 10, versão 1903.Se você ainda não tiver um manifesto do aplicativo em seu project, adicione um novo arquivo XML ao seu project e nomeie-o app.manifest.
No manifesto do aplicativo, inclua o elemento compatibility e os elementos filho mostrados no exemplo a seguir. Substitua o atributo ID do elemento maxversiontested pelo número de versão do Windows que você está direcionando (a versão deverá ser 10.0.18362.0 ou posterior). Observe que definir um valor mais alto significa que as versões anteriores do Windows não executarão o aplicativo de modo correto porque cada versão do Windows reconhece somente as versões anteriores. Se quiser que o aplicativo seja executado no Windows 10, versão 1903 (build 10.0.18362), você deve deixar o valor 10.0.18362.0 como está ou adicionar vários elementos maxversiontested para os diferentes valores aos quais o aplicativo dá suporte.
<?xml version="1.0" encoding="UTF-8"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- Windows 10 --> <maxversiontested Id="10.0.18362.0"/> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> </application> </compatibility> </assembly>
Adicione uma referência aos metadados do Windows Runtime:
- Em Gerenciador de Soluções, clique com o botão direito do mouse no nó Referências do projeto e selecione Adicionar Referência.
- Clique no botão Procurar na parte inferior da página e navegue até a pasta UnionMetadata no caminho de instalação do SDK. Por padrão, o SDK será instalado em
C:\Program Files (x86)\Windows Kits\10\UnionMetadata. - Depois, selecione a pasta nomeada com a versão do Windows que você está visando (por exemplo, 10.0.18362.0) e, dentro dessa pasta, escolha o arquivo
Windows.winmd. - Clique em OK para fechar a caixa de diálogo Adicionar Referência.
Usar a API de hospedagem XAML para hospedar um controle XAML UWP
O processo básico de usar a API de hospedagem XAML para hospedar um controle XAML UWP segue estas etapas gerais:
Inicialize a estrutura XAML UWP para o thread atual antes que seu aplicativo crie qualquer um dos Windows. UI. Xaml.UIElement objetos que ele hospedará. Há várias maneiras de fazer isso, dependendo de quando você planeja criar o objeto DesktopWindowXamlSource que hospedará os controles.
Se o aplicativo criar o objeto DesktopWindowXamlSource antes de criar um dos objetos Windows.UI.Xaml.UIElement que ele hospedará, essa estrutura será inicializada para você ao criar uma instância do objeto DesktopWindowXamlSource. Nesse cenário, você não precisa adicionar nenhum código próprio para inicializar a estrutura.
No entanto, se o aplicativo criar os objetos Windows.UI.Xaml.UIElement antes de criar o objeto DesktopWindowXamlSource que os hospedará, seu aplicativo deve chamar o método estático WindowsXamlManager.InitializeForCurrentThread para inicializar explicitamente o framework XAML UWP antes que os objetos Windows.UI.Xaml.UIElement sejam instanciados. Seu aplicativo normalmente deverá chamar esse método quando for criada uma instância do elemento pai da interface do usuário que hospeda o DesktopWindowXamlSource.
Observação
Esse método retorna um objeto WindowsXamlManager que contém uma referência à estrutura XAML UWP. Você pode criar quantos objetos WindowsXamlManager desejar em determinado thread. No entanto, como cada objeto contém uma referência à estrutura XAML UWP, você deve descartar os objetos para garantir que os recursos XAML sejam finalmente liberados.
Crie um objeto DesktopWindowXamlSource e anexe-o a um elemento pai da interface do usuário no aplicativo associado a um identificador de janela.
Para fazer isso, você precisará seguir estas etapas:
Crie um objeto DesktopWindowXamlSource e converta-o na interface COM IDesktopWindowXamlSourceNative ou IDesktopWindowXamlSourceNative2.
Chame o método AttachToWindow da interface IDesktopWindowXamlSourceNative ou IDesktopWindowXamlSourceNative2 e transmita o identificador de janela do elemento pai da interface do usuário no aplicativo.
Importante
Verifique se seu código chama o método AttachToWindow apenas uma vez por objeto DesktopWindowXamlSource. Chamar esse método mais de uma vez para um objeto DesktopWindowXamlSource pode resultar em perda de memória.
Defina o tamanho inicial da janela interna filha contida no DesktopWindowXamlSource. Por padrão, essa subjanela interna é definida com uma largura e uma altura de 0. Se você não definir o tamanho da janela, os controles XAML UWP adicionados ao DesktopWindowXamlSource não estarão visíveis. Para acessar a janela filha interna no DesktopWindowXamlSource, use a propriedade WindowHandle da interface IDesktopWindowXamlSourceNative ou IDesktopWindowXamlSourceNative2.
Por fim, atribua o Windows.UI.Xaml.UIElement que deseja hospedar à propriedade Conteúdo do objeto DesktopWindowXamlSource.
As seguintes etapas e exemplos de código demonstram como to do implementar o processo acima:
Na pasta Source Files do project, abra o arquivo MyDesktopWin32App.cpp padrão. Exclua todo o conteúdo do arquivo e adicione as instruções
includeeusinga seguir. Além dos cabeçalhos e namespaces C++ e UWP padrão, essas instruções incluem vários itens específicos para ilhas XAML UWP.#include <windows.h> #include <stdlib.h> #include <string.h> #include <winrt/Windows.Foundation.Collections.h> #include <winrt/Windows.system.h> #include <winrt/windows.ui.xaml.hosting.h> #include <windows.ui.xaml.hosting.desktopwindowxamlsource.h> #include <winrt/windows.ui.xaml.controls.h> #include <winrt/Windows.ui.xaml.media.h> using namespace winrt; using namespace Windows::UI; using namespace Windows::UI::Composition; using namespace Windows::UI::Xaml::Hosting; using namespace Windows::Foundation::Numerics;Copie o código a seguir após a seção anterior. Esse código define a função WinMain para o aplicativo. Essa função inicializa uma janela básica e usa a API de Hospedagem XAML para hospedar um controle UWP simples TextBlock na janela.
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); HWND _hWnd; HWND _childhWnd; HINSTANCE _hInstance; int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) { _hInstance = hInstance; // The main window class name. const wchar_t szWindowClass[] = L"Win32DesktopApp"; WNDCLASSEX windowClass = { }; windowClass.cbSize = sizeof(WNDCLASSEX); windowClass.lpfnWndProc = WindowProc; windowClass.hInstance = hInstance; windowClass.lpszClassName = szWindowClass; windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); windowClass.hIconSm = LoadIcon(windowClass.hInstance, IDI_APPLICATION); if (RegisterClassEx(&windowClass) == NULL) { MessageBox(NULL, L"Windows registration failed!", L"Error", NULL); return 0; } _hWnd = CreateWindow( szWindowClass, L"Windows c++ Win32 Desktop App", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); if (_hWnd == NULL) { MessageBox(NULL, L"Call to CreateWindow failed!", L"Error", NULL); return 0; } // Begin XAML Island section. // The call to winrt::init_apartment initializes COM; by default, in a multithreaded apartment. winrt::init_apartment(apartment_type::single_threaded); // Initialize the XAML framework's core window for the current thread. WindowsXamlManager winxamlmanager = WindowsXamlManager::InitializeForCurrentThread(); // This DesktopWindowXamlSource is the object that enables a non-UWP desktop application // to host UWP XAML controls in any UI element that is associated with a window handle (HWND). DesktopWindowXamlSource desktopSource; // Get handle to the core window. auto interop = desktopSource.as<IDesktopWindowXamlSourceNative>(); // Parent the DesktopWindowXamlSource object to the current window. check_hresult(interop->AttachToWindow(_hWnd)); // This HWND will be the window handler for the XAML Island: A child window that contains XAML. HWND hWndXamlIsland = nullptr; // Get the new child window's HWND. interop->get_WindowHandle(&hWndXamlIsland); // Update the XAML Island window size because initially it is 0,0. SetWindowPos(hWndXamlIsland, 0, 200, 100, 800, 200, SWP_SHOWWINDOW); // Create the XAML content. Windows::UI::Xaml::Controls::StackPanel xamlContainer; xamlContainer.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() }); Windows::UI::Xaml::Controls::TextBlock tb; tb.Text(L"Hello World from Xaml Islands!"); tb.VerticalAlignment(Windows::UI::Xaml::VerticalAlignment::Center); tb.HorizontalAlignment(Windows::UI::Xaml::HorizontalAlignment::Center); tb.FontSize(48); xamlContainer.Children().Append(tb); xamlContainer.UpdateLayout(); desktopSource.Content(xamlContainer); // End XAML Island section. ShowWindow(_hWnd, nCmdShow); UpdateWindow(_hWnd); //Message loop: MSG msg = { }; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }Copie o código a seguir após a seção anterior. Esse código define o procedimento de janela da janela.
LRESULT CALLBACK WindowProc(HWND hWnd, UINT messageCode, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; wchar_t greeting[] = L"Hello World in Win32!"; RECT rcClient; switch (messageCode) { case WM_PAINT: if (hWnd == _hWnd) { hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 300, 5, greeting, wcslen(greeting)); EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; // Create main window case WM_CREATE: _childhWnd = CreateWindowEx(0, L"ChildWClass", NULL, WS_CHILD | WS_BORDER, 0, 0, 0, 0, hWnd, NULL, _hInstance, NULL); return 0; // Main window changed size case WM_SIZE: // Get the dimensions of the main window's client // area, and enumerate the child windows. Pass the // dimensions to the child windows during enumeration. GetClientRect(hWnd, &rcClient); MoveWindow(_childhWnd, 200, 200, 400, 500, TRUE); ShowWindow(_childhWnd, SW_SHOW); return 0; // Process other messages. default: return DefWindowProc(hWnd, messageCode, wParam, lParam); break; } return 0; }Salve o arquivo de código e compile e execute o aplicativo. Confirme se você vê o controle TextBlock UWP na janela do aplicativo.
Observação
Você poderá ver os vários avisos de build, incluindo
warning C4002: too many arguments for function-like macro invocation 'GetCurrentTime'emanifest authoring warning 81010002: Unrecognized Element "maxversiontested" in namespace "urn:schemas-microsoft-com:compatibility.v1". Esses avisos são problemas conhecidos com as ferramentas e os pacotes NuGet atuais e eles podem ser ignorados.
Para obter exemplos completos que demonstram o uso da API de hospedagem XAML para hospedar um controle XAML UWP, consulte os seguintes arquivos de código:
- Área de trabalho do C++ (Win32): Consulte o arquivo XamlBridge.cpp no repositório de exemplos de código UWP XAML Islands.
- WPF: Consulte os arquivos WindowsXamlHostBase.cs e WindowsXamlHost.cs no Windows Community Toolkit.
- Windows Forms: Consulte os arquivos WindowsXamlHostBase.cs e WindowsXamlHost.cs no Windows Community Toolkit.
Empacotar o aplicativo
Opcionalmente, você pode empacotar o aplicativo em um pacote MSIX para implantação. O MSIX é a tecnologia moderna de empacotamento de aplicativo para o Windows e se baseia em uma combinação das tecnologias de instalação MSI, .appx, App-V e ClickOnce.
As instruções a seguir mostram como empacotar todos os componentes na solução em um pacote MSIX usando o Windows Application Packaging Project no Visual Studio 2019. Essas etapas serão necessárias apenas se você quiser empacotar o aplicativo em um pacote MSIX.
Observação
Se você optar por não empacotar seu aplicativo em um pacote MSIX para implantação, os computadores que executam o aplicativo precisarão ter o Runtime do Visual C++ instalado.
Adicione um novo Windows Application Packaging Project à sua solução. Ao criar o projeto, selecione Windows 10, versão 1903 (10.0; Build 18362) para a versão de destino e versão mínima.
No projeto de empacotamento, clique com o botão direito do mouse no nó Applications e escolha Adicionar referência. Na lista de projetos, selecione o projeto de aplicativo de desktop C++ em sua solução e clique em OK.
Compile e execute o projeto de empacotamento. Confirme se o aplicativo é executado e exibe os controles XAML UWP conforme o esperado.
Para obter informações sobre como distribuir/implantar o pacote, consulte Gerenciar sua implantação MSIX.
Próximas etapas
Os exemplos de código neste artigo iniciam o cenário básico de hospedagem de um controle XAML UWP padrão em um aplicativo de área de trabalho C++. As seções a seguir apresentam outros cenários aos quais o seu aplicativo poderá precisar dar suporte.
Hospedar um controle XAML UWP personalizado
Para muitos cenários, talvez seja necessário hospedar um controle XAML UWP personalizado que contenha vários controles individuais que funcionam juntos. O processo para hospedar um controle personalizado (ou seja, que você define por conta própria ou fornecido por terceiros) em um aplicativo da área de trabalho em C++ é mais complexo do que hospedar um controle padrão e exige código adicional.
Para obter um passo a passo completo, consulte Hospedar um controle XAML UWP personalizado em um aplicativo de área de trabalho C++ usando a API de Hospedagem XAML.
Cenários avançados
Muitos aplicativos de área de trabalho que hospedam ilhas XAML do UWP precisarão lidar com cenários adicionais para fornecer uma experiência do usuário fluida. Por exemplo, aplicativos de desktop podem precisar lidar com entrada de teclado em Ilhas XAML UWP, navegação de foco entre Ilhas XAML UWP e outros elementos da interface do usuário, e alterações de layout.
Para obter mais informações sobre como lidar com esses cenários e ponteiros para exemplos de código relacionados, consulte Cenários avançados para ilhas XAML UWP.
Tópicos relacionados
- Integrar controles XAML UWP em aplicativos desktop (Ilhas XAML UWP)
- Usando a API de hospedagem XAML da UWP em um aplicativo da área de trabalho do C++
- Incorporar um controle XAML UWP personalizado em um aplicativo C++ de área de trabalho
- Cenários avançados para ilhas XAML UWP
- Exemplos de código das Ilhas XAML UWP