函数
BOOL EnumDisplayDevicesA( LPCSTR lpDevice, DWORD iDevNum, PDISPLAY_DEVICEA lpDisplayDevice, DWORD dwFlags );
用于枚举显示设备信息。当lpDevice = NULL时,枚举视频卡(Display adapter)信息;当lpDevice = DISPLAY_DEVICE::DeviceName时,枚举显示器(monitor)信息;
函数
BOOL EnumDisplaySettingsA( LPCSTR lpszDeviceName, DWORD iModeNum, DEVMODEA *lpDevMode );
用于枚举视频模式(Video mode)信息
范例:
1 #pragma once 2 3 #include4 #include 5 #include 6 7 struct VIDEOMODE; 8 struct DISPLAY; 9 10 typedef struct VIDEOMODE 11 { 12 VIDEOMODE* next; 13 14 int width; 15 int height; 16 int red_bits; 17 int green_bits; 18 int blue_bits; 19 int refresh_rates; 20 21 } *PVIDEOMODE; 22 23 24 typedef struct DISPLAY 25 { 26 DISPLAY* next; 27 28 TCHAR monitor_name[1024]; 29 TCHAR adapter_name[1024]; 30 int widthMM; 31 int heightMM; 32 33 VIDEOMODE* pVideoMode; 34 VIDEOMODE* pCurrentMode; 35 36 } *PDISPLAY; 37 38 class CDispDeviceInfo 39 { 40 public: 41 42 CDispDeviceInfo(); 43 ~CDispDeviceInfo(); 44 45 bool CDispDeviceInfoInit(); 46 DISPLAY* EnumDisplay(int index); 47 VIDEOMODE* EnumVideoModes(DISPLAY* adapter, int index); 48 VIDEOMODE* GetCurrentMode(); 49 50 protected: 51 52 void SpiltBPP(int color_bits, int* red_bits, int* green_bits, int* blue_bits); 53 bool CompareVideoMode(VIDEOMODE* adapter, VIDEOMODE* result); 54 DISPLAY* CreateMonitors(DISPLAY_DEVICEW* display, DISPLAY_DEVICEW* adapter); 55 VIDEOMODE* CreateVideoModes(DISPLAY_DEVICEW* adapter); 56 void CreateVideoMode(DEVMODE* devmode, VIDEOMODE* mode); 57 void FreeDispDevicesInfo(); 58 59 60 DISPLAY* head; 61 VIDEOMODE* CurrentMode; 62 };
1 #include "CDispDevice.h" 2 3 CDispDeviceInfo::CDispDeviceInfo() 4 { 5 head = nullptr; 6 CurrentMode = nullptr; 7 } 8 9 CDispDeviceInfo::~CDispDeviceInfo() 10 { 11 this->FreeDispDevicesInfo(); 12 } 13 14 bool CDispDeviceInfo::CDispDeviceInfoInit() 15 { 16 DWORD adapterIndex, displayIndex; 17 DISPLAY_DEVICEW adapter, display; 18 19 for (adapterIndex = 0; ; adapterIndex++) { 20 21 ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW)); 22 adapter.cb = sizeof(DISPLAY_DEVICEW); 23 24 if (!EnumDisplayDevices(NULL, adapterIndex, &adapter, 0)) 25 break; 26 27 // skip unactive adapter 28 if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) 29 continue; 30 31 for (displayIndex = 0; ; displayIndex++) { 32 33 ZeroMemory(&display, sizeof(DISPLAY_DEVICEW)); 34 display.cb = sizeof(DISPLAY_DEVICEW); 35 36 if (!EnumDisplayDevices(adapter.DeviceName, displayIndex, &display, 0)) 37 break; 38 39 // skip unactive monitor 40 if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE)) 41 continue; 42 43 PDISPLAY pDisp = CreateMonitors(&display, &adapter); 44 if (head) { 45 pDisp->next = head; 46 } 47 else 48 { 49 head = pDisp; 50 head->next = nullptr; 51 } 52 53 } 54 } 55 56 return true; 57 } 58 59 DISPLAY* CDispDeviceInfo::EnumDisplay(int index) 60 { 61 PDISPLAY iter = head; 62 63 if (!head) 64 return nullptr; 65 66 for (int i = 0; i < index; i++) { 67 if (!(iter = iter->next)) 68 return nullptr; 69 } 70 71 return iter; 72 } 73 74 VIDEOMODE* CDispDeviceInfo::EnumVideoModes(DISPLAY* adapter, int index) 75 { 76 PVIDEOMODE iter = adapter->pVideoMode; 77 78 if(!adapter->pVideoMode) 79 return nullptr; 80 81 for (int i = 0; i < index; i++) { 82 if (!(iter = iter->next)) 83 return nullptr; 84 } 85 86 return iter; 87 } 88 89 void CDispDeviceInfo::SpiltBPP(int bpp, int* red_bits, int* green_bits, int* blue_bits) 90 { 91 if (bpp >= 32) { 92 bpp = 24; 93 } 94 95 *red_bits = *green_bits = *blue_bits = bpp / 3; 96 int delta = bpp - (*red_bits * 3); 97 if (delta >= 1) { 98 *green_bits = *green_bits + 1; 99 } 100 if (delta == 2) { 101 *red_bits = *red_bits + 1; 102 } 103 } 104 105 bool CDispDeviceInfo::CompareVideoMode(VIDEOMODE* src, VIDEOMODE* result) 106 { 107 if (!(result && src)) 108 { 109 return false; 110 } 111 112 int r_bpp = result->red_bits + result->green_bits + result->blue_bits; 113 int r_area = result->width * result->height; 114 int t_bpp = src->red_bits + src->green_bits + src->blue_bits; 115 int t_area = src->width * src->height; 116 117 if (src->refresh_rates == result->refresh_rates && r_bpp == t_bpp && r_area == t_area) 118 return true; 119 120 return false; 121 } 122 123 DISPLAY* CDispDeviceInfo::CreateMonitors(DISPLAY_DEVICEW* display, DISPLAY_DEVICEW* adapter) 124 { 125 DEVMODE dm; 126 HDC dc; 127 DISPLAY* pm; 128 129 pm = (DISPLAY*)calloc(1, sizeof(DISPLAY)); 130 131 EnumDisplaySettings(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm); 132 133 dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL); 134 if (!IsWindows8Point1OrGreater()) { 135 pm->widthMM = GetDeviceCaps(dc, HORZSIZE); 136 pm->heightMM = GetDeviceCaps(dc, VERTSIZE); 137 } 138 else 139 { 140 pm->widthMM = (int)(dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX)); 141 pm->heightMM = (int)(dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY)); 142 } 143 DeleteDC(dc); 144 145 wcscpy_s(pm->adapter_name, adapter->DeviceString); 146 wcscpy_s(pm->monitor_name, display->DeviceString); 147 148 pm->pVideoMode = this->CreateVideoModes(adapter); 149 150 return pm; 151 } 152 153 VIDEOMODE* CDispDeviceInfo::CreateVideoModes(DISPLAY_DEVICEW* adapter) 154 { 155 DEVMODEW devmode; 156 VIDEOMODE Mode, Current, * pMode = NULL; 157 bool firstCreate = true; 158 159 ZeroMemory(&devmode, sizeof(devmode)); 160 devmode.dmSize = sizeof(devmode); 161 if(!EnumDisplaySettings(adapter->DeviceName, 0, &devmode)){ 162 return false; 163 } 164 else { 165 // Get current mode 166 EnumDisplaySettings(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &devmode); 167 this->CreateVideoMode(&devmode, &Current); 168 } 169 170 171 172 for (DWORD modesIndex = 0;; modesIndex++) { 173 174 ZeroMemory(&devmode, sizeof(devmode)); 175 devmode.dmSize = sizeof(devmode); 176 if (!EnumDisplaySettings(adapter->DeviceName, modesIndex, &devmode)) 177 break; 178 179 // skip modes less than 15 BPP 180 if (devmode.dmBitsPerPel < 15) 181 continue; 182 183 this->CreateVideoMode(&devmode, &Mode); 184 185 // check duplicated mode 186 if (this->CompareVideoMode(&Mode, pMode)) 187 continue; 188 if (!firstCreate) { 189 PVIDEOMODE pNextMode = (VIDEOMODE*)calloc(1, sizeof(VIDEOMODE)); 190 memcpy(pNextMode, &Mode, sizeof(Mode)); 191 pNextMode->next = pMode; 192 pMode = pNextMode; 193 194 // store current mode 195 if (this->CompareVideoMode(&Mode, &Current)) { 196 this->CurrentMode = pMode; 197 } 198 199 } 200 else { 201 pMode = (VIDEOMODE*)calloc(1, sizeof(VIDEOMODE)); 202 memcpy(pMode, &Mode, sizeof(Mode)); 203 } 204 205 firstCreate = false; 206 } 207 208 return pMode; 209 } 210 211 VIDEOMODE* CDispDeviceInfo::GetCurrentMode() 212 { 213 return CurrentMode; 214 } 215 216 void CDispDeviceInfo::CreateVideoMode(DEVMODE* devmode, VIDEOMODE* mode) 217 { 218 ZeroMemory(mode, sizeof(mode)); 219 mode->width = devmode->dmPelsWidth; 220 mode->height = devmode->dmPelsHeight; 221 mode->refresh_rates = devmode->dmDisplayFrequency; 222 this->SpiltBPP(devmode->dmBitsPerPel, &mode->red_bits, &mode->green_bits, &mode->blue_bits); 223 } 224 225 void CDispDeviceInfo::FreeDispDevicesInfo() 226 { 227 DISPLAY* dis_tmp; 228 VIDEOMODE* vid_tmp; 229 dis_tmp = head; 230 231 for (; head;) { 232 if (head->pVideoMode) { 233 vid_tmp = head->pVideoMode; 234 235 for (; head->pVideoMode;) { 236 head->pVideoMode = head->pVideoMode->next; 237 free(vid_tmp); 238 vid_tmp = head->pVideoMode; 239 } 240 241 } 242 243 head = head->next; 244 free(dis_tmp); 245 dis_tmp = head; 246 } 247 }
1 #include "CDispDevice.h" 2 3 4 int main(int argc, char** argv) 5 { 6 DISPLAY* disp; 7 VIDEOMODE* vidmodes; 8 CDispDeviceInfo info; 9 info.CDispDeviceInfoInit(); 10 11 vidmodes = info.GetCurrentMode(); 12 printf("Current Mode: %d x %d (%d %d %d) %dHz\n", vidmodes->width, vidmodes->height, 13 vidmodes->red_bits, vidmodes->green_bits, vidmodes->blue_bits, vidmodes->refresh_rates); 14 15 16 for (int i = 0; disp = info.EnumDisplay(i);i++) { 17 wprintf(TEXT("Adapter Name: %s\n"), disp->adapter_name); 18 wprintf(TEXT("Monitor Name: %s\n"), disp->monitor_name); 19 printf("Monitor properties: Width: %dmm Height: %dmm\n", disp->widthMM, disp->heightMM); 20 printf("Display Modes : \n"); 21 for (int k = 0; vidmodes = info.EnumVideoModes(disp, k); k++) { 22 printf("%d:%d x %d (%d %d %d) %dHz\n",k , vidmodes->width, vidmodes->height, 23 vidmodes->red_bits, vidmodes->green_bits, vidmodes->blue_bits, vidmodes->refresh_rates); 24 } 25 } 26 return 0; 27 }
运行环境: Visual Studio 2019