Advertisement
FlyFar

win32_window.cpp

Jul 25th, 2023
653
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.10 KB | Cybersecurity | 0 0
  1. #include "win32_window.h"
  2.  
  3. #include <flutter_windows.h>
  4.  
  5. #include "resource.h"
  6.  
  7. namespace {
  8.  
  9. constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
  10.  
  11. // The number of Win32Window objects that currently exist.
  12. static int g_active_window_count = 0;
  13.  
  14. using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
  15.  
  16. // Scale helper to convert logical scaler values to physical using passed in
  17. // scale factor
  18. int Scale(int source, double scale_factor) {
  19.   return static_cast<int>(source * scale_factor);
  20. }
  21.  
  22. // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
  23. // This API is only needed for PerMonitor V1 awareness mode.
  24. void EnableFullDpiSupportIfAvailable(HWND hwnd) {
  25.   HMODULE user32_module = LoadLibraryA("User32.dll");
  26.   if (!user32_module) {
  27.     return;
  28.   }
  29.   auto enable_non_client_dpi_scaling =
  30.       reinterpret_cast<EnableNonClientDpiScaling*>(
  31.           GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
  32.   if (enable_non_client_dpi_scaling != nullptr) {
  33.     enable_non_client_dpi_scaling(hwnd);
  34.     FreeLibrary(user32_module);
  35.   }
  36. }
  37.  
  38. }  // namespace
  39.  
  40. // Manages the Win32Window's window class registration.
  41. class WindowClassRegistrar {
  42.  public:
  43.   ~WindowClassRegistrar() = default;
  44.  
  45.   // Returns the singleton registar instance.
  46.   static WindowClassRegistrar* GetInstance() {
  47.     if (!instance_) {
  48.       instance_ = new WindowClassRegistrar();
  49.     }
  50.     return instance_;
  51.   }
  52.  
  53.   // Returns the name of the window class, registering the class if it hasn't
  54.   // previously been registered.
  55.   const wchar_t* GetWindowClass();
  56.  
  57.   // Unregisters the window class. Should only be called if there are no
  58.   // instances of the window.
  59.   void UnregisterWindowClass();
  60.  
  61.  private:
  62.   WindowClassRegistrar() = default;
  63.  
  64.   static WindowClassRegistrar* instance_;
  65.  
  66.   bool class_registered_ = false;
  67. };
  68.  
  69. WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
  70.  
  71. const wchar_t* WindowClassRegistrar::GetWindowClass() {
  72.   if (!class_registered_) {
  73.     WNDCLASS window_class{};
  74.     window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
  75.     window_class.lpszClassName = kWindowClassName;
  76.     window_class.style = CS_HREDRAW | CS_VREDRAW;
  77.     window_class.cbClsExtra = 0;
  78.     window_class.cbWndExtra = 0;
  79.     window_class.hInstance = GetModuleHandle(nullptr);
  80.     window_class.hIcon =
  81.         LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
  82.     window_class.hbrBackground = 0;
  83.     window_class.lpszMenuName = nullptr;
  84.     window_class.lpfnWndProc = Win32Window::WndProc;
  85.     RegisterClass(&window_class);
  86.     class_registered_ = true;
  87.   }
  88.   return kWindowClassName;
  89. }
  90.  
  91. void WindowClassRegistrar::UnregisterWindowClass() {
  92.   UnregisterClass(kWindowClassName, nullptr);
  93.   class_registered_ = false;
  94. }
  95.  
  96. Win32Window::Win32Window() {
  97.   ++g_active_window_count;
  98. }
  99.  
  100. Win32Window::~Win32Window() {
  101.   --g_active_window_count;
  102.   Destroy();
  103. }
  104.  
  105. bool Win32Window::CreateAndShow(const std::wstring& title,
  106.                                 const Point& origin,
  107.                                 const Size& size) {
  108.   Destroy();
  109.  
  110.   const wchar_t* window_class =
  111.       WindowClassRegistrar::GetInstance()->GetWindowClass();
  112.  
  113.   const POINT target_point = {static_cast<LONG>(origin.x),
  114.                               static_cast<LONG>(origin.y)};
  115.   HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
  116.   UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
  117.   double scale_factor = dpi / 96.0;
  118.  
  119.   HWND window = CreateWindow(
  120.       window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  121.       Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
  122.       Scale(size.width, scale_factor), Scale(size.height, scale_factor),
  123.       nullptr, nullptr, GetModuleHandle(nullptr), this);
  124.  
  125.   if (!window) {
  126.     return false;
  127.   }
  128.  
  129.   return OnCreate();
  130. }
  131.  
  132. // static
  133. LRESULT CALLBACK Win32Window::WndProc(HWND const window,
  134.                                       UINT const message,
  135.                                       WPARAM const wparam,
  136.                                       LPARAM const lparam) noexcept {
  137.   if (message == WM_NCCREATE) {
  138.     auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
  139.     SetWindowLongPtr(window, GWLP_USERDATA,
  140.                      reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
  141.  
  142.     auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
  143.     EnableFullDpiSupportIfAvailable(window);
  144.     that->window_handle_ = window;
  145.   } else if (Win32Window* that = GetThisFromHandle(window)) {
  146.     return that->MessageHandler(window, message, wparam, lparam);
  147.   }
  148.  
  149.   return DefWindowProc(window, message, wparam, lparam);
  150. }
  151.  
  152. LRESULT
  153. Win32Window::MessageHandler(HWND hwnd,
  154.                             UINT const message,
  155.                             WPARAM const wparam,
  156.                             LPARAM const lparam) noexcept {
  157.   switch (message) {
  158.     case WM_DESTROY:
  159.       window_handle_ = nullptr;
  160.       Destroy();
  161.       if (quit_on_close_) {
  162.         PostQuitMessage(0);
  163.       }
  164.       return 0;
  165.  
  166.     case WM_DPICHANGED: {
  167.       auto newRectSize = reinterpret_cast<RECT*>(lparam);
  168.       LONG newWidth = newRectSize->right - newRectSize->left;
  169.       LONG newHeight = newRectSize->bottom - newRectSize->top;
  170.  
  171.       SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
  172.                    newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
  173.  
  174.       return 0;
  175.     }
  176.     case WM_SIZE: {
  177.       RECT rect = GetClientArea();
  178.       if (child_content_ != nullptr) {
  179.         // Size and position the child window.
  180.         MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
  181.                    rect.bottom - rect.top, TRUE);
  182.       }
  183.       return 0;
  184.     }
  185.  
  186.     case WM_ACTIVATE:
  187.       if (child_content_ != nullptr) {
  188.         SetFocus(child_content_);
  189.       }
  190.       return 0;
  191.   }
  192.  
  193.   return DefWindowProc(window_handle_, message, wparam, lparam);
  194. }
  195.  
  196. void Win32Window::Destroy() {
  197.   OnDestroy();
  198.  
  199.   if (window_handle_) {
  200.     DestroyWindow(window_handle_);
  201.     window_handle_ = nullptr;
  202.   }
  203.   if (g_active_window_count == 0) {
  204.     WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
  205.   }
  206. }
  207.  
  208. Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
  209.   return reinterpret_cast<Win32Window*>(
  210.       GetWindowLongPtr(window, GWLP_USERDATA));
  211. }
  212.  
  213. void Win32Window::SetChildContent(HWND content) {
  214.   child_content_ = content;
  215.   SetParent(content, window_handle_);
  216.   RECT frame = GetClientArea();
  217.  
  218.   MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
  219.              frame.bottom - frame.top, true);
  220.  
  221.   SetFocus(child_content_);
  222. }
  223.  
  224. RECT Win32Window::GetClientArea() {
  225.   RECT frame;
  226.   GetClientRect(window_handle_, &frame);
  227.   return frame;
  228. }
  229.  
  230. HWND Win32Window::GetHandle() {
  231.   return window_handle_;
  232. }
  233.  
  234. void Win32Window::SetQuitOnClose(bool quit_on_close) {
  235.   quit_on_close_ = quit_on_close;
  236. }
  237.  
  238. bool Win32Window::OnCreate() {
  239.   // No-op; provided for subclasses.
  240.   return true;
  241. }
  242.  
  243. void Win32Window::OnDestroy() {
  244.   // No-op; provided for subclasses.
  245. }
Tags: windows win32
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement