我正在使用XAML托管API在Win32程序中托管XAML内容。我已经成功初始化了托管框架并创建了DesktopWindowXamlSource
对象。我已经将Content()
的DesktopWindowXamlSource
设置为Frame.
。每当我尝试导航到带有Frame
的页面时,都会出现问题。
要创建供程序使用的Page
,我按照以下步骤操作:
进行IDL定义
namespace Program
{
[default_interface]
runtimeclass SettingsPage: Windows.UI.Xaml.Controls.Page
{
SettingsPage();
}
}
我构建项目,将生成的头文件和源文件从project_root_folder\Debug\Generated Files\sources
复制到项目的根目录。然后,我使用解决方案资源管理器添加文件。
我从每个文件中删除了static_assert
。
我构建了项目,然后尝试使用ContentFrame.Navigate(xaml_typename<winrt::Program::SettingsPage>);
DesktopWindowXamlSource
的内容设置为ContentFrame
。每次尝试导航到页面时,都会出现此错误:
在Program.exe中的0x00007FFA08C08106(Windows.UI.Xaml.dll)处引发的异常:0xC0000005:访问冲突读取位置0x0000000000000000。
我的入口和WindowProc
:
#include "pchRT.h" #include <Windows.h> #include <windowsx.h> #include "UIEngine.h" LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { static UI::UIEngine* uiEngine{ nullptr }; switch (msg) { case WM_CREATE: uiEngine = new UI::UIEngine{ reinterpret_cast<HMODULE>(GetWindowLongPtrW(hWnd, GWLP_HINSTANCE)), hWnd }; break; case WM_GETMINMAXINFO: { const auto mmInfo{ reinterpret_cast<LPMINMAXINFO>(lParam) }; mmInfo->ptMinTrackSize.x = 876; mmInfo->ptMinTrackSize.y = 565; } break; case WM_SIZE: if (uiEngine) { //... } break; case WM_DESTROY: delete uiEngine; winrt::uninit_apartment(); PostQuitMessage(0); break; default: return DefWindowProcW(hWnd, msg, wParam, lParam); } return 0; } int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int nCmdShow) { PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY handlePolicy{0}; handlePolicy.HandleExceptionsPermanentlyEnabled = 1; handlePolicy.RaiseExceptionOnInvalidHandleReference = 1; SetProcessMitigationPolicy(ProcessStrictHandleCheckPolicy, &handlePolicy, sizeof PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY); WNDCLASSEXW wc{ sizeof WNDCLASSEXW, CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, WindowProc, 0, 0, hInstance, nullptr, reinterpret_cast<HCURSOR>(LoadImageW(nullptr, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED)), reinterpret_cast<HBRUSH>(COLOR_WINDOWTEXT), nullptr, L"Settings Manager", nullptr }; const auto hWnd{ CreateWindowExW(WS_EX_LAYERED, MAKEINTATOM(RegisterClassExW(&wc)), L"Settings Manager", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, nullptr, hInstance, nullptr) }; SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA); ShowWindow(hWnd, nCmdShow); MSG msg; while (GetMessageW(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); } return 0; }
UIEngine
标头:#pragma once #include "pchRT.h" #include "resource.h" #include "MainPage.h" #include <Windows.h> #include <dwmapi.h> #include <string> #include <fstream> #include <memory> #include <vector> namespace UI { class UIEngine { HWND XamlIslandsWindow{}, CaptionIslandsWindow{}, Window; winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource DesktopWindowXamlSource; winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource CaptionXamlSource; winrt::Windows::UI::Xaml::Controls::Grid CaptionGrid, PanelGrid{ nullptr }; winrt::Windows::UI::Xaml::Controls::Frame ContentFrame; bool HandleOverlap; RECT ClientArea; HINSTANCE AppInstance; winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::IRandomAccessStream> ExtractAndLoadResource( int resourceId, LPCWSTR resourceType) const; static winrt::Windows::UI::Xaml::FrameworkElement FindElement( winrt::Windows::UI::Xaml::FrameworkElement const& startElement, PCWCH name); public: explicit UIEngine(HINSTANCE appInstance, HWND hWnd); }; }
UIEngine
实现:#include "pchRT.h" #include "UIEngine.h" using namespace winrt; using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::UI::Xaml::Controls; using namespace winrt::Windows::UI::Xaml::Media; using namespace winrt::Windows::UI; using namespace winrt::Windows::UI::Composition; using namespace winrt::Windows::UI::Xaml::Input; using namespace winrt::Windows::Foundation; using namespace winrt::Windows::Foundation::Numerics; using namespace winrt::Windows::Storage::Streams; using namespace winrt::Windows::UI::Xaml::Media::Imaging; using namespace winrt::Windows::UI::Xaml::Controls::Primitives; namespace UI { UIEngine::UIEngine(const HINSTANCE appInstance, const HWND hWnd) : Window(hWnd), HandleOverlap(false), AppInstance(appInstance) { init_apartment(); auto windowInterop{ DesktopWindowXamlSource.as<IDesktopWindowXamlSourceNative>() }, windowInterop2{ CaptionXamlSource.as<IDesktopWindowXamlSourceNative>() }; check_hresult(windowInterop->AttachToWindow(hWnd)); check_hresult(windowInterop2->AttachToWindow(hWnd)); windowInterop->get_WindowHandle(&XamlIslandsWindow); windowInterop2->get_WindowHandle(&CaptionIslandsWindow); ClientArea.top *= -1; SetWindowLongPtrW(CaptionIslandsWindow, GWL_EXSTYLE, GetWindowLongPtrW(CaptionIslandsWindow, GWL_EXSTYLE) | WS_EX_TRANSPARENT); EnableWindow(CaptionIslandsWindow, FALSE); SetWindowPos(CaptionIslandsWindow, nullptr, 0, 1, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); SetWindowPos(XamlIslandsWindow, nullptr, 0, ClientArea.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); const Border captionBorder; const AcrylicBrush captionBorderBrush; captionBorderBrush.TintOpacity(0.65); captionBorderBrush.TintColor({ 255, 25, 25, 25 }); captionBorderBrush.FallbackColor({ 255, 35, 35, 35 }); captionBorderBrush.BackgroundSource(AcrylicBackgroundSource::HostBackdrop); captionBorder.Background(captionBorderBrush); captionBorder.HorizontalAlignment(HorizontalAlignment::Left); captionBorder.Width(75); CaptionGrid.Children().Append(captionBorder); CaptionXamlSource.Content(CaptionGrid); ContentFrame.Navigate(xaml_typename<winrt::Program::SettingsPage>()); } }
pchRT.h
:#pragma once #include <Unknwn.h> #include <winrt/base.h> #include <windows.ui.xaml.hosting.desktopwindowxamlsource.h> #include <winrt/Windows.UI.Xaml.Hosting.h> #include <winrt/Windows.UI.Xaml.Media.h> #include <winrt/Windows.UI.Xaml.Controls.h> #include <winrt/Windows.UI.Xaml.Input.h> #include <winrt/Windows.UI.h> #include <winrt/Windows.UI.Input.h> #include <winrt/Windows.UI.Xaml.h> #include <winrt/Windows.UI.Xaml.Controls.Primitives.h> #include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.Collections.h> #include <winrt/Windows.UI.Xaml.Markup.h> #include <winrt/Windows.UI.Xaml.Interop.h> #include <winrt/Windows.Storage.Streams.h> #include <winrt/Windows.UI.Xaml.Media.Imaging.h> #include <winrt/Windows.UI.Xaml.Data.h>
我的调用堆栈由以下函数调用组成:
Windows.UI.Xaml.dll!00007ffa08c08106() Unknown Windows.UI.Xaml.dll!00007ffa08c25edc() Unknown Windows.UI.Xaml.dll!00007ffa08c27c22() Unknown Windows.UI.Xaml.dll!00007ffa08c27da7() Unknown Windows.UI.Xaml.dll!00007ffa08c27ead() Unknown Windows.UI.Xaml.dll!00007ffa08c28006() Unknown Windows.UI.Xaml.dll!00007ffa08c280e8() Unknown Windows.UI.Xaml.dll!00007ffa08c281df() Unknown Windows.UI.Xaml.dll!00007ffa08b7e225() Unknown Windows.UI.Xaml.dll!00007ffa08b7e1af() Unknown > Program.exe!winrt::impl::consume_Windows_UI_Xaml_Controls_INavigate<winrt::Windows::UI::Xaml::Controls::Frame>::Navigate(const winrt::Windows::UI::Xaml::Interop::TypeName & sourcePageType) Line 10998 C++ Program.exe!UI::UIEngine::UIEngine(HINSTANCE__ * appInstance, HWND__ * hWnd, tagRECT clientArea) Line 123 C++ Program.exe!WindowProc(HWND__ * hWnd, unsigned int msg, unsigned __int64 wParam, __int64 lParam) Line 33 C++ [External Code] Program.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * __formal, wchar_t * __formal, int nCmdShow) Line 128 C++ [External Code]
我正在用C ++ / WinRT标志
-optimize
编译我的代码,并且包含了#include "UI.SettingsPage.g.cpp"
我正在使用XAML托管API在Win32程序中托管XAML内容。我已经成功初始化了托管框架并创建了DesktopWindowXamlSource对象。我已经将Content()设置为...
所以我开始工作了。您需要执行以下步骤:Custom Control XAML Hosting API
执行以下步骤时,请忽略方向Add a new UserControl
,而是添加Page
。然后,在桌面应用程序中,从UWP应用程序中创建的Frame
导航到页面。