Переход на страницу с использованием API-интерфейса хостинга XAML в программе Win32 вызывает нарушение прав доступа - PullRequest
0 голосов
/ 01 апреля 2020

Я использую API хостинга XAML для размещения контента XAML в моей программе win32. Я успешно инициализировал структуру хостинга и создал DesktopWindowXamlSource объекты. Я установил Content() моего DesktopWindowXamlSource на Frame. Моя проблема возникает, когда я пытаюсь перейти на страницу с этим Frame.

Чтобы создать Page для моей программы на используйте, я выполнил следующие действия:

  1. Определить IDL

    namespace Program
    {
        [default_interface]
        runtimeclass SettingsPage: Windows.UI.Xaml.Controls.Page
        {
            SettingsPage();
        }
    }
    
  2. Я создаю проект, копирую сгенерированный заголовок и исходный файл из project_root_folder\Debug\Generated Files\sources к проекту root. Затем я добавляю файлы с помощью обозревателя решений.

  3. Я удаляю static_assert из каждого из файлов.

  4. Я создаю проект затем я пытаюсь перейти на страницу с помощью ContentFrame.Navigate(xaml_typename<winrt::Program::SettingsPage>);

Для содержимого DesktopWindowXamlSource установлено значение ContentFrame. Каждый раз, когда я пытаюсь перейти на страницу, я получаю эту ошибку:

Исключение, выданное в 0x00007FFA08C08106 (Windows .UI.Xaml.dll) в Program.exe: 0xC0000005: Место чтения нарушения доступа 0x0000000000000000.

My Entrypoint и 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 header:

#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"

1 Ответ

0 голосов
/ 07 апреля 2020

Так что я получил это работает. Необходимо выполнить следующие действия: API-интерфейс хостинга XAML с пользовательским управлением

Следуя инструкциям, игнорируйте указания Add a new UserControl и вместо них добавьте Page. Затем в настольном приложении перейдите на страницу из Frame, созданного в приложении UWP.

...