Windows获取显示器的分辨率,缩放比等信息。

该代码示例展示了如何利用WindowsAPI中的DISPLAY_DEVICE和DEVMODE结构体来获取显示器的详细信息,包括是否为主显示器、物理分辨率、显示分辨率、缩放比例以及屏幕尺寸(毫米和英寸)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

显示器的信息存在DISPLAY_DEVICEDEVOMDE中。他们的文档链接:

DISPLAY_DEVICEA (wingdi.h) - Win32 apps | Microsoft Learn

DEVMODEA (wingdi.h) - Win32 apps | Microsoft Learn

里面还有些如色深和刷新率等参数如需要可以根据文档自行添加。

代码示例如下:

#include <windows.h>
#include <iostream>
#include <vector>
#include <format>

#define CEIL_TO_2_DECIMALS(f) (std::round((f) * 100) / 100) 

// 获取显示器信息
struct CMonitorInfo {
    
    bool m_bPrimary{ false };               //是否是主显示器

    int32_t m_nPixelHorizon{ 0 };          //物理分辨率 水平
    int32_t m_nPixelVertical{ 0 };         //物理分辨率 垂直
    int32_t m_nPixelHorizonLog{ 0 };       //显示分辨率 水平
    int32_t m_nPixelVerticalLog{ 0 };      //显示分辨率 垂直
    float   m_fScale{ 0.0f };              //缩放比例 

    /*=======为了方便就同时存了mm和inch的单位,可以根据自己的需要删除一部分内容=======*/
    float m_fScreenLengthInch{ 0.0f };      //屏幕长度inch
    float m_fScreenWidthInch{ 0.0f };       //屏幕长度inch
    float m_fScreenDiagonalInch{ 0.0f };    //屏幕对角长度inch

    int32_t m_nScreenLengthMM{ 0 };        //屏幕长度mm
    int32_t m_nScreenWidthMM{ 0 };         //屏幕宽度mm
    float m_fScreenDiagonalMM{ 0.0f };     //屏幕对角线长度mm
    /*=======================================end===============================*/

};

/*获得所有显示器的所有信息*/
std::vector<CMonitorInfo> GetMonitorInfor()
{
    std::vector<CMonitorInfo> vMonitorInfor;
    CMonitorInfo MonitorInfo;
    for (int i{ 0 }; ; ++i)
    {
        DISPLAY_DEVICE device{ 0 };      //设备信息的结构体 
        device.cb = sizeof(DISPLAY_DEVICE);
        DEVMODE devmode{ 0 };            //显示设备详细信息的结构体 

        if (!::EnumDisplayDevices(NULL, i, &device, 0))
            break;

        if (!::EnumDisplaySettings(device.DeviceName, ENUM_REGISTRY_SETTINGS, &devmode))
            break;

        if (device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) //当前的设备是连接到显示器的设备
        {
            HDC hdc = ::CreateDC(L"DISPLAY", device.DeviceName, NULL, NULL);

            MonitorInfo.m_bPrimary = (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE);

            MonitorInfo.m_nScreenLengthMM = ::GetDeviceCaps(hdc, HORZSIZE);
            MonitorInfo.m_nScreenWidthMM = ::GetDeviceCaps(hdc, VERTSIZE);
            MonitorInfo.m_fScreenDiagonalMM = CEIL_TO_2_DECIMALS(sqrt(MonitorInfo.m_nScreenLengthMM * MonitorInfo.m_nScreenLengthMM + MonitorInfo.m_nScreenWidthMM * MonitorInfo.m_nScreenWidthMM));
            MonitorInfo.m_fScreenLengthInch = CEIL_TO_2_DECIMALS(MonitorInfo.m_nScreenLengthMM / 25.4f);
            MonitorInfo.m_fScreenWidthInch = CEIL_TO_2_DECIMALS(MonitorInfo.m_nScreenWidthMM / 25.4f);
            MonitorInfo.m_fScreenDiagonalInch = std::round((MonitorInfo.m_fScreenDiagonalMM / 25.4f) * 100) / 100;

            MonitorInfo.m_nPixelHorizon =   devmode.dmPelsWidth; 
            MonitorInfo.m_nPixelVertical =   devmode.dmPelsHeight; 
            MonitorInfo.m_nPixelHorizonLog = ::GetDeviceCaps(hdc, HORZRES); 
            MonitorInfo.m_nPixelVerticalLog = ::GetDeviceCaps(hdc, VERTRES); 

            MonitorInfo.m_fScale = CEIL_TO_2_DECIMALS((float)MonitorInfo.m_nPixelHorizon / MonitorInfo.m_nPixelHorizonLog) ;

            vMonitorInfor.emplace_back(MonitorInfo);
            ::DeleteDC(hdc);
        }
    }
    return vMonitorInfor;
}
int main() 
{
    auto vInfo = GetMonitorInfor();
    for (auto& i : vInfo)
    {
        std::cout << "是否是主显示器: " << std::boolalpha << i.m_bPrimary << "\n";
        std::cout << "长  度\t: " << i.m_nScreenLengthMM << "\t\tmm\n";
        std::cout << "高  度\t: " << i.m_nScreenWidthMM << "\t\tmm\n";
        std::cout << "对  角\t: " << i.m_fScreenDiagonalMM << "\tmm\n";
        std::cout << "长  度\t: " << i.m_fScreenLengthInch << "\tinch\n";
        std::cout << "高  度\t: " << i.m_fScreenWidthInch << "\t\tinch\n";
        std::cout << "对  角\t: " << i.m_fScreenDiagonalInch << "\t\tinch\n";
        std::cout << "实际水平: " << i.m_nPixelHorizon << "\n";
        std::cout << "实际垂直: " << i.m_nPixelVertical << "\n";
        std::cout << "显示水平: " << i.m_nPixelHorizonLog << "\n";
        std::cout << "显示垂直: " << i.m_nPixelVerticalLog << "\n";
        std::cout << "缩放比\t: " << i.m_fScale << "\n\n\n";
    }
    std::cout << std::endl;
    getchar();
    return 0;
}

<think>嗯,用户问的是如何在FlaUI中获取当前桌面的分辨率缩放比例。首先,我需要回忆一下FlaUI的功能。FlaUI是一个用于UI自动化的库,主要针对Windows应用程序。不过,获取缩放比例可能涉及到底层的系统API,而不仅仅是FlaUI本身的功能。 用户之前的问题是关于调用SetProcessDpiAwareness的,所以可能他们在处理高DPI环境下的应用程序适配问题。现在他们想知道如何获取缩放比例,可能是为了调整UI元素的位置或大小,确保自动化脚本在不同DPI设置下正常工作。 接下来,我需要确定FlaUI是否直接提供获取缩放比例的方法。根据我的了解,FlaUI主要处理UI元素的查找和操作,可能不直接提供DPI相关的功能。这时候可能需要使用Windows API或者.NET框架中的类来获取这些信息。 在Windows中,获取DPI缩放比例通常涉及到GetDpiForWindow或者GetDpiForSystem函数,或者使用SystemParameters类的相关属性。例如,SystemInformation.PrimaryMonitorSize和SystemInformation.PrimaryMonitorDPI可以计算出缩放比例。 另外,用户可能需要当前主显示器缩放比例,或者所有显示器的。这里需要明确回答中的方法是否适用于多显示器环境。如果是多显示器,可能需要使用System.Windows.Forms.Screen类来获取每个屏幕的信息,再结合DPI值来计算。 还需要考虑不同版本的Windows对DPI处理的不同。比如,Windows 10和11对Per Monitor DPI的支持更好,而旧版本可能需要不同的方法。另外,.NET框架版本也可能影响可用的API,比如在.NET Core 3.0及以上,有更多内置的DPI相关方法。 在用户之前的回答中,提到了使用P/Invoke调用SetProcessDpiAwareness,所以在这次回答中可能需要类似的技术,或者转而使用.NET内置的方法来简化代码。例如,使用Graphics类中的DpiX和DpiY属性来获取当前设备的DPI,然后根据系统标准DPI(通常是96)计算缩放比例。 此外,需要注意调用获取DPI方法的时机,是否需要在应用程序启动时设置DPI感知模式,否则可能获取到错误的缩放比例。例如,如果应用程序没有正确设置DPI感知,SystemInformation可能会返回系统DPI而不是当前显示器的DPI,导致计算结果不准确。 可能的步骤包括:通过System.Windows.Forms.SystemInformation获取DPI,然后计算缩放比例;或者使用Windows API如GetDpiForWindow来获取更精确的数据。需要对比两种方法的优缺点,比如使用.NET方法更简单,但可能不够灵活;使用API更直接,但需要处理P/Invoke和兼容性问题。 另外,是否需要考虑不同的DPI感知模式对获取结果的影响。比如,如果应用程序设置为Per Monitor Aware,那么获取的DPI值可能更准确,否则可能得到主显示器的DPI。这一点需要在回答中说明,确保用户根据他们的DPI感知设置选择合适的获取方法。 最后,可能需要提供一个完整的代码示例,展示如何通过FlaUI或结合.NET框架的方法来获取缩放比例,并解释每一步的作用。同时提醒用户注意DPI感知设置和系统版本兼容性,确保代码在不同环境下正常工作。</think>--- ### **1. 核心思路** 通过FlaUI获取当前屏幕的DPI缩放比例需要结合Windows API或.NET框架方法,因为FlaUI本身不直接提供DPI缩放比查询功能。以下是两种常用方案: --- ### **2. 方法一:使用.NET内置类(推荐)** 通过`System.Windows.Forms`或`System.Drawing`直接获取当前屏幕的缩放比例: ```csharp using System.Windows.Forms; // 获取显示器的DPI缩放比例 public float GetPrimaryScreenScaling() { // 获取系统标准DPI(通常96) const float standardDpi = 96f; // 获取当前屏幕的DPI using (var graphics = Graphics.FromHwnd(IntPtr.Zero)) { float dpiX = graphics.DpiX; return dpiX / standardDpi; // 返回缩放比例(例如1.25 = 125%) } } // 调用示例 float scale = GetPrimaryScreenScaling(); Console.WriteLine($"当前缩放比例:{scale * 100}%"); ``` --- ### **3. 方法二:通过Windows API(精确控制)** 使用`GetDpiForWindow`或`GetDpiForSystem`函数(需设置DPI感知模式): #### **步骤1:声明API函数** ```csharp using System.Runtime.InteropServices; public static class DpiHelper { [DllImport("user32.dll")] public static extern int GetDpiForWindow(IntPtr hwnd); [DllImport("user32.dll")] public static extern int GetDpiForSystem(); } ``` #### **步骤2:计算缩放比例** ```csharp public float GetScalingViaApi() { // 获取系统标准DPI const int standardDpi = 96; // 获取当前窗口的DPI(传入窗口句柄,或直接用GetDpiForSystem) int currentDpi = DpiHelper.GetDpiForSystem(); return currentDpi / (float)standardDpi; } // 调用示例(需确保已设置进程DPI感知) float scale = GetScalingViaApi(); Console.WriteLine($"API获取缩放比例:{scale * 100}%"); ``` --- ### **4. 结合FlaUI获取特定窗口的缩放比** 如果需要针对FlaUI操作的窗口计算缩放比例,可以获取窗口句柄后调用API: ```csharp using FlaUI.Core.AutomationElements; // 获取FlaUI窗口的缩放比例 public float GetWindowScaling(Window window) { IntPtr hwnd = new IntPtr(window.Properties.NativeWindowHandle); int dpi = DpiHelper.GetDpiForWindow(hwnd); return dpi / 96f; } // 使用示例 var app = FlaUI.Core.Application.Launch("notepad.exe"); var window = app.GetMainWindow(); float windowScale = GetWindowScaling(window); ``` --- ### **5. 注意事项** 1. **DPI感知模式**:调用API前需设置进程DPI感知(参考`SetProcessDpiAwareness`),否则可能返回错误值。 ```csharp // 确保在程序启动时设置 Application.SetHighDpiMode(HighDpiMode.PerMonitorV2); ``` 2. **多显示器差异**:不同显示器可能有不同DPI,上述方法默认获取显示器值。如需多屏支持,需通过`Screen.AllScreens`遍历处理。 3. **兼容性**:`GetDpiForWindow`仅支持Windows 10 1607+,旧系统需改用`GetDeviceCaps`。 --- ### **6. 完整代码示例** ```csharp using System; using System.Drawing; using System.Windows.Forms; using FlaUI.Core.AutomationElements; class Program { static void Main() { // 设置DPI感知模式(必需) Application.SetHighDpiMode(HighDpiMode.PerMonitorV2); // 方法1:通过.NET获取 float scale1 = GetPrimaryScreenScaling(); Console.WriteLine($"方法1:{scale1 * 100}%"); // 方法2:通过API获取 float scale2 = GetScalingViaApi(); Console.WriteLine($"方法2:{scale2 * 100}%"); // 结合FlaUI获取窗口DPI var app = FlaUI.Core.Application.Launch("notepad.exe"); var window = app.GetMainWindow(); float windowScale = GetWindowScaling(window); Console.WriteLine($"窗口缩放:{windowScale * 100}%"); } static float GetPrimaryScreenScaling() { using (var graphics = Graphics.FromHwnd(IntPtr.Zero)) { return graphics.DpiX / 96f; } } static float GetScalingViaApi() { int dpi = DpiHelper.GetDpiForSystem(); return dpi / 96f; } static float GetWindowScaling(Window window) { IntPtr hwnd = new IntPtr(window.Properties.NativeWindowHandle); int dpi = DpiHelper.GetDpiForWindow(hwnd); return dpi / 96f; } } public static class DpiHelper { [DllImport("user32.dll")] public static extern int GetDpiForWindow(IntPtr hwnd); [DllImport("user32.dll")] public static extern int GetDpiForSystem(); } ``` --- 通过上述方法,可以在C#和FlaUI中准确获取当前屏幕或窗口的DPI缩放比例,适配高分辨率环境下的UI自动化需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值