#include "WindowMessageDispatcher.h" #include "../Application.h" namespace XCEngine::UI::Editor::Host { namespace { constexpr UINT kDeferredRenderMessage = WM_APP + 1u; void TryEnableNonClientDpiScaling(HWND hwnd) { if (hwnd == nullptr) { return; } const HMODULE user32 = GetModuleHandleW(L"user32.dll"); if (user32 == nullptr) { return; } using EnableNonClientDpiScalingFn = BOOL(WINAPI*)(HWND); const auto enableNonClientDpiScaling = reinterpret_cast( GetProcAddress(user32, "EnableNonClientDpiScaling")); if (enableNonClientDpiScaling != nullptr) { enableNonClientDpiScaling(hwnd); } } } // namespace Application* WindowMessageDispatcher::GetApplicationFromWindow(HWND hwnd) { return reinterpret_cast(GetWindowLongPtrW(hwnd, GWLP_USERDATA)); } bool WindowMessageDispatcher::TryHandleNonClientCreate( HWND hwnd, UINT message, LPARAM lParam, LRESULT& outResult) { if (message != WM_NCCREATE) { return false; } TryEnableNonClientDpiScaling(hwnd); const auto* createStruct = reinterpret_cast(lParam); auto* application = reinterpret_cast(createStruct->lpCreateParams); SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast(application)); outResult = TRUE; return true; } bool WindowMessageDispatcher::TryDispatch( Application& application, UINT message, WPARAM wParam, LPARAM lParam, LRESULT& outResult) { switch (message) { case WM_SETCURSOR: if (LOWORD(lParam) == HTCLIENT && application.ApplyCurrentCursor()) { outResult = TRUE; return true; } return false; case WM_DPICHANGED: if (lParam == 0) { return false; } application.OnDpiChanged( static_cast(LOWORD(wParam)), *reinterpret_cast(lParam)); RequestDeferredRenderFrame(application); outResult = 0; return true; case WM_ENTERSIZEMOVE: application.OnEnterSizeMove(); outResult = 0; return true; case WM_EXITSIZEMOVE: application.OnExitSizeMove(); RequestDeferredRenderFrame(application); outResult = 0; return true; case WM_SIZE: if (wParam != SIZE_MINIMIZED) { application.OnResize(); RequestDeferredRenderFrame(application); } outResult = 0; return true; case kDeferredRenderMessage: application.OnDeferredRenderMessage(); outResult = 0; return true; case WM_PAINT: application.OnPaintMessage(); outResult = 0; return true; default: return false; } } void WindowMessageDispatcher::RequestDeferredRenderFrame(Application& application) { if (application.m_hwnd == nullptr || !IsWindow(application.m_hwnd) || !application.m_hostRuntime.TryQueueDeferredRender()) { return; } PostMessageW(application.m_hwnd, kDeferredRenderMessage, 0, 0); } } // namespace XCEngine::UI::Editor::Host