C语言 Win32 获取显示设备信息

函数

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 #include 
 4 #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 };
CDispDevice.h
  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 }
CDispDevice.cpp
 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 }
main.cpp

 

运行环境: Visual Studio 2019

C语言 Win32 获取显示设备信息_第1张图片

 

你可能感兴趣的:(C语言 Win32 获取显示设备信息)