屏幕像素分辨率,单位mm

时间:2010-01-04 14:08:02

标签: c++ c mfc winapi

使用Win32 API可以获得mm的屏幕像素分辨率吗?我有一个应用程序显示0.34722222222222222作为我的1280x1024显示器上96dpi的值。但我无法弄清楚它是如何获得这个价值的。任何线索都会有所帮助。如果需要,我也可以使用MFC。

修改 对不起,我所说的软件没有使用当前的屏幕分辨率。它是从一些配置文件中读取的。

6 个答案:

答案 0 :(得分:8)

获取显示器的设备上限为您提供像素和mm的尺寸:

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

答案 1 :(得分:4)

每像素0.34722222222222222毫米实际上相当于大约73dpi。 Windows使用两个标准设置72dpi和96dpi,但也支持自定义值。这些是名义价值,可能与物理屏幕没有任何关系。例如,可以将物理96dpi屏幕设置为72dpi,这将影响各种应用程序中图像和布局的缩放以及系统字体和图标的大小。

Windows的默认值为72dpi,我发现某些应用程序(通常在“关于”和对话框中)在设置为其他值时无法正确呈现。如果您的应用程序报告0.34,则无论物理分辨率如何,它都可能设置为72dpi或自定义值。设置为与物理分辨率匹配时,例如设置为100%缩放级别时的页面宽度将与实际纸张大小相匹配。由于此指标可由最终用户设置,因此与实际分辨率无直接关系。

答案 2 :(得分:2)

关于在MSDN中编写“DPI感知”应用程序的部分对于有兴趣为可变显示分辨率提供合适支持的人来说非常值得一读。用于获取相关设备的API&系统指标描述为here

答案 3 :(得分: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;
}

答案 4 :(得分:0)

使用GetDC功能获取显示器上的句柄,然后调用GetDeviceCaps功能以毫米为单位获取显示器的大小。例如:

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

答案 5 :(得分:0)

以下代码段证明可以提供最佳效果。

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