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

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

xuwenyan2年前 (2022-03-01)c++2255

可以获取到哪些信息?

  • 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++指针*为什么靠后会比较好?

    大多数书中和大神的代码里,往往指针的*都是靠变量而不是靠类型的,这主要是为了不造成我们第一眼对变量类型的误解和对指针类型的误解,比如: int* p1,p2 我们一眼看上去是不是通常会觉得p1、p1都是一个int*的指针呢?因为我们通常会误把int*当作一个类型,然而无论int*还是i...

    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的值读进去以后没有作用。想要支持透...

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

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

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

    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...

    C++ 获取进程所在目录(进程全路径)

    C++ 获取进程所在目录(进程全路径)

    打开windows任务管理器,会看到很多的进程在运行,随机挑选一个,如何通过c++代码获取某一个进程的所在全路径呢?这也是在windows软件开发中经常遇到的需求。通过进程名获取进程全路径由于可能很多进程叫同一个名字,所以获得的结果也有可能是多个#include <windows.h...