monitors.cpp
1 #include "monitors.h" 2 3 #include <algorithm> 4 5 Box MonitorInfo::GetScreenSize(const bool includeNonWorkingArea) const 6 { 7 return includeNonWorkingArea ? Box{ info.rcMonitor } : Box{ info.rcWork }; 8 } 9 10 bool MonitorInfo::IsPrimary() const 11 { 12 return static_cast<bool>(info.dwFlags & MONITORINFOF_PRIMARY); 13 } 14 15 MonitorInfo::MonitorInfo(HMONITOR h) : 16 handle{ h } 17 { 18 info.cbSize = sizeof(MONITORINFOEX); 19 GetMonitorInfoW(handle, &info); 20 } 21 22 static BOOL CALLBACK GetDisplaysEnumCb(HMONITOR monitor, HDC /*hdc*/, LPRECT /*rect*/, LPARAM data) 23 { 24 auto* monitors = reinterpret_cast<std::vector<MonitorInfo>*>(data); 25 monitors->emplace_back(monitor); 26 return true; 27 }; 28 29 std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool includeNonWorkingArea) 30 { 31 std::vector<MonitorInfo> monitors; 32 EnumDisplayMonitors(nullptr, nullptr, GetDisplaysEnumCb, reinterpret_cast<LPARAM>(&monitors)); 33 std::sort(begin(monitors), end(monitors), [=](const MonitorInfo& lhs, const MonitorInfo& rhs) { 34 const auto lhsSize = lhs.GetScreenSize(includeNonWorkingArea); 35 const auto rhsSize = rhs.GetScreenSize(includeNonWorkingArea); 36 37 return lhsSize < rhsSize; 38 }); 39 return monitors; 40 } 41 42 MonitorInfo MonitorInfo::GetPrimaryMonitor() 43 { 44 auto monitors = MonitorInfo::GetMonitors(false); 45 if (monitors.size() > 1) 46 { 47 for (auto monitor : monitors) 48 { 49 if (monitor.IsPrimary()) 50 return monitor; 51 } 52 } 53 return monitors[0]; 54 } 55 56 MonitorInfo MonitorInfo::GetFromWindow(const HWND window) 57 { 58 auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL); 59 return MonitorInfo::MonitorInfo(monitor); 60 } 61 62 MonitorInfo MonitorInfo::GetFromPoint(int32_t x, int32_t y) 63 { 64 auto monitor = MonitorFromPoint(POINT{ x, y }, MONITOR_DEFAULTTONULL); 65 return MonitorInfo::MonitorInfo(monitor); 66 } 67 68 MonitorInfo::Size MonitorInfo::GetSize(const MONITORINFOEX& monitorInfoEx) 69 { 70 Size size = {}; 71 72 auto device_name = PCTSTR(monitorInfoEx.szDevice); 73 74 auto hdc = CreateDC(device_name, nullptr, nullptr, nullptr); 75 size.width_mm = static_cast<float>(GetDeviceCaps(hdc, HORZSIZE)); 76 size.height_mm = static_cast<float>(GetDeviceCaps(hdc, VERTSIZE)); 77 if (hdc != nullptr) 78 { 79 ReleaseDC(nullptr, hdc); 80 } 81 82 auto monitor = &monitorInfoEx.rcMonitor; 83 size.width_logical = static_cast<uint32_t>(monitor->right - monitor->left); 84 size.height_logical = static_cast<uint32_t>(monitor->bottom - monitor->top); 85 86 DEVMODE dev_mode = { .dmSize = sizeof DEVMODE }; 87 if (EnumDisplaySettingsEx(device_name, ENUM_CURRENT_SETTINGS, &dev_mode, EDS_RAWMODE)) 88 { 89 size.width_physical = dev_mode.dmPelsWidth; 90 size.height_physical = dev_mode.dmPelsHeight; 91 } 92 93 return size; 94 } 95 96 MonitorInfo::Size MonitorInfo::GetSize() const 97 { 98 if (this->handle) 99 { 100 return MonitorInfo::GetSize(this->info); 101 } 102 else 103 { 104 return MonitorInfo::Size{}; 105 } 106 }