¿Cómo obtener el tamaño físico correcto del monitor?

¿Cómo puedo obtener el tamaño de la pantalla en centímetros o pulgadas?

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 monitores múltiples.

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

Encontré otra manera. El tamaño físico del monitor se almacena en el EDID y Windows casi siempre es una copia de su valor en el registro. Si puede analizar EDID, puede leer el ancho 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; } 

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.

Piénsese, por ejemplo, en los dispositivos de proyección, donde el tamaño físico depende de la distancia al área de proyección que no se puede determinar mediante progtwigción, ya que el proyector de video se puede mover manualmente en cualquier momento.

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

Especialmente en una situación de múltiples monitores con diferentes pantallas (por ejemplo, una pantalla LCD de 19 “y 24”). 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 progtwigs han necesitado esta información exactamente en el pasado, han mostrado un medidor en la pantalla, y el usuario ha sostenido un trozo de papel en la pantalla y mide el ancho del papel con el medidor. Dado que el papel es de 8.5 “o A4, entonces conoce el ancho, y puede usar el número que ingresan para calcular el PPP real para una pantalla determinada. Puede que necesite que lo haga para cada monitor en una configuración de múltiples monitores.

-Adán

Navegar por el registro directamente no solo no es compatible, sino que falla para dispositivos diferentes a los tuyos. (por ejemplo, aquel en el que probé tu código).

A diferencia de lo que algunos dicen aquí, hay 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 configuración tediosa involucrada – El código de muestra está aquí .


EDITAR: múltiples monitores se manejan aquí .

Windows Vista y la nueva función de soporte superior GetMonitorDisplayAreaSize () http://msdn.microsoft.com/en-us/library/ms775210%28VS.85%29.aspx

Actualización: no funciona correctamente

Puede solicitar LOGPIXELSX desde GetDeviceCaps para obtener el DPI para la pantalla, aunque generalmente devolverá 96. Consulte también este artículo de MSDN sobre cómo escribir aplicaciones compatibles con DPI .

Puede obtener EDID desde el registro.