2010-01-04 2 views
5

Возможно ли получить разрешение экрана в мм с использованием API Win32? У меня есть приложение, которое показывает 0.3472222222222222 в качестве значения для этого на моем мониторе 1280x1024 с разрешением 96 точек на дюйм. Но я не могу узнать, как это получилось. Любые подсказки будут полезны. Я также могу использовать MFC, если это необходимо.Разрешение экрана в мм

EDIT Извините за недоразумение, программное обеспечение, о котором я говорю, не использовало текущее разрешение экрана. Он читал его из некоторого файла конфигурации.

+0

25/72 = 0.347222. Не знаю, откуда у вас 25 человек. –

ответ

0

Используйте функцию GetDC, чтобы получить ручку на мониторе, затем вызовите функцию GetDeviceCaps, чтобы получить размер монитора в миллиметрах. Например:

HDC monitor = GetDC(NULL); 
int horizSize = GetDeviceCaps(monitor, HORZSIZE); 
int vertSize = GetDeviceCaps(monitor, VERTSIZE); 
4

0,3472222222222222 мм на пиксель на самом деле эквивалентно приблизительно 73 dpi. Windows использует два стандартных параметра 72dpi и 96dpi, но также поддерживаются пользовательские значения. Они являются номинальными значениями и не могут иметь никакого отношения к физическому экрану. Например, можно установить физически 96-экранный экран с разрешением 72dpi, что повлияет на масштабирование изображений и макетов в различных приложениях, а также размер системных шрифтов и значков.

По умолчанию для Windows 72dpi, и я обнаружил, что некоторые приложения (часто в их «О» и диалоговые окна) не отображаются правильно, если установлены другие значения. Если ваше приложение сообщает 0.34, кажется вероятным, что оно настроено на 72dpi или пользовательское значение независимо от физического разрешения. Если установлено, чтобы соответствовать физическому разрешению, ширина страницы в слове Word, например, при установке уровня масштабирования 100%, будет соответствовать физическому размеру бумаги. Поскольку эта метрика может быть задана конечным пользователем, она напрямую не связана с фактическим разрешением.

8

колпачки Get устройства для монитора дает вам как размер в пикселях и мм, таким образом:

HDC screen = GetDC(NULL); 
int hSize=GetDeviceCaps(screen,HORZSIZE); 
int hRes=GetDeviceCaps(screen,HORZRES); 
float PixelsPerMM=(float)hRes/hSize; // pixels per millimeter 
float PixelsPerInch=PixelsPerMM*25.4; //dpi 
+5

, но это логические дюймы, не так ли? – Ponting

+1

Есть 25,4 миллиметра на дюйм - не 2,54. – Spire

+0

Спасибо - отредактировано как правильное – Elemental

2

В разделе по написанию «DPI-Aware» приложений в MSDN хорошо стоит прочитать для тех, кто заинтересован в обеспечении достойного поддержка разрешений с переменным отображением. API для получения соответствующего устройства & описаны системные показатели here.

0

Приведенный ниже фрагмент кода показал лучший результат.

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

Я также имел аналогичные проблемы на Windows 7 и попробовать различные подходы, но не смог найти правильный ответ, пока я не нашел это: http://ofekshilon.com/2011/11/13/reading-monitor-physical-dimensions-or-getting-the-edid-the-right-way/

Это работает для меня для различных размеров экрана!

#include <atlstr.h> 
#include <SetupApi.h> 
#pragma comment(lib, "setupapi.lib") 

#define NAME_SIZE 128 

const GUID GUID_CLASS_MONITOR = {0x4d36e96e, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}; 

// Assumes hDevRegKey is valid 
bool GetMonitorSizeFromEDID(const HKEY hDevRegKey, short& WidthMm, short& HeightMm) 
{ 
    DWORD dwType, AcutalValueNameLength = NAME_SIZE; 
    TCHAR valueName[NAME_SIZE]; 

    BYTE EDIDdata[1024]; 
    DWORD edidsize=sizeof(EDIDdata); 

    for (LONG i = 0, retValue = ERROR_SUCCESS; retValue != ERROR_NO_MORE_ITEMS; ++i) 
    { 
     retValue = RegEnumValue (hDevRegKey, i, &valueName[0], 
      &AcutalValueNameLength, NULL, &dwType, 
      EDIDdata, // buffer 
      &edidsize); // buffer size 

     if (retValue != ERROR_SUCCESS || 0 != _tcscmp(valueName,_T("EDID"))) 
      continue; 

     WidthMm = ((EDIDdata[68] & 0xF0) << 4) + EDIDdata[66]; 
     HeightMm = ((EDIDdata[68] & 0x0F) << 8) + EDIDdata[67]; 

     return true; // valid EDID found 
    } 

    return false; // EDID not found 
} 

bool GetSizeForDevID(const CString& TargetDevID, short& WidthMm, short& HeightMm) 
{ 
    HDEVINFO devInfo = SetupDiGetClassDevsEx(
     &GUID_CLASS_MONITOR, //class GUID 
     NULL, //enumerator 
     NULL, //HWND 
     DIGCF_PRESENT, // Flags //DIGCF_ALLCLASSES| 
     NULL, // device info, create a new one. 
     NULL, // machine name, local machine 
     NULL);// reserved 

    if (NULL == devInfo) 
     return false; 

    bool bRes = false; 

    for (ULONG i=0; ERROR_NO_MORE_ITEMS != GetLastError(); ++i) 
    { 
     SP_DEVINFO_DATA devInfoData; 
     memset(&devInfoData,0,sizeof(devInfoData)); 
     devInfoData.cbSize = sizeof(devInfoData); 

     if (SetupDiEnumDeviceInfo(devInfo,i,&devInfoData)) 
     { 
      HKEY hDevRegKey = SetupDiOpenDevRegKey(devInfo,&devInfoData, 
       DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); 

      if(!hDevRegKey || (hDevRegKey == INVALID_HANDLE_VALUE)) 
       continue; 

      bRes = GetMonitorSizeFromEDID(hDevRegKey, WidthMm, HeightMm); 

      RegCloseKey(hDevRegKey); 
     } 
    } 
    SetupDiDestroyDeviceInfoList(devInfo); 
    return bRes; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    short WidthMm, HeightMm; 

    DISPLAY_DEVICE dd; 
    dd.cb = sizeof(dd); 
    DWORD dev = 0; // device index 
    int id = 1; // monitor number, as used by Display Properties > Settings 

    CString DeviceID; 
    bool bFoundDevice = false; 
    while (EnumDisplayDevices(0, dev, &dd, 0) && !bFoundDevice) 
    { 
     DISPLAY_DEVICE ddMon; 
     ZeroMemory(&ddMon, sizeof(ddMon)); 
     ddMon.cb = sizeof(ddMon); 
     DWORD devMon = 0; 

     while (EnumDisplayDevices(dd.DeviceName, devMon, &ddMon, 0) && !bFoundDevice) 
     { 
      if (ddMon.StateFlags & DISPLAY_DEVICE_ACTIVE && 
       !(ddMon.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) 
      { 
       DeviceID.Format (L"%s", ddMon.DeviceID); 
       DeviceID = DeviceID.Mid (8, DeviceID.Find (L"\\", 9) - 8); 

       bFoundDevice = GetSizeForDevID(DeviceID, WidthMm, HeightMm); 
      } 
      devMon++; 

      ZeroMemory(&ddMon, sizeof(ddMon)); 
      ddMon.cb = sizeof(ddMon); 
     } 

     ZeroMemory(&dd, sizeof(dd)); 
     dd.cb = sizeof(dd); 
     dev++; 
    } 

    return 0; 
}