2009-02-23 8 views
9

¿Cómo puedo obtener el tamaño de la pantalla en centímetros o pulgadas?¿Cómo obtener el tamaño físico correcto del monitor?

Este código no siempre funciona correctamente:

HDC hdc = CreateDC(_T("DISPLAY"),dd.DeviceName,NULL,NULL); 
int width = GetDeviceCaps(hdc, HORZSIZE); 
int height = GetDeviceCaps(hdc, VERTSIZE); 
ReleaseDC(0, hdc) 

Especialmente para la configuración de varios monitores.

Actualización: Necesito obtener el tamaño solo para monitores ordinarios, que tienen un tamaño físico constante.

Respuesta

17

he encontrado otra manera. el tamaño físico de la pantalla se almacenan en el EDID y Windows son casi siempre copias de su valor en el registro. Si se puede analizar EDID, se puede leer la la anchura y la altura del monitor en centímetros

actualización:. código Agregado

BOOL GetMonitorDevice(TCHAR* adapterName, DISPLAY_DEVICE &ddMon) 
{ 
    DWORD devMon = 0; 

    while (EnumDisplayDevices(adapterName, devMon, &ddMon, 0)) 
    { 
     if (ddMon.StateFlags & DISPLAY_DEVICE_ACTIVE && 
      ddMon.StateFlags & DISPLAY_DEVICE_ATTACHED) // for ATI, Windows XP 
      break; 

     devMon++; 
    } 

    if (ddMon.DeviceString[0] == '\0') 
    { 
     EnumDisplayDevices(adapterName, 0, &ddMon, 0); 
     if (ddMon.DeviceString[0] == '\0') 
      _tcscpy_s(ddMon.DeviceString, _T("Default Monitor")); 
    } 
    return ddMon.DeviceID[0] != '\0'; 
} 

BOOL GetMonitorSizeFromEDID(TCHAR* adapterName, DWORD& Width, DWORD& Height) 
{ 
    DISPLAY_DEVICE ddMon; 
    ZeroMemory(&ddMon, sizeof(ddMon)); 
    ddMon.cb = sizeof(ddMon); 

    //read edid 
    bool result = false; 
    Width = 0; 
    Height = 0; 
    if (GetMonitorDevice(adapterName, ddMon)) 
    { 
     TCHAR model[8]; 
     TCHAR* s = _tcschr(ddMon.DeviceID, '\\') + 1; 
     size_t len = _tcschr(s, '\\') - s; 
     if (len >= _countof(model)) 
      len = _countof(model) - 1; 
     _tcsncpy_s(model, s, len); 

     TCHAR *path = _tcschr(ddMon.DeviceID, '\\') + 1; 
     TCHAR str[MAX_PATH] = _T("SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\"); 
     _tcsncat_s(str, path, _tcschr(path, '\\')-path); 
     path = _tcschr(path, '\\') + 1; 
     HKEY hKey; 
     if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, str, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 
     { 
      DWORD i = 0; 
      DWORD size = MAX_PATH; 
      FILETIME ft; 
      while(RegEnumKeyEx(hKey, i, str, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS) 
      { 
       HKEY hKey2; 
       if(RegOpenKeyEx(hKey, str, 0, KEY_READ, &hKey2) == ERROR_SUCCESS) 
       { 
        size = MAX_PATH; 
        if(RegQueryValueEx(hKey2, _T("Driver"), NULL, NULL, (LPBYTE)&str, &size) == ERROR_SUCCESS) 
        { 
         if (_tcscmp(str, path) == 0) 
         { 
          HKEY hKey3; 
          if(RegOpenKeyEx(hKey2, _T("Device Parameters"), 0, KEY_READ, &hKey3) == ERROR_SUCCESS) 
          { 
           BYTE EDID[256]; 
           size = 256; 
           if(RegQueryValueEx(hKey3, _T("EDID"), NULL, NULL, (LPBYTE)&EDID, &size) == ERROR_SUCCESS) 
           { 
            DWORD p = 8; 
            TCHAR model2[9]; 

            char byte1 = EDID[p]; 
            char byte2 = EDID[p+1]; 
            model2[0]=((byte1 & 0x7C) >> 2) + 64; 
            model2[1]=((byte1 & 3) << 3) + ((byte2 & 0xE0) >> 5) + 64; 
            model2[2]=(byte2 & 0x1F) + 64; 
            _stprintf(model2 + 3, _T("%X%X%X%X"), (EDID[p+3] & 0xf0) >> 4, EDID[p+3] & 0xf, (EDID[p+2] & 0xf0) >> 4, EDID[p+2] & 0x0f); 
            if (_tcscmp(model, model2) == 0) 
            { 
             Width = EDID[22]; 
             Height = EDID[21]; 
             result = true; 
            } 
            else 
            { 
             // EDID incorrect 
            } 
           } 
           RegCloseKey(hKey3); 
          } 
         } 
        } 
        RegCloseKey(hKey2); 
       } 
       i++; 
      } 
      RegCloseKey(hKey); 
     } 
    } 

    return result; 
} 
+0

Siempre he tenido curiosidad sobre el canal de comunicación entre un monitor y la interfaz gráfica. ¡Gracias por darme el nombre! –

+2

Un poco más de sangría estaría bien. Eso me aseguraría de no poder ver las líneas completas en la pantalla de mi computadora de 30 '. –

+0

@devo sí, está demasiado anidado. Recomiendo refactorizar este código si planea usarlo – Earlz

8

No es posible determinar el tamaño físico exacto de un dispositivo de video en Windows, ya que depende de bastantes variables (por ejemplo, perfil de monitor activo, resolución horizontal/vertical, tamaño de píxel, etc.), algunas de las cuales no están bajo el control de la computadora.

pensar por ejemplo de dispositivos de proyección, donde el tamaño físico depende de la distancia a la zona de proyección que no se puede determinar mediante programación, como el proyector de vídeo podría ser movido manualmente en cualquier momento.

+6

+1, Tendrías que preguntarte de qué serviría conocer el tamaño físico en lugar de la resolución real. – user7116

+0

horicontal => horizontal – SAMills

+0

/me piensa que Kosi2801 acaba de aparecer como alemán, al usar la palabra "beamer". Realmente no significa "video proyector" en inglés. :) – unwind

5

No se puede obtener el tamaño real exacto; se puede obtener una aproximación que depende de la configuración de DPI en Windows y la resolución de la pantalla, pero no se puede garantizar que sea del tamaño real.

especialmente en una situación de varios monitores con pantallas diferentes (por ejemplo un CRT y 24" LCD de 19" pulgadas). Además, si la pantalla es CRT, entonces la medida es la medición del tubo, y no el área de visualización.

Cuando los programas han necesitado esta información exactamente en el pasado, han mostrado un indicador en pantalla, y el usuario ha sostenido una hoja de papel en la pantalla y mide el ancho del papel con el medidor. Dado el papel es de 8,5" o A4 entonces usted sabe el ancho, y se puede usar el número que de entrada para averiguar el valor real de PPP para una pantalla dada. Es posible que necesite tener a hacer eso para cada monitor en una configuración de varios monitores.

-Adam

6

Navegando por el Registro directamente no sólo es compatible, pero en realidad falla para dispositivos diferentes a la suya. (por ejemplo, aquel en el que probé tu código).

A diferencia de lo que algunos dicen aquí, es una forma oficial de acceder a la ruta de la clave EDID: mediante el uso de la API de configuración, y específicamente SetupDiOpenDevRegKey.

Hay una instalación tediosa involucrada - Sample code is here.


EDITAR: múltiples monitores se manejan here.

+0

Su código no funciona para múltiples monitores ya que GetsizeForDevID ignora el dispositivo usado, siempre recupera el tamaño del último. El tamaño de la primera siempre se ignora. – Samuel

Cuestiones relacionadas