2009-02-23 8 views
9

Wie kann ich die Größe des Displays in Zentimetern oder Zoll angeben?Wie erhält man die korrekte physische Größe des Monitors?

Dieser Code funktioniert nicht immer korrekt funktioniert:

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

Speziell für Multi-Monitor-Konfiguration.

Update: Ich brauche die Größe nur für normale Monitore, die eine konstante physikalische Größe haben.

Antwort

17

fand ich eine andere Art und Weise. die physikalische Größe des Monitors in der EDID gespeichert sind, und Windows sind fast immer Kopien seines Wertes in der Registrierung. Wenn Sie EDID analysieren kann, können Sie das lesen können Breite und Höhe des Monitors in Zentimetern

Update:. Added Code

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

Ich war schon immer neugierig auf den Kommunikationskanal zwischen einem Monitor und der Grafikschnittstelle - danke für den Namen! –

+2

Ein bisschen mehr Eindruck wäre schön. Das würde sicherstellen, dass ich die vollen Zeilen auf meinem 30-Zoll-Bildschirm nicht sehen konnte. –

+0

@devo ja, es ist einfach viel zu tief verschachtelt. Ich würde empfehlen, diesen Code zu refactoring, wenn Sie es verwenden möchten – Earlz

8

Es ist nicht möglich, die genaue physikalische Größe eines Videogeräts unter Windows zu bestimmen, da dies von einer Reihe von Variablen abhängt (z. B. aktives Monitorprofil, horizontale/vertikale Auflösung, Pixelgröße usw.) sind nicht unter der Kontrolle des Computers.

Denken Sie beispielsweise an Projektorgeräte, deren physikalische Größe von der Entfernung zum Projektionsbereich abhängt, die nicht programmatisch festgelegt werden kann, da der Videoprojektor jederzeit manuell verschoben werden kann.

+6

+1, Sie müssten sich fragen, welchen Nutzen es hätte, die physikalische Größe und nicht die tatsächliche Auflösung zu kennen. – user7116

+0

horicontal => horizontal – SAMills

+0

/ich denke Kosi2801 hat sich selbst als Deutscher geoutet, indem er das Wort "Beamer" benutzt hat. Es bedeutet wirklich nicht "Videoprojektor" in Englisch. :) – unwind

5

Sie können nicht die tatsächliche genaue Größe erhalten - Sie können eine Approximation erhalten, die von der DPI-Einstellung in Windows und der Auflösung des Bildschirms abhängt, aber Sie können nicht garantieren, dass dies die tatsächliche Größe ist.

Vor allem in einer Multimonitor Situation mit verschiedenen Anzeigen (sagen wir eine 19 "CRT und 24" LCD). Wenn die Anzeige CRT ist, ist die Messung die Röhrenmessung und nicht die Anzeigefläche.

Wenn Programme diese Informationen genau in der Vergangenheit benötigt haben, haben sie eine Anzeige auf dem Bildschirm angezeigt und der Benutzer sollte ein Stück Papier auf den Bildschirm halten und die Papierbreite mit dem Messgerät messen. Wenn das Papier 8,5 "oder A4 ist, dann kennen Sie die Breite und Sie können die eingegebene Zahl verwenden, um die tatsächliche DPI für eine bestimmte Anzeige herauszufinden. Möglicherweise müssen Sie diese für jeden Monitor in einem Multimonitor-Setup tun.

-Adam

6

Das direkte Navigieren in der Registrierung wird nicht nur nicht unterstützt, sondern kann auch bei anderen Geräten fehlschlagen. (z. B. die, auf der ich Ihren Code getestet habe).

Im Gegensatz zu dem, was einige hier sagen, ist eine offizielle Art des Zugriffs auf den EDID-Schlüsselpfad: mithilfe der Setup-API und speziell SetupDiOpenDevRegKey.

Es ist einige langwierige Setup beteiligt - Sample code is here.


EDIT: mehrere Monitore werden behandelt here.

+0

Ihr Code funktioniert nicht für mehrere Monitore, da GetsizeForDevID das verwendete Gerät ignoriert und immer die Größe des letzten Geräts abruft. Die Größe des ersten wird immer ignoriert. – Samuel