簡體   English   中英

屏幕像素分辨率 (mm)

[英]Screen Pixel Resolution in mm

是否可以使用 Win32 API 以毫米為單位獲得屏幕像素分辨率? 我有一個應用程序,它在 96 dpi 的 1280x1024 顯示器上顯示 0.3472222222222222 作為此值。 但我無法找出它是如何獲得這個價值的。 任何線索都會有所幫助。 如果需要,我也可以使用 MFC。

編輯抱歉造成混亂,我正在談論的軟件沒有使用當前的屏幕分辨率。 它正在從一些配置文件中讀取它。

獲取顯示器的設備上限為您提供像素和毫米的尺寸,因此:

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 毫米實際上相當於大約 73 dpi。 Windows 使用兩個標准設置 72dpi 和 96dpi,但也支持自定義值。 這些是標稱值,可能與物理屏幕沒有任何關系。 例如,可以將物理 96dpi 屏幕設置為 72dpi,這將影響各種應用程序中圖像和布局的縮放以及系統字體和圖標的大小。

Windows 的默認值為 72dpi,我發現某些應用程序(通常在其“關於”和對話框中)在設置為其他值時無法正確呈現。 如果您的應用程序報告 0.34,則無論物理分辨率如何,它似乎都設置為 72dpi 或自定義值。 當設置為匹配物理分辨率時,例如 Word 中的頁面寬度設置為 100% 縮放級別時將匹配物理紙張大小。 由於該指標可由最終用戶設置,因此與實際分辨率沒有直接關系。

MSDN 中有關編寫“DPI 感知”應用程序的部分非常值得任何有興趣為可變顯示分辨率提供適當支持的人閱讀。 此處描述用於獲取相關設備和系統指標的 API。

使用GetDC函數獲取監視器的句柄,然后調用GetDeviceCaps函數獲取以毫米為單位的監視器大小。 例如:

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

下面的代碼片段被證明提供了最好的結果。

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

我在Windows 7上也遇到了類似的問題並嘗試了不同的方法,但直到我找到這個才找到正確的答案: http : //ofekshilon.com/2011/11/13/reading-monitor-physical-dimensions-or-getting -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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM