当前位置:首页 > c++ > 正文内容

C++ windows显示器相关信息获取

xuwenyan11个月前 (03-01)c++773

可以获取到哪些信息?

  • 1. 显示器个数
  • 2. 是否为主显示器
  • 3. 显示器硬件id
  • 4. 屏幕物理分辨率(硬件支持的最大分辨率)
  • 5. 屏幕逻辑分辨率(软件所能达到的最大分辨率)
  • 6. 屏幕英寸

demo代码如下:

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

  // 获取显示器信息
struct monitor_info {
  bool    primary_device;   // 主显示器
  std::wstring HardwareID;  // 硬件ID
  SIZE    size_;            // 屏幕物理大小(单位毫米)
  SIZE    physical_pixel_;  // 物理分辨率(单位像素)
  SIZE    logical_pixel_;   // 逻辑分辨率(单位像素)
  float   inches;           // 屏幕英寸
};

std::wstring GetHardwareID(const std::wstring& DeviceID) {
  std::wstring::size_type pos = 0, lastpos = 0;
  std::wstring::size_type len = DeviceID.length();
  std::vector<std::wstring> params;
  for (; ;) {
    pos = DeviceID.find_first_of(L"#", lastpos);
    if (pos == std::wstring::npos) {
      if (pos >= len)
        break;
    }
    params.push_back(DeviceID.substr(lastpos, pos - lastpos));
    lastpos = pos + 1;
  }

  return params.size() >= 2 ? params[1] : std::wstring();
}

void GetMonitorInfo(std::vector<monitor_info>& vcMonitorInfo) {
  struct DISPLAY_SETTING {
    DISPLAY_DEVICE device;
    DEVMODE devmode;
  };

  std::vector<DISPLAY_SETTING> vcDisplay;
  for (int devno = 0; ; devno++) {
    DISPLAY_DEVICE device = { 0 };
    device.cb = sizeof(DISPLAY_DEVICE);
    /*
    要查询当前会话中的所有显示设备,请在循环中调用此函数,从iDevNum设置为0开始,
    并递增iDevNum直到函数失败。要选择桌面中的所有显示设备,请仅使用DISPLAY_DEVICE
    结构中具有DISPLAY_DEVICE_ATTACHED_TO_DESKTOP标志的显示设备。
    */
    if (!::EnumDisplayDevices(NULL, devno, &device, 0)) {
      break;
    }

    DEVMODE devmode = { 0 };
    if (!::EnumDisplaySettings(device.DeviceName,
      ENUM_REGISTRY_SETTINGS, &devmode)) {
      break;
    }

    if (device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
      DISPLAY_SETTING setting = { 0 };
      setting.device = device;
      setting.devmode = devmode;
      vcDisplay.push_back(setting);
    }
  }

  for (auto iter : vcDisplay) {
    HDC hdc = ::CreateDC(L"DISPLAY", iter.device.DeviceName, NULL, NULL);
    if (hdc == NULL) {
      continue;
    }

    int cx = ::GetDeviceCaps(hdc, HORZSIZE);
    int cy = ::GetDeviceCaps(hdc, VERTSIZE);
    float unit_inches_millimeter = 25.4f; // 25.4毫米/英寸
    if (cx <= 0 || cy <= 0) {
      ::DeleteDC(hdc);
      continue;
    }

    monitor_info item;
    item.size_ = { cx ,cy };
    item.physical_pixel_ = { (LONG)iter.devmode.dmPelsWidth ,(LONG)iter.devmode.dmPelsHeight };
    item.inches = (float)sqrt(pow(cx, 2.0f) + pow(cy, 2.0f)) / unit_inches_millimeter;

    int log_pixels_x = ::GetDeviceCaps(hdc, LOGPIXELSX);
    int log_pixels_y = ::GetDeviceCaps(hdc, LOGPIXELSY);
    if (log_pixels_x == 96 && log_pixels_y == 96) {
      item.logical_pixel_ = { ::GetDeviceCaps(hdc,HORZRES),::GetDeviceCaps(hdc,VERTRES) };
    }
    else {
      LONG logical_pixel_x = (int)(96.0f / log_pixels_x) * item.physical_pixel_.cx;
      LONG logical_pixel_y = (int)(96.0f / log_pixels_y) * item.physical_pixel_.cy;
      item.logical_pixel_ = { logical_pixel_x,logical_pixel_y };
    }

    DISPLAY_DEVICE device = { 0 };
    device.cb = sizeof(DISPLAY_DEVICE);
    if (::EnumDisplayDevices(iter.device.DeviceName, 0,
      &device, EDD_GET_DEVICE_INTERFACE_NAME)) {
      item.HardwareID = GetHardwareID(device.DeviceID);
    }

    // 通过DISPLAY_DEVICE_PRIMARY_DEVICE判断是否为主显示器
    item.primary_device = (iter.device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE);

    vcMonitorInfo.push_back(item);

    ::DeleteDC(hdc);
  }
}

int main() {
  std::vector<monitor_info> vcMonitorInfo;
  GetMonitorInfo(vcMonitorInfo);

  std::cout << "显示器个数:" << vcMonitorInfo.size() << std::endl;

  for (size_t i = 0; i < vcMonitorInfo.size(); ++i) {
    std::cout << std::endl;
    std::cout << "显示器" << i + 1 << ":" << std::endl;
    std::cout << "是否为主显示器: " << (vcMonitorInfo[i].primary_device ? "是" : "否") << std::endl;
    std::wcout << L"显示器硬件id: " << vcMonitorInfo[i].HardwareID.c_str() << std::endl;
    std::cout << "物理分辨率: " << vcMonitorInfo[i].physical_pixel_.cx << " x " << vcMonitorInfo[i].physical_pixel_.cy << std::endl;
    std::cout << "逻辑分辨率: " << vcMonitorInfo[i].logical_pixel_.cx << " x " << vcMonitorInfo[i].logical_pixel_.cy << std::endl;
    std::cout << "屏幕英寸: " << vcMonitorInfo[i].inches << std::endl;
  }

  system("pause");

  return 0;
}

demo输出展示:



    文章作者:xuwenyan
    版权声明:本文为本站原创文章,转载请注明出处,非常感谢,如版权漏申明或您觉得任何有异议的地方欢迎与本站取得联系。

    扫描二维码推送至手机访问。

    版权声明:本文由艺文笔记发布,如需转载请注明出处。

    本文链接:https://www.xuwenyan.com/archives/2711

    分享给朋友:

    “C++ windows显示器相关信息获取” 的相关文章

    C++如何获取控制台程序的输出内容?

    C++如何获取控制台程序的输出内容?

    很多工具程序(如ffmpeg)的进度显示往往都是以控制台字符显示的方法,我们可能需要调用这种控制台工具去完成工作,但同时又希望以友好的ui界面去显示当前的工作状态(如进度)。此时我们能想到的就是运行控制台程序,然后以某种方式去获取到控制台程序的输出,然后转换到我们的ui界面上去显示。 有多种...

    使用GDI、MFC_GDI、GDI+绘制数组RGBA序列

    使用GDI、MFC_GDI、GDI+绘制数组RGBA序列

    学习ffmpeg时遇到一个问题,ffmpeg解码出RGB颜色后怎么绘制到屏幕上,于是将GDI、MFC_GDI、GDI+等方式都记录一下 1:注意按windows的要求,R、G、B、A顺序要调整为B、G、R、A 。 2:GDI不支持透明通道A,透明通道A的值读进去以后没有作用。想要支持透...

    VC的ATL工程向导同时生成一个PS工程是做什么的?可以不要吗?

    VC的ATL工程向导同时生成一个PS工程是做什么的?可以不要吗?

    例如,我用VC2015的工程向导新建一个ATL的工程名字叫myAtl,那么VC会同时给我生成一个叫做myAtlPS的工程。这个myAtlPS工程是做什么的?什么情况下可以不需要它?什么情况下它又是必须存在的? PS工程是什么?可以不要吗? 这个PS工程叫做代理与存根(proxy&nbs...

    解决程序在xp系统总是莫名奇妙的崩溃问题(/Zc:threadSafeInit- )

    解决程序在xp系统总是莫名奇妙的崩溃问题(/Zc:threadSafeInit- )

    现象:程序在xp系统上面总是莫名其妙的崩溃,检查代码看不出任何问题,感觉代码都很好。即使你远程调试,找到了崩溃的点,当你注释了崩溃点之后,还是会崩溃到别的地方。当你遇到了这种情况的时候,不妨参照一下下面的方法看看,说不定可以解决问题。如何解决?将崩溃程序相关的所有工程代码全部关闭全局变量的线程安全检...

    ATL实现windows右键菜单扩展(ContextMenu)

    ATL实现windows右键菜单扩展(ContextMenu)

    右键菜单,即用户右击shell对象时弹出的上下文菜单(context menu)。本文记录了如何创建右键菜单的基本过程,跟着步骤一步一步来,即可创建出一个右键菜单工程。第一步,新建一个ATL工程Visual Studio—>新建项目—>ATL—>使用默认配置(一直按下一步即可)。注...

    uafxcwd.lib(afxmem.obj) : error LNK2005:

    uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)"解决办法

    如果在编译MFC程序的时候出现下列及类似的错误: 1˃uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) 已经在 LIBCMTD.lib(new...