كيفية الحصول على الحجم الفعلي الصحيح للشاشة؟

StackOverflow https://stackoverflow.com/questions/577736

  •  05-09-2019
  •  | 
  •  

سؤال

كيف يمكنني الحصول على حجم العرض في سنتيمترات أو بوصة؟

هذا الرمز لا يعمل دائما بشكل صحيح:

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

خاصة تكوين متعدد الشاشات.

تحديث: أحتاج إلى الحصول على الحجم لمجرد الشاشات العادية، والتي لها حجم مادي ثابت.

هل كانت مفيدة؟

المحلول

لقد وجدت طريقة أخرى. يتم تخزين الحجم المادي للشاشة في 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;
}

نصائح أخرى

لا يمكن تحديد الحجم المادي الدقيق لجهاز الفيديو على Windows لأن هذا يعتمد على الكثير من المتغيرات (مثل ملف تعريف الشاشة النشطة والدقة الأفقية / الرأسية، وحجم بكسل، إلخ)، بعضها ليس تحت السيطرة على الكمبيوتر.

فكر في مثال أجهزة العرض، حيث يعتمد الحجم المادي على المسافة إلى منطقة الإسقاط التي لا يمكن تحديدها برمجيا، حيث يمكن نقل جهاز عرض الفيديو يدويا في أي وقت.

التنقل في التسجيل مباشرة ليس غير مدعوم فقط، ولكن في الواقع فشل في فعلا الأجهزة مختلفة عنك. (على سبيل المثال، الشخص الذي اختبرته رمزك).

على عكس ما يقوله البعض هنا، هناك يكون طريقة رسمية للوصول إلى مسار EDID الرئيسي: عن طريق استخدام API الإعداد، وتحديدا setupdiopendevregke..

هناك بعض الإعداد الشارقي المعني - نموذج التعليمة البرمجية هنا.


تحرير: يتم التعامل مع شاشات متعددة هنا.

لا يمكنك الحصول على الحجم الحقيقي الحقيقي - يمكنك الحصول على تقريب يعتمد على إعداد DPI في Windows، ودقة الشاشة، ولكن لا يمكنك ضمان أن هذا هو الحجم الحقيقي.

خاصة في وضع متعدد الوسائط مع عروض مختلفة (قل 19 "CRT و 24" LCD). علاوة على ذلك، إذا كانت الشاشة CRT، فإن القياس هو قياس الأنبوب، وليس منطقة العرض.

عندما احتاجت البرامج إلى هذه المعلومات بالضبط في الماضي، فقد أظهروا مقياسا قياسيا، وكان لدى المستخدم قطعة من الورق حتى الشاشة وقياس عرض الورق مع المقياس. بالنظر إلى الورق 8.5 "أو A4، فأنت تعرف العرض، ويمكنك استخدام الرقم الذي يتم إدخاله لمعرفة DPI الحقيقي لعرض معين. قد تحتاج إلى القيام بذلك لكل شاشة في إعداد متعدد الوسائط.

-Adam.

ويندوز فيستا والدعم العلوي وظيفة جديدة getmonitordisplayareasize ()http://msdn.microsoft.com/en-us/library/ms775210٪28vs.85٪29.aspx.

تحديث: لا يعمل بشكل صحيح

يمكنك طلب logpixelsx من getdevicecaps. للحصول على DPI للعرض، على الرغم من أنه سيعود عموما 96. انظر أيضا هذا MSDN مقالة على كتابة تطبيقات DPI-Aware.

يمكنك الحصول على EDID من السجل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top