webview/webview

Not work when embed into a win32 window

HIllya51 opened this issue · 2 comments

tested the code in #1074
set_html and navigate only show a blank window.
屏幕截图 2024-04-28 141410

Here's a revised version of the example I posted in #1074.

I've only updated the functions resize_widget and focus_webview which depended on PR #1064.

Feel free to let me know any opinions you may have on the ok() and value() calls which were introduced not too long ago.

#include "webview.h"
#include <memory>
#include <windows.h>

class window {
public:
  window() {
    HINSTANCE hInstance = GetModuleHandleW(nullptr);

    WNDCLASSEXW wc{};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
    wc.lpszClassName = L"window";
    wc.lpfnWndProc = wndproc_wrapper;
    RegisterClassExW(&wc);

    CreateWindowExW(0, L"window", L"Win32 Example", WS_OVERLAPPEDWINDOW,
                    CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, nullptr, nullptr,
                    hInstance, this);
  }

  void show() {
    // When a future PR stops showing non-owned windows automatially,
    // code similar to this will be needed.
    ShowWindow(m_native_window, SW_SHOW);
    UpdateWindow(m_native_window);
    SetFocus(m_native_window);
    focus_webview();
  }

private:
  static LRESULT wndproc_wrapper(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    window *self{};

    if (msg == WM_NCCREATE) {
      auto *lpcs{reinterpret_cast<LPCREATESTRUCT>(lp)};
      self = static_cast<window *>(lpcs->lpCreateParams);
      self->m_native_window = hwnd;
      SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(self));
    } else {
      self = reinterpret_cast<window *>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
    }

    if (!self) {
      return DefWindowProcW(hwnd, msg, wp, lp);
    }

    return self->wndproc(msg, wp, lp);
  }

  LRESULT wndproc(UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
    case WM_CREATE:
      m_webview = std::make_unique<webview::webview>(false, m_native_window);
      m_webview->set_html("Thanks for using webview!");
      break;
    case WM_SIZE:
      resize_widget();
      break;
    case WM_CLOSE:
      DestroyWindow(m_native_window);
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    case WM_ACTIVATE:
      if (LOWORD(wp) != WA_INACTIVE) {
        focus_webview();
      }
      break;
    default:
      return DefWindowProcW(m_native_window, msg, wp, lp);
    }
    return 0;
  }

  void resize_widget() {
    if (m_webview) {
      auto widget = m_webview->widget();
      if (widget.ok()) {
        auto widget_handle = static_cast<HWND>(widget.value());
        RECT r{};
        if (GetClientRect(GetParent(widget_handle), &r)) {
          MoveWindow(widget_handle, r.left, r.top, r.right - r.left, r.bottom - r.top,
                     TRUE);
        }
      }
    }
  }

  void focus_webview() {
    if (m_webview) {
      auto controller = m_webview->browser_controller();
      if (controller.ok()) {
        auto* controller_ptr = static_cast<ICoreWebView2Controller *>(controller.value());
        controller_ptr->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
      }
    }
  }

  HWND m_native_window{};
  std::unique_ptr<webview::webview> m_webview;
};

class application {
public:
  application() { CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); }

  void run() {
    MSG msg;
    while (GetMessageW(&msg, nullptr, 0, 0) > 0) {
      TranslateMessage(&msg);
      DispatchMessageW(&msg);
    }
  }
};

int WINAPI WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/,
                   LPSTR /*lpCmdLine*/, int /*nCmdShow*/) {
  application app;

  window window;
  window.show();

  app.run();
  return 0;
}

This is what it looks like in my Windows 10 environment.

image

good! it now works fine!