Как определить собственное разрешение экрана или коэффициент масштабирования дополнительного монитора в Windows 10
Есть два монитора: вторичный слева от первичного. Решения:
Primary: 2560*1440 scaling 100%
Secondary: 1920*1200 scaling 150%
При запуске программы это делает EnumDisplayMonitors
который дает следующие RECTs:
Primary: 0,0,2560,1440
Secondary: -1920,0,-640,800
Также я попробовал код:
int width, height;
RECT rect = { -1920, 0, -640, 800 };
SystemParametersInfoA(SPI_SETWORKAREA, 0, &rect, 0);
width = GetSystemMetrics(SM_CXSCREEN);
height = GetSystemMetrics(SM_CYSCREEN);
но width
а также height
всегда иметь размеры основного монитора.
Как определить собственное разрешение вторичного монитора 1920*1200
или коэффициент масштабирования 150%
?
Это тоже не работает, дает 1280*800
:
BOOL CALLBACK EnumMonitorCallback(HMONITOR hMon, HDC hdc, LPRECT rect, LPARAM param)
{
MONITORINFOEXA mi;
mi.cbSize = sizeof(mi);
GetMonitorInfoA(hMon, &mi);
HDC dc = CreateDCA("DISPLAY", mi.szDevice, NULL, NULL);
int width = GetDeviceCaps(dc, HORZRES);
int height = GetDeviceCaps(dc, VERTRES);
DeleteDC(dc);
return TRUE;
}
4 ответа
Ваше приложение должно демонстрировать высокую чувствительность DPI, чтобы ОС не пыталась лгать о разрешениях, пытаясь имитировать унаследованную среду. Затем перечисление DXGI возвращает вам запрошенные данные.
Вы можете быстро проверить это с помощью инструмента в нижней части этого блога. У меня есть два монитора с разрешением 3840x2160, первый с масштабированием 175%, а второй с 150%. Обратите внимание на "координаты рабочего стола" и "DPI DPI" в распечатке ниже:
#### Output: \\.\DISPLAY4
* Desktop Coordinates: (0, 0) - (3840, 2160); 3840 x 2160
* Attached To Desktop: 1
* Rotation: DXGI_MODE_ROTATION_IDENTITY
* Monitor: 0x000100B3
* Physical Monitors: LG ULTRA HD(DisplayPort) (0x00000000)
* Bits Per Color: 10
* Color Space: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
* Primaries, White Point: R { 0.652, 0.335 }, G { 0.305, 0.637 }, B { 0.148, 0.062 }; { 0.313, 0.329 }
* Luminance: Min 0.500, Max 270.000, Max Full Frame 270.000
* Hardware Composition Support: DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_FULLSCREEN | DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_CURSOR_STRETCHED
* Monitor DPI, MDT_EFFECTIVE_DPI: 168, 168 ; System DPI 168
* Monitor DPI, MDT_ANGULAR_DPI: 161, 160
* Monitor DPI, MDT_RAW_DPI: 162, 161
…
#### Output: \\.\DISPLAY5
* Desktop Coordinates: (3840, 0) - (7680, 2160); 3840 x 2160
* Attached To Desktop: 1
* Rotation: DXGI_MODE_ROTATION_IDENTITY
* Monitor: 0x000200B1
* Physical Monitors: LG ULTRA HD(DisplayPort) (0x00000000)
* Bits Per Color: 10
* Color Space: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
* Primaries, White Point: R { 0.652, 0.335 }, G { 0.305, 0.637 }, B { 0.148, 0.062 }; { 0.313, 0.329 }
* Luminance: Min 0.500, Max 270.000, Max Full Frame 270.000
* Hardware Composition Support: DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_FULLSCREEN | DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_CURSOR_STRETCHED
* Monitor DPI, MDT_EFFECTIVE_DPI: 144, 144 ; System DPI 168
* Monitor DPI, MDT_ANGULAR_DPI: 161, 160
* Monitor DPI, MDT_RAW_DPI: 162, 161
GetSystemMetrics
призывает для SM_CXSCREEN
или же SM_CYSCREEN
вернет разрешение основного дисплея. Чтобы получить разрешение для вторичных мониторов, необходимо использовать GetDeviceCaps
или API для нескольких мониторов.
Используйте функцию GetScaleFactorForMonitor, чтобы получить коэффициент масштабирования.
Попробуй это:
void GetMonitorRealResolution(HMONITOR monitor, int* pixelsWidth, int* pixelsHeight)
{
MONITORINFOEX info = { sizeof(MONITORINFOEX) };
winrt::check_bool(GetMonitorInfo(monitor, &info));
DEVMODE devmode = {};
devmode.dmSize = sizeof(DEVMODE);
winrt::check_bool(EnumDisplaySettings(info.szDevice, ENUM_CURRENT_SETTINGS, &devmode));
*pixelsWidth = devmode.dmPelsWidth;
*pixelsHeight = devmode.dmPelsHeight;
}
Он вернет это собственное разрешение в любом случае, даже если осведомленность о DPI процесса заставит ОС лгать.