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

可以获取到哪些信息?

  • 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输出展示: