主窗口后面出现应用内购买弹出窗口 - Flutter Win32 C++ 应用程序

问题描述 投票:0回答:1

我正在使用 Flutter Method Channel 开发 Windows 桌面应用程序,并且遇到了应用内购买功能的问题。触发后,购买模式对话框出现在主应用程序窗口后面,使其不可见。

这是发生的事情:

  1. 通过单击按钮启动应用内购买。
  2. 应用程序内购买弹出窗口在主应用程序窗口后面启动,使其不可见(如第一张图片所示)。
  3. 应用程序变得无响应,因为
    RequestPurchaseAsync
    在 UI 线程上运行,这是预期的。
  4. 关闭应用程序后,我可以看到弹出窗口打开,并且它保持交互状态(请参阅第二张图片)。

尝试使用

BringWindowToTop(hwnd)
SetForegroundWindow(hwnd)
尚未成功,因为它们会影响整个应用程序,而不仅仅是弹出窗口。

我正在寻找一种解决方案,将应用内购买弹出窗口带到最前面,但我对 C++ 和 Win32 的了解非常有限。

#include <Unknwn.h>
#include <flutter/event_channel.h>
#include <flutter/event_sink.h>
#include <flutter/event_stream_handler_functions.h>
#include <flutter/method_channel.h>
#include <flutter/standard_method_codec.h>
#include <winrt/Windows.Services.Store.h>
#include <winrt/Windows.Foundation.h>
#include <windows.h>
#include <memory>
#include <optional>
#include <string> 
#include <future>
#include <shobjidl.h>

#include "flutter_window.h"
#include "flutter/generated_plugin_registrant.h"

using namespace winrt;
using namespace Windows::Services::Store;


std::string store_id = "ABCDEFASD";
std::string success_key = "SUCCESS";

StoreContext storeContext = StoreContext::GetDefault();

FlutterWindow::FlutterWindow(const flutter::DartProject& project)
    : project_(project) {}

FlutterWindow::~FlutterWindow() {}

std::string upgrade() {
    if (!storeContext) {
        return "storeContext not initialized";
    }

    // Retrieve the IInitializeWithWindow interface from the StoreContext
    auto initWindow = storeContext.as<IInitializeWithWindow>();

    // Get the current process main window handle
    HWND hwnd = GetActiveWindow();

    // Initialize the StoreContext with the window handle
    initWindow->Initialize(hwnd);


    try {
        std::future<StorePurchaseResult> purchaseTask = std::async(std::launch::async, [&]() {
            return storeContext.RequestPurchaseAsync(winrt::to_hstring(store_id)).get();
            });

        StorePurchaseResult result = purchaseTask.get();

        if (result.ExtendedError().value != S_OK) {
            return "ExtendedError";
        }

        switch (result.Status())
        {
        case StorePurchaseStatus::Succeeded:
            return success_key;

        case StorePurchaseStatus::AlreadyPurchased:
            return "Already Purchased";

        case StorePurchaseStatus::NotPurchased:
            return "Purchase Not Completed";

        case StorePurchaseStatus::NetworkError:
            return "Network Error";

        case StorePurchaseStatus::ServerError:
            return "Server Error";

        default:
            return "Unknown Error";
        }
    }
    catch (const winrt::hresult_error& ex) {
        auto errorMessage = winrt::to_string(ex.message());
        return "Exception: " + errorMessage;
    }
    catch (const std::exception& ex) {
        return "Exception: " + std::string(ex.what());
    }
}

bool FlutterWindow::OnCreate() {
    if (!Win32Window::OnCreate()) {
        return false;
    }

    RECT frame = GetClientArea();

    // The size here must match the window dimensions to avoid unnecessary surface
    // creation / destruction in the startup path.
    flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
        frame.right - frame.left, frame.bottom - frame.top, project_);
    // Ensure that basic setup of the controller was successful.
    if (!flutter_controller_->engine() || !flutter_controller_->view()) {
        return false;
    }
    RegisterPlugins(flutter_controller_->engine());


    // Method Channel
    flutter::MethodChannel<> channel(
        flutter_controller_->engine()->messenger(), "method.channel.id",
        &flutter::StandardMethodCodec::GetInstance());
    channel.SetMethodCallHandler(
        [](const flutter::MethodCall<>& call,
            std::unique_ptr<flutter::MethodResult<>> result) {
                if (call.method_name() == "purchase") {
                    std::string purchaseResult = upgrade();
                    if (purchaseResult == success_key) {
                        result->Success();
                    }
                    else {
                        result->Error("ERROR", purchaseResult);
                    }
                }
                else {
                    result->NotImplemented();
                }
        });


    SetChildContent(flutter_controller_->view()->GetNativeWindow());

    flutter_controller_->engine()->SetNextFrameCallback([&]() {
        this->Show();
        });

    // Flutter can complete the first frame before the "show window" callback is
    // registered. The following call ensures a frame is pending to ensure the
    // window is shown. It is a no-op if the first frame hasn't completed yet.
    flutter_controller_->ForceRedraw();

    return true;
}

void FlutterWindow::OnDestroy() {
    if (flutter_controller_) {
        flutter_controller_ = nullptr;
    }

    Win32Window::OnDestroy();
}

LRESULT
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
    WPARAM const wparam,
    LPARAM const lparam) noexcept {
    // Give Flutter, including plugins, an opportunity to handle window messages.
    if (flutter_controller_) {
        std::optional<LRESULT> result =
            flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
                lparam);
        if (result) {
            return *result;
        }
    }

    switch (message) {
    case WM_FONTCHANGE:
        flutter_controller_->engine()->ReloadSystemFonts();
        break;
    }

    return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
}
c++ flutter windows winapi win32gui
1个回答
0
投票

经过几个小时的努力,我终于找到了解决方案。下面的代码有效地在中心显示应用内购买弹出窗口,并确保它位于前台的显着位置。

之前:

HWND hwnd = GetActiveWindow();
initWindow->Initialize(hwnd);

之后:

HWND activeHwnd = GetActiveWindow();
HWND parentHwnd = GetAncestor(activeHwnd, GA_PARENT);
initWindow->Initialize(parentHwnd);
© www.soinside.com 2019 - 2024. All rights reserved.