スポンサーリンク
#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);