Получение фактического экрана dpi/ppi под окнами

Я хотел бы получить фактическое разрешение экрана dpi/ppi, а не параметр dpi, используемый для шрифта в C++.

Я пробовал со следующими кодами:

Версия 1, сообщает 72 dpi, что неправильно.

SetProcessDPIAware(); //true
HDC screen = GetDC(NULL);
double hSize = GetDeviceCaps(screen, HORZSIZE);
double vSize = GetDeviceCaps(screen, VERTSIZE);
double hRes = GetDeviceCaps(screen, HORZRES);
double vRes = GetDeviceCaps(screen, VERTRES);
double hPixelsPerInch = hRes / hSize * 25.4;
double vPixelsPerInch = vRes / vSize * 25.4;
ReleaseDC(NULL, screen);
return (hPixelsPerInch + vPixelsPerInch) * 0.5;

Версия 2, сообщает 96 точек на дюйм, который является настройкой шрифта в Windows для шрифта, но не фактическое разрешение экрана.

SetProcessDPIAware(); //true
HDC screen = GetDC(NULL);
double hPixelsPerInch = GetDeviceCaps(screen,LOGPIXELSX);
double vPixelsPerInch = GetDeviceCaps(screen,LOGPIXELSY);
ReleaseDC(NULL, screen);
return (hPixelsPerInch + vPixelsPerInch) * 0.5;

4 ответа

Я честно смущен ответами здесь.

У Microsoft есть метод GetDpiForMonitor:

https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx

И мониторы действительно выставляют свои физические размеры инструментам. Вы можете прочитать ширину и высоту ваших мониторов в сантиметрах, используя инструмент HWiNFO64. Так что, если они получают его (DDI?), Вполне понятно, что вы можете получить доступ к этой информации самостоятельно.

Даже в другой публикации о переполнении стека упоминается использование WmiMonitorBasicDisplayParams для получения данных.

Как получить размер монитора

Таким образом, верхний пост является плоским, 100%, неправильно.

То, что вы просите, к сожалению, невозможно в общем случае.

Windows не знает физического размера экрана. Windows может знать, что ваш экран имеет 1024x768 пикселей, но он не знает, насколько большой экран на самом деле. Вы можете вытащить кабель из старого 13-дюймового экрана и подключить его к 19-дюймовому монитору без изменения разрешения. DPI будет другим, но Windows не заметит, что вы сменили мониторы.

Вы можете получить истинные физические размеры и DPI для принтера (при условии, что драйвер не лежит), но не для экрана. По крайней мере, не надежно.

ОБНОВЛЕНО

Как отмечали другие, существуют стандарты двусторонней связи между новыми мониторами и ОС (EDID), которые могут сделать эту информацию доступной для некоторых устройств. Но я еще не нашел монитор, который предоставляет эту информацию.

Даже если бы EDID были доступны повсеместно, в общем случае это все равно невозможно решить, так как дисплей может быть видеопроектором, где DPI будет зависеть от масштаба, фокуса, типа объектива и расстояния проекции. Крайне маловероятно, что проектор будет знать расстояние проекции, поэтому у него нет возможности сообщить фактическое значение DPI.

Обнаружено, что получение информации DPI дает точное значение, используя метод ниже.

ID2D1Factory* m_pDirect2dFactory;
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pDirect2dFactory);
FLOAT dpiX, dpiY;
m_pDirect2dFactory->GetDesktopDpi( &dpiX, &dpiY );

Я думаю, что вы после того, как:

GetDeviceCaps(hdcScreen, LOGPIXELSX); GetDeviceCaps(hdcScreen, LOGPIXELSY);

Другие вопросы по тегам