2010-01-04 8 views
5

¿Es posible obtener la resolución de píxel de la pantalla en mm con las API de Win32? Tengo una aplicación que muestra 0.3472222222222222 como el valor para esto en mi monitor 1280x1024 con 96 ppp. Pero no puedo descubrir cómo obtuvo este valor. Cualquier pista será útil. Puedo usar MFC también si es necesario.Resolución de píxeles de pantalla en mm

EDIT Disculpe la confusión, el software del que estoy hablando no usaba la resolución de pantalla actual. Lo estaba leyendo desde algún archivo de configuración.

+0

25/72 = 0.347222. No tengo idea de dónde sacaste 25. –

Respuesta

0

Utilice la función GetDC para obtener un control sobre el monitor, luego llame a la función GetDeviceCaps para obtener el tamaño del monitor en milímetros. Por ejemplo:

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

0.3472222222222222 mm por píxel es, de hecho, equivalente a aproximadamente 73 ppp. Windows usa dos configuraciones estándar, 72 ppp y 96 ppp, pero también admite valores personalizados. Estos son valores nominales y pueden no tener ninguna relación con la pantalla física. Por ejemplo, es posible tener una pantalla física de 96 ppp configurada en 72 ppp, y esto afectará la escala de las imágenes y el diseño en varias aplicaciones, así como el tamaño de las fuentes y los iconos del sistema.

El valor predeterminado para Windows es 72 ppp, y he encontrado que algunas aplicaciones (a menudo en su "Acerca de" y cuadros de diálogo) no se representan correctamente cuando se establece en otros valores. Si su aplicación informa 0.34, parece probable que esté configurada en 72 ppp o un valor personalizado independientemente de la resolución física. Cuando se configura para que coincida con la resolución física, el ancho de la página en Word, por ejemplo, cuando se establece en un nivel de zoom del 100%, coincidirá con el tamaño del papel físico. Dado que esta métrica puede ser configurada por el usuario final, no está directamente relacionada con la resolución real.

8

tapas Get dispositivo para el monitor que da tanto en tamaño en píxeles y milímetros así:

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

pero esas son pulgadas lógicas ¿no? – Ponting

+1

Hay 25.4 milímetros por pulgada, no 2.54. – Spire

+0

Gracias - corregido para ser correcto – Elemental

2

La sección de escribir aplicaciones "DPI-Aware" en MSDN está bien vale la pena leer para cualquier persona interesada en proporcionar decente soporte para resoluciones de visualización variables. Las API para obtener las métricas del sistema del dispositivo & se describen en here.

0

El siguiente fragmento de código demostró proporcionar el mejor resultado.

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

También tuve problemas similares en Windows 7 y probar diferentes enfoques, pero no pudo encontrar la respuesta correcta hasta que encontré esto: http://ofekshilon.com/2011/11/13/reading-monitor-physical-dimensions-or-getting-the-edid-the-right-way/

Funciona para mí para diferentes tamaños de pantalla!

#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; 
} 
Cuestiones relacionadas