スポンサーリンク

CEFをwxWidgetsのウィンドウに貼り付ける(settings.multi_threaded_message_loop = false)

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

#include <wx/gdicmn.h> // wxPointに必要
#include <wx/frame.h>  // wxFrameに必要


#ifdef _DEBUG
#pragma comment(lib, "D:\\cmmon\\cef_binary_138.0.15+gd0f1f64+chromium-138.0.7204.50_windows64\\Debug\\libcef.lib")
#pragma comment(lib, "D:\\cmmon\\MD\\Debug\\libcef_dll_wrapper.lib")
#else
#pragma comment(lib, "D:\\cmmon\\cef_binary_138.0.15+gd0f1f64+chromium-138.0.7204.50_windows64\\Release\\libcef.lib")
#pragma comment(lib, "D:\\cmmon\\MD\\Release\\libcef_dll_wrapper.lib")
#endif


#include <wx/evtloop.h>

/////////////////////////////////////
/////////////////////////////////////
/////////////////////////////////////
#include <include/cef_app.h>

#include <string>

class MyHandler : 
    public CefClient, 
    public CefLifeSpanHandler  {
public:
    MyHandler() {}

    CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
        return this;
    }

    void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
        m_Browser = browser;
    }

    void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
        m_Browser = nullptr;

        // イベントから抜ける
        if (wxEventLoopBase::GetActive()) {
            wxEventLoopBase::GetActive()->Exit();
        }

    }

    void CloseAllBrowsers(bool force_close) {
        if (m_Browser) {
            m_Browser->GetHost()->CloseBrowser(force_close);
        }
    }


    CefRefPtr<CefBrowser> GetBrowser() { return m_Browser; }

    IMPLEMENT_REFCOUNTING(MyHandler);

private:
    CefRefPtr<CefBrowser> m_Browser;
};

class MyCustomEventLoop : public wxGUIEventLoop
{
public:
    MyCustomEventLoop() = default;
    virtual ~MyCustomEventLoop() = default;


protected:

    // Yieldが必要な場合
    virtual void DoYieldFor(long eventsToProcess) override
    {
        // デフォルトの実装
        wxGUIEventLoop::DoYieldFor(eventsToProcess);
    }

    // メッセージループの各イテレーション開始時に呼ばれるフック
    virtual void OnNextIteration() override
    {

        // デフォルトの実装
        wxGUIEventLoop::OnNextIteration();
    }

    //////////////////////////////////////////////
    // メッセージを処理する
    bool Dispatch() override
    {
        bool running = true;
        MSG msg;
        while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                running = false;
            else
            {
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
            }
        }

        CefDoMessageLoopWork();

        ::Sleep(10);

        
        return true;  // まだ継続

    }
    //////////////////////////////////////////////

};


// メインフレーム
class MyFrame : public wxFrame
{
    CefRefPtr<MyHandler> g_handler;
public:
    MyFrame()
        : wxFrame(nullptr, wxID_ANY, "メッセージループ")
    {
        Bind(wxEVT_CLOSE_WINDOW, &MyFrame::OnClose, this);

        Bind(wxEVT_SIZE, &MyFrame::OnSize, this);

        CallAfter(&MyFrame::PostCreate);
    }

private:

    void PostCreate() {

        g_handler = CefRefPtr<MyHandler>(new MyHandler);

        CefBrowserSettings browser_settings;

        CefWindowInfo window_info;
        CefRect cefRect(
            0,
            0,
            400,
            400);

        HWND hwnd = (HWND)this->GetHandle();
        window_info.SetAsChild(hwnd, cefRect);



        CefBrowserHost::CreateBrowser(
            window_info,
            g_handler,
            "https://www.google.com",
            browser_settings,
            nullptr,
            nullptr);


        this->Layout(); // レイアウトの更新
    }

    void OnClose(wxCloseEvent& evt)
    {
        // CEFのブラウザを閉じる
        g_handler->CloseAllBrowsers(true);

        // ウィンドウを閉じない指示
        evt.Veto();
    }

    void OnSize(wxSizeEvent& evt)
    {
        if (g_handler) {
            HWND hBrowserWnd = g_handler->GetBrowser()->GetHost()->GetWindowHandle();
            // ウィンドウサイズ変更時の処理
            if (g_handler && g_handler->GetBrowser()) {
                RECT rect(0, 0, evt.GetSize().GetWidth(), evt.GetSize().GetHeight());
                SetWindowPos(hBrowserWnd, NULL,
                    0, 0,
                    rect.right - rect.left,
                    rect.bottom - rect.top,
                    SWP_NOZORDER);

                // ブラウザにサイズ変更を通知
                g_handler->GetBrowser()->GetHost()->WasResized();
            }
        }

        evt.Skip(); // イベントをスキップしてデフォルトの処理を行う
    }

};


class MyApp : public wxApp
{
public:
    bool OnInit() override
    {

        HINSTANCE hInstance = ::GetModuleHandle(NULL);
        CefMainArgs main_args(hInstance);
        int exit_code = CefExecuteProcess(main_args, nullptr, nullptr);
        if (exit_code >= 0)
            return false;

        // CEFの設定
        CefSettings settings;
        settings.no_sandbox = true;

        // マルチスレッドメッセージループを無効にする
        settings.multi_threaded_message_loop = false;


        CefInitialize(main_args, settings, nullptr, nullptr);

        ///////////////////////////////////////////////////


        auto frame = new MyFrame();
        frame->Show();
        return true;
    }

    int OnRun() override
    {
        // wxGUIEventLoop を使って自前ループを構築
        MyCustomEventLoop* loop = new MyCustomEventLoop;
        wxEventLoopBase::SetActive(loop);   // アクティブなループとして登録
        int retval = loop->Run();           // ここでメッセージループ開始
        delete loop;                        // ループ終了後に解放

        // CEFのシャットダウン
        CefShutdown();

        return retval;
    }

    virtual int OnExit() {
        return wxApp::OnExit();
    }

};

// WinMainをマクロで定義
wxIMPLEMENT_APP(MyApp);

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: