当前位置:  开发笔记 > 编程语言 > 正文

如何获得正确的显示器物理尺寸?

如何解决《如何获得正确的显示器物理尺寸?》经验,为你挑选了4个好方法。

如何以厘米或英寸为单位显示显示尺寸?

此代码并不总是正常工作:

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

特别适用于多显示器配置.

更新:我需要获得普通显示器的大小,它具有恒定的物理尺寸.



1> KindDragon..:

我发现了另一种方式.监视器的物理大小存储在EDID中,Windows几乎总是在注册表中复制其值.如果您可以解析EDID,您可以以厘米为单位读取显示器的宽度和高度.

更新:添加了代码

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


哈哈,需要C 100行代码才能获得监视器大小.
此外,值得注意的是,并非所有监视器都提供EDID信息.
更多的缩进会很好.那确保我在30英寸电脑屏幕上看不到全线.
@KingDragon:我相信有些信用.https://ofekshilon.com/2014/06/19/reading-specific-monitor-dimensions/

2> Kosi2801..:

在Windows上无法确定视频设备的确切物理尺寸,因为这取决于相当多的变量(例如,有源监视器配置文件,水平/垂直分辨率,像素大小等),其中一些不在控制计算机.

想想投影仪设备的例子,其中物理尺寸取决于到投影区域的距离,这是无法以编程方式确定的,因为视频投影仪可以随时手动移动.


+1,你不得不想知道物理尺寸而不是实际分辨率的用途.
水平/垂直分辨率和像素大小究竟如何影响显示器的**物理尺寸?我已经改变了很多分辨率,而且我从未注意到我的显示器在增长或缩小.关于投影仪的确如此,但这并不意味着获得物理尺寸总是*不可能.只是说投影仪等是不可能的.

3> Ofek Shilon..:

直接导航注册表不仅不受支持,而且对于与您不同的设备实际上也会失败.(例如,我测试你的代码的那个).

不像有些什么在这里说,有访问EDID关键路径的官方途径:通过使用安装程序的API,特别SetupDiOpenDevRegKey.

这涉及一些繁琐的设置 - 示例代码在这里.


编辑:这里处理多个监视器.



4> Adam Davis..:

您无法获得真正的确切大小 - 您可以获得取决于窗口中DPI设置的近似值以及屏幕的分辨率,但您无法保证这是实际大小.

特别是在具有不同显示器的多监视器情况下(例如19"CRT和24"LCD).此外,如果显示器是CRT,则测量是管测量,而不是显示区域.

当程序在过去完全需要这些信息时,他们在屏幕上显示了一个仪表,并让用户将一张纸拿到屏幕上并用仪表测量纸张宽度.如果纸张是8.5英寸或A4,那么您就知道宽度,并且您可以使用它们输入的数字来计算给定显示器的实际DPI.您可能需要让它们在多监视器设置中为每个监视器执行此操作.

-亚当

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有