2019-09-04 18:26:26 +02:00
|
|
|
#include "monitors.h"
|
|
|
|
|
|
2020-12-15 15:16:09 +03:00
|
|
|
#include <algorithm>
|
2020-04-20 18:09:10 +02:00
|
|
|
|
2022-08-27 02:17:20 +03:00
|
|
|
Box MonitorInfo::GetScreenSize(const bool includeNonWorkingArea) const
|
2020-08-25 18:55:29 +02:00
|
|
|
{
|
2022-08-27 02:17:20 +03:00
|
|
|
return includeNonWorkingArea ? Box{ info.rcMonitor } : Box{ info.rcWork };
|
2020-08-25 18:55:29 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-27 02:17:20 +03:00
|
|
|
bool MonitorInfo::IsPrimary() const
|
2020-03-05 13:07:06 +03:00
|
|
|
{
|
2022-08-27 02:17:20 +03:00
|
|
|
return static_cast<bool>(info.dwFlags & MONITORINFOF_PRIMARY);
|
2019-09-04 18:26:26 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-27 02:17:20 +03:00
|
|
|
MonitorInfo::MonitorInfo(HMONITOR h) :
|
|
|
|
|
handle{ h }
|
2020-03-05 13:07:06 +03:00
|
|
|
{
|
2022-08-27 02:17:20 +03:00
|
|
|
info.cbSize = sizeof(MONITORINFOEX);
|
|
|
|
|
GetMonitorInfoW(handle, &info);
|
|
|
|
|
}
|
2019-09-04 18:26:26 +02:00
|
|
|
|
2022-11-09 14:41:14 +00:00
|
|
|
static BOOL CALLBACK GetDisplaysEnumCb(HMONITOR monitor, HDC /*hdc*/, LPRECT /*rect*/, LPARAM data)
|
2020-03-05 13:07:06 +03:00
|
|
|
{
|
2022-08-27 02:17:20 +03:00
|
|
|
auto* monitors = reinterpret_cast<std::vector<MonitorInfo>*>(data);
|
|
|
|
|
monitors->emplace_back(monitor);
|
2020-03-05 13:07:06 +03:00
|
|
|
return true;
|
2019-09-04 18:26:26 +02:00
|
|
|
};
|
|
|
|
|
|
2020-04-20 18:09:10 +02:00
|
|
|
std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool includeNonWorkingArea)
|
2020-03-05 13:07:06 +03:00
|
|
|
{
|
|
|
|
|
std::vector<MonitorInfo> monitors;
|
2022-08-27 02:17:20 +03:00
|
|
|
EnumDisplayMonitors(nullptr, nullptr, GetDisplaysEnumCb, reinterpret_cast<LPARAM>(&monitors));
|
|
|
|
|
std::sort(begin(monitors), end(monitors), [=](const MonitorInfo& lhs, const MonitorInfo& rhs) {
|
|
|
|
|
const auto lhsSize = lhs.GetScreenSize(includeNonWorkingArea);
|
|
|
|
|
const auto rhsSize = rhs.GetScreenSize(includeNonWorkingArea);
|
|
|
|
|
|
|
|
|
|
return lhsSize < rhsSize;
|
2019-09-04 18:26:26 +02:00
|
|
|
});
|
2020-03-05 13:07:06 +03:00
|
|
|
return monitors;
|
2019-09-04 18:26:26 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-27 02:17:20 +03:00
|
|
|
MonitorInfo MonitorInfo::GetPrimaryMonitor()
|
2020-04-15 12:34:11 +02:00
|
|
|
{
|
2022-08-27 02:17:20 +03:00
|
|
|
auto monitors = MonitorInfo::GetMonitors(false);
|
|
|
|
|
if (monitors.size() > 1)
|
2020-03-05 13:07:06 +03:00
|
|
|
{
|
2022-08-27 02:17:20 +03:00
|
|
|
for (auto monitor : monitors)
|
|
|
|
|
{
|
|
|
|
|
if (monitor.IsPrimary())
|
|
|
|
|
return monitor;
|
|
|
|
|
}
|
2020-03-05 13:07:06 +03:00
|
|
|
}
|
2022-08-27 02:17:20 +03:00
|
|
|
return monitors[0];
|
2019-09-04 18:26:26 +02:00
|
|
|
}
|
2024-12-06 06:02:17 +08:00
|
|
|
|
|
|
|
|
MonitorInfo MonitorInfo::GetFromWindow(const HWND window)
|
|
|
|
|
{
|
|
|
|
|
auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
|
|
|
|
return MonitorInfo::MonitorInfo(monitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MonitorInfo MonitorInfo::GetFromPoint(int32_t x, int32_t y)
|
|
|
|
|
{
|
|
|
|
|
auto monitor = MonitorFromPoint(POINT{ x, y }, MONITOR_DEFAULTTONULL);
|
|
|
|
|
return MonitorInfo::MonitorInfo(monitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MonitorInfo::Size MonitorInfo::GetSize(const MONITORINFOEX& monitorInfoEx)
|
|
|
|
|
{
|
|
|
|
|
Size size = {};
|
|
|
|
|
|
|
|
|
|
auto device_name = PCTSTR(monitorInfoEx.szDevice);
|
|
|
|
|
|
|
|
|
|
auto hdc = CreateDC(device_name, nullptr, nullptr, nullptr);
|
|
|
|
|
size.width_mm = static_cast<float>(GetDeviceCaps(hdc, HORZSIZE));
|
|
|
|
|
size.height_mm = static_cast<float>(GetDeviceCaps(hdc, VERTSIZE));
|
|
|
|
|
if (hdc != nullptr)
|
|
|
|
|
{
|
|
|
|
|
ReleaseDC(nullptr, hdc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto monitor = &monitorInfoEx.rcMonitor;
|
|
|
|
|
size.width_logical = static_cast<uint32_t>(monitor->right - monitor->left);
|
|
|
|
|
size.height_logical = static_cast<uint32_t>(monitor->bottom - monitor->top);
|
|
|
|
|
|
|
|
|
|
DEVMODE dev_mode = { .dmSize = sizeof DEVMODE };
|
|
|
|
|
if (EnumDisplaySettingsEx(device_name, ENUM_CURRENT_SETTINGS, &dev_mode, EDS_RAWMODE))
|
|
|
|
|
{
|
|
|
|
|
size.width_physical = dev_mode.dmPelsWidth;
|
|
|
|
|
size.height_physical = dev_mode.dmPelsHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MonitorInfo::Size MonitorInfo::GetSize() const
|
|
|
|
|
{
|
|
|
|
|
if (this->handle)
|
|
|
|
|
{
|
|
|
|
|
return MonitorInfo::GetSize(this->info);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return MonitorInfo::Size{};
|
|
|
|
|
}
|
|
|
|
|
}
|