简体   繁体   English

屏幕像素分辨率 (mm)

[英]Screen Pixel Resolution in mm

Is it possible to get the screen pixel resolution in mm using Win32 APIs ?是否可以使用 Win32 API 以毫米为单位获得屏幕像素分辨率? I have an application which is showing 0.3472222222222222 as the value for this on my 1280x1024 monitor with 96 dpi .我有一个应用程序,它在 96 dpi 的 1280x1024 显示器上显示 0.3472222222222222 作为此值。 But I am not able to find out how it got this value.但我无法找出它是如何获得这个价值的。 Any clues will be helpful.任何线索都会有所帮助。 I can use MFC also if required.如果需要,我也可以使用 MFC。

EDIT Sorry for the confusion, the software I am talking about was not using the current screen resolution.编辑抱歉造成混乱,我正在谈论的软件没有使用当前的屏幕分辨率。 It was reading it from some config file.它正在从一些配置文件中读取它。

Get device caps for the monitor gives you both size in pixels and mm thus:获取显示器的设备上限为您提供像素和毫米的尺寸,因此:

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

0.3472222222222222 mm per pixel is in fact equivalent to approximately 73 dpi.每像素 0.3472222222222222 毫米实际上相当于大约 73 dpi。 Windows uses two standard settings 72dpi and 96dpi, but custom values are also supported. Windows 使用两个标准设置 72dpi 和 96dpi,但也支持自定义值。 These are nominal values and may not bear any relationship to the physical screen.这些是标称值,可能与物理屏幕没有任何关系。 For example it is possible to have a physically 96dpi screen set to 72dpi, and this will affect the scaling of images and layout in various applications as well as the size of system fonts and icons.例如,可以将物理 96dpi 屏幕设置为 72dpi,这将影响各种应用程序中图像和布局的缩放以及系统字体和图标的大小。

The default for Windows is 72dpi, and I have found that some applications (often in their "About" and dialog boxes) do not render correctly when set to other values. Windows 的默认值为 72dpi,我发现某些应用程序(通常在其“关于”和对话框中)在设置为其他值时无法正确呈现。 If your application reports 0.34, it seems likely that it is set to 72dpi or a custom value regardless of physical resolution.如果您的应用程序报告 0.34,则无论物理分辨率如何,它似乎都设置为 72dpi 或自定义值。 When set to match the physical resolution, the page width in say Word for example when set to a zoom level of 100% will match the physical paper size.当设置为匹配物理分辨率时,例如 Word 中的页面宽度设置为 100% 缩放级别时将匹配物理纸张大小。 Since this metric can be set by the end user, it is not directly related to the actual resolution.由于该指标可由最终用户设置,因此与实际分辨率没有直接关系。

The section on writing "DPI-aware" applications in MSDN is well worth a read for anyone interested in providing decent support for variable display resolutions.MSDN 中有关编写“DPI 感知”应用程序的部分非常值得任何有兴趣为可变显示分辨率提供适当支持的人阅读。 APIs for obtaining relevant device & system metrics are described here . 此处描述用于获取相关设备和系统指标的 API。

Use the GetDC function to get a handle on the monitor, then call the GetDeviceCaps function to get the size of the monitor in millimeters.使用GetDC函数获取监视器的句柄,然后调用GetDeviceCaps函数获取以毫米为单位的监视器大小。 For example:例如:

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

The below code snippet proved to provide the best result.下面的代码片段被证明提供了最好的结果。

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

I also had similar problems on Windows 7 and try different approaches but couldn't find the right answer until I found this: http://ofekshilon.com/2011/11/13/reading-monitor-physical-dimensions-or-getting-the-edid-the-right-way/我在Windows 7上也遇到了类似的问题并尝试了不同的方法,但直到我找到这个才找到正确的答案: http : //ofekshilon.com/2011/11/13/reading-monitor-physical-dimensions-or-getting -edid-the-right-way/

It works for me for different screen sizes!它适用于不同的屏幕尺寸!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM