Files
XCEngine/new_editor/app/Platform/Win32/BorderlessWindowChromeDwm.cpp

196 lines
5.9 KiB
C++

#include "BorderlessWindowChrome.h"
#include <dwmapi.h>
namespace XCEngine::UI::Editor::Host {
namespace {
bool IsWindowAlignedToMonitorWorkArea(HWND hwnd) {
if (hwnd == nullptr) {
return false;
}
RECT windowRect = {};
if (!GetWindowRect(hwnd, &windowRect)) {
return false;
}
const HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor == nullptr) {
return false;
}
MONITORINFO monitorInfo = {};
monitorInfo.cbSize = sizeof(monitorInfo);
if (!GetMonitorInfoW(monitor, &monitorInfo)) {
return false;
}
const RECT& workArea = monitorInfo.rcWork;
return windowRect.left == workArea.left &&
windowRect.top == workArea.top &&
windowRect.right == workArea.right &&
windowRect.bottom == workArea.bottom;
}
void ApplyDwmBoolWindowAttribute(HWND hwnd, DWORD attribute, BOOL value) {
if (hwnd == nullptr) {
return;
}
using DwmSetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, LPCVOID, DWORD);
static const auto setWindowAttribute = []() -> DwmSetWindowAttributeFn {
HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll");
if (dwmapi == nullptr) {
dwmapi = LoadLibraryW(L"dwmapi.dll");
}
if (dwmapi == nullptr) {
return nullptr;
}
return reinterpret_cast<DwmSetWindowAttributeFn>(
GetProcAddress(dwmapi, "DwmSetWindowAttribute"));
}();
if (setWindowAttribute != nullptr) {
setWindowAttribute(hwnd, attribute, &value, sizeof(value));
}
}
void ApplyDwmColorWindowAttribute(HWND hwnd, DWORD attribute, COLORREF value) {
if (hwnd == nullptr) {
return;
}
using DwmSetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, LPCVOID, DWORD);
static const auto setWindowAttribute = []() -> DwmSetWindowAttributeFn {
HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll");
if (dwmapi == nullptr) {
dwmapi = LoadLibraryW(L"dwmapi.dll");
}
if (dwmapi == nullptr) {
return nullptr;
}
return reinterpret_cast<DwmSetWindowAttributeFn>(
GetProcAddress(dwmapi, "DwmSetWindowAttribute"));
}();
if (setWindowAttribute != nullptr) {
setWindowAttribute(hwnd, attribute, &value, sizeof(value));
}
}
void ApplyDwmIntWindowAttribute(HWND hwnd, DWORD attribute, int value) {
if (hwnd == nullptr) {
return;
}
using DwmSetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, LPCVOID, DWORD);
static const auto setWindowAttribute = []() -> DwmSetWindowAttributeFn {
HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll");
if (dwmapi == nullptr) {
dwmapi = LoadLibraryW(L"dwmapi.dll");
}
if (dwmapi == nullptr) {
return nullptr;
}
return reinterpret_cast<DwmSetWindowAttributeFn>(
GetProcAddress(dwmapi, "DwmSetWindowAttribute"));
}();
if (setWindowAttribute != nullptr) {
setWindowAttribute(hwnd, attribute, &value, sizeof(value));
}
}
} // namespace
void EnableBorderlessWindowShadow(HWND hwnd) {
if (hwnd == nullptr) {
return;
}
using DwmExtendFrameIntoClientAreaFn = HRESULT(WINAPI*)(HWND, const MARGINS*);
static const auto extendFrameIntoClientArea = []() -> DwmExtendFrameIntoClientAreaFn {
HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll");
if (dwmapi == nullptr) {
dwmapi = LoadLibraryW(L"dwmapi.dll");
}
if (dwmapi == nullptr) {
return nullptr;
}
return reinterpret_cast<DwmExtendFrameIntoClientAreaFn>(
GetProcAddress(dwmapi, "DwmExtendFrameIntoClientArea"));
}();
if (extendFrameIntoClientArea != nullptr) {
const bool maximized = IsZoomed(hwnd) || IsWindowAlignedToMonitorWorkArea(hwnd);
const MARGINS margins = maximized
? MARGINS{ 0, 0, 0, 0 }
: MARGINS{ 1, 1, 1, 1 };
extendFrameIntoClientArea(hwnd, &margins);
}
}
void RefreshBorderlessWindowDwmDecorations(HWND hwnd) {
if (hwnd == nullptr) {
return;
}
ApplyDwmIntWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, DWMNCRP_DISABLED);
ApplyDwmBoolWindowAttribute(hwnd, DWMWA_ALLOW_NCPAINT, FALSE);
ApplyDwmBoolWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, TRUE);
ApplyDwmBoolWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, TRUE);
ApplyDwmColorWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, RGB(26, 26, 26));
ApplyDwmColorWindowAttribute(hwnd, DWMWA_TEXT_COLOR, RGB(235, 235, 235));
ApplyDwmColorWindowAttribute(hwnd, DWMWA_BORDER_COLOR, RGB(26, 26, 26));
EnableBorderlessWindowShadow(hwnd);
}
bool HandleBorderlessWindowGetMinMaxInfo(HWND hwnd, LPARAM lParam) {
if (hwnd == nullptr || lParam == 0) {
return false;
}
auto* minMaxInfo = reinterpret_cast<MINMAXINFO*>(lParam);
if (minMaxInfo == nullptr) {
return false;
}
const HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor == nullptr) {
return false;
}
MONITORINFO monitorInfo = {};
monitorInfo.cbSize = sizeof(monitorInfo);
if (!GetMonitorInfoW(monitor, &monitorInfo)) {
return false;
}
const RECT& workArea = monitorInfo.rcWork;
const RECT& monitorArea = monitorInfo.rcMonitor;
minMaxInfo->ptMaxPosition.x = workArea.left - monitorArea.left;
minMaxInfo->ptMaxPosition.y = workArea.top - monitorArea.top;
minMaxInfo->ptMaxSize.x = workArea.right - workArea.left;
minMaxInfo->ptMaxSize.y = workArea.bottom - workArea.top;
minMaxInfo->ptMaxTrackSize = minMaxInfo->ptMaxSize;
return true;
}
LRESULT HandleBorderlessWindowNcCalcSize(
HWND hwnd,
WPARAM wParam,
LPARAM lParam,
UINT dpi) {
(void)hwnd;
(void)wParam;
(void)lParam;
(void)dpi;
return 0;
}
} // namespace XCEngine::UI::Editor::Host