1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * PURPOSE: Settings property page
5 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
6 * Hervé Poussineau (hpoussin@reactos.org)
7 */
8
9 #include "desk.h"
10
11 typedef struct _SETTINGS_DATA
12 {
13 PDISPLAY_DEVICE_ENTRY DisplayDeviceList;
14 PDISPLAY_DEVICE_ENTRY CurrentDisplayDevice;
15 HBITMAP hSpectrumBitmaps[NUM_SPECTRUM_BITMAPS];
16 int cxSource[NUM_SPECTRUM_BITMAPS];
17 int cySource[NUM_SPECTRUM_BITMAPS];
18 } SETTINGS_DATA, *PSETTINGS_DATA;
19
20 typedef struct _TIMEOUTDATA
21 {
22 TCHAR szRawBuffer[256];
23 TCHAR szCookedBuffer[256];
24 INT nTimeout;
25 } TIMEOUTDATA, *PTIMEOUTDATA;
26
27 static VOID
UpdateDisplay(IN HWND hwndDlg,PSETTINGS_DATA pData,IN BOOL bUpdateThumb)28 UpdateDisplay(IN HWND hwndDlg, PSETTINGS_DATA pData, IN BOOL bUpdateThumb)
29 {
30 TCHAR Buffer[64];
31 TCHAR Pixel[64];
32 DWORD index;
33 HWND hwndMonSel;
34 MONSL_MONINFO info;
35
36 LoadString(hApplet, IDS_PIXEL, Pixel, _countof(Pixel));
37 _stprintf(Buffer, Pixel, pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth, pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight, Pixel);
38 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT, WM_SETTEXT, 0, (LPARAM)Buffer);
39
40 for (index = 0; index < pData->CurrentDisplayDevice->ResolutionsCount; index++)
41 {
42 if (pData->CurrentDisplayDevice->Resolutions[index].dmPelsWidth == pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth &&
43 pData->CurrentDisplayDevice->Resolutions[index].dmPelsHeight == pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight)
44 {
45 if (bUpdateThumb)
46 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETPOS, TRUE, index);
47 break;
48 }
49 }
50 if (LoadString(hApplet, (2900 + pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel), Buffer, _countof(Buffer)))
51 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)Buffer);
52
53 hwndMonSel = GetDlgItem(hwndDlg, IDC_SETTINGS_MONSEL);
54 index = (INT)SendMessage(hwndMonSel, MSLM_GETCURSEL, 0, 0);
55 if (index != (DWORD)-1 && SendMessage(hwndMonSel, MSLM_GETMONITORINFO, index, (LPARAM)&info))
56 {
57 info.Size.cx = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
58 info.Size.cy = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
59 SendMessage(hwndMonSel, MSLM_SETMONITORINFO, index, (LPARAM)&info);
60 }
61 }
62
63 static int
CompareSettings(PSETTINGS_ENTRY Entry,DWORD dmPelsWidth,DWORD dmPelsHeight,DWORD dmBitsPerPel,DWORD dmDisplayFrequency)64 CompareSettings(PSETTINGS_ENTRY Entry, DWORD dmPelsWidth, DWORD dmPelsHeight,
65 DWORD dmBitsPerPel, DWORD dmDisplayFrequency)
66 {
67 if (Entry->dmPelsWidth == dmPelsWidth &&
68 Entry->dmPelsHeight == dmPelsHeight &&
69 Entry->dmBitsPerPel == dmBitsPerPel &&
70 Entry->dmDisplayFrequency == dmDisplayFrequency)
71 {
72 return 0;
73 }
74 else
75 if ((Entry->dmPelsWidth < dmPelsWidth) ||
76 (Entry->dmPelsWidth == dmPelsWidth && Entry->dmPelsHeight < dmPelsHeight) ||
77 (Entry->dmPelsWidth == dmPelsWidth && Entry->dmPelsHeight == dmPelsHeight &&
78 Entry->dmBitsPerPel < dmBitsPerPel))
79 {
80 return 1;
81 }
82 return -1;
83 }
84
85 static PSETTINGS_ENTRY
GetPossibleSettings(IN LPCTSTR DeviceName,OUT DWORD * pSettingsCount,OUT PSETTINGS_ENTRY * CurrentSettings)86 GetPossibleSettings(IN LPCTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings)
87 {
88 DEVMODE devmode;
89 DWORD NbSettings = 0;
90 DWORD iMode = 0;
91 DWORD dwFlags = 0;
92 PSETTINGS_ENTRY Settings = NULL;
93 HDC hDC;
94 PSETTINGS_ENTRY Current;
95 DWORD bpp, xres, yres;
96 DWORD curDispFreq;
97
98 /* Get current settings */
99 *CurrentSettings = NULL;
100 hDC = CreateIC(NULL, DeviceName, NULL, NULL);
101 bpp = GetDeviceCaps(hDC, PLANES);
102 bpp *= GetDeviceCaps(hDC, BITSPIXEL);
103 xres = GetDeviceCaps(hDC, HORZRES);
104 yres = GetDeviceCaps(hDC, VERTRES);
105 DeleteDC(hDC);
106
107 /* List all settings */
108 devmode.dmSize = (WORD)sizeof(devmode);
109 devmode.dmDriverExtra = 0;
110
111 if (!EnumDisplaySettingsEx(DeviceName, ENUM_CURRENT_SETTINGS, &devmode, dwFlags))
112 return NULL;
113
114 curDispFreq = devmode.dmDisplayFrequency;
115
116 while (EnumDisplaySettingsEx(DeviceName, iMode, &devmode, dwFlags))
117 {
118 iMode++;
119
120 if (devmode.dmPelsWidth < 640 ||
121 devmode.dmPelsHeight < 480 ||
122 devmode.dmDisplayFrequency != curDispFreq ||
123 (devmode.dmBitsPerPel != 4 &&
124 devmode.dmBitsPerPel != 8 &&
125 devmode.dmBitsPerPel != 16 &&
126 devmode.dmBitsPerPel != 24 &&
127 devmode.dmBitsPerPel != 32))
128 {
129 continue;
130 }
131
132 Current = HeapAlloc(GetProcessHeap(), 0, sizeof(SETTINGS_ENTRY));
133 if (Current != NULL)
134 {
135 /* Sort resolutions by increasing height, and BPP */
136 PSETTINGS_ENTRY Previous = NULL;
137 PSETTINGS_ENTRY Next = Settings;
138 Current->dmPelsWidth = devmode.dmPelsWidth;
139 Current->dmPelsHeight = devmode.dmPelsHeight;
140 Current->dmBitsPerPel = devmode.dmBitsPerPel;
141 Current->dmDisplayFrequency = devmode.dmDisplayFrequency;
142 while (Next != NULL &&
143 CompareSettings(Next, devmode.dmPelsWidth,
144 devmode.dmPelsHeight, devmode.dmBitsPerPel,
145 devmode.dmDisplayFrequency) > 0)
146 {
147 Previous = Next;
148 Next = Next->Flink;
149 }
150 Current->Blink = Previous;
151 Current->Flink = Next;
152 if (Previous == NULL)
153 Settings = Current;
154 else
155 Previous->Flink = Current;
156 if (Next != NULL)
157 Next->Blink = Current;
158 if (devmode.dmPelsWidth == xres && devmode.dmPelsHeight == yres && devmode.dmBitsPerPel == bpp)
159 {
160 *CurrentSettings = Current;
161 }
162 NbSettings++;
163 }
164 }
165
166 *pSettingsCount = NbSettings;
167 return Settings;
168 }
169
170 static BOOL
AddDisplayDevice(IN PSETTINGS_DATA pData,IN const DISPLAY_DEVICE * DisplayDevice)171 AddDisplayDevice(IN PSETTINGS_DATA pData, IN const DISPLAY_DEVICE *DisplayDevice)
172 {
173 PDISPLAY_DEVICE_ENTRY newEntry = NULL;
174 LPTSTR description = NULL;
175 LPTSTR name = NULL;
176 LPTSTR key = NULL;
177 LPTSTR devid = NULL;
178 SIZE_T descriptionSize, nameSize, keySize, devidSize;
179 PSETTINGS_ENTRY Current;
180 DWORD ResolutionsCount = 1;
181 DWORD i;
182
183 newEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAY_DEVICE_ENTRY));
184 if (!newEntry) goto ByeBye;
185
186 newEntry->Settings = GetPossibleSettings(DisplayDevice->DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings);
187 if (!newEntry->Settings) goto ByeBye;
188
189 newEntry->InitialSettings.dmPelsWidth = newEntry->CurrentSettings->dmPelsWidth;
190 newEntry->InitialSettings.dmPelsHeight = newEntry->CurrentSettings->dmPelsHeight;
191 newEntry->InitialSettings.dmBitsPerPel = newEntry->CurrentSettings->dmBitsPerPel;
192 newEntry->InitialSettings.dmDisplayFrequency = newEntry->CurrentSettings->dmDisplayFrequency;
193
194 /* Count different resolutions */
195 for (Current = newEntry->Settings; Current != NULL; Current = Current->Flink)
196 {
197 if (Current->Flink != NULL &&
198 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) ||
199 (Current->dmPelsHeight != Current->Flink->dmPelsHeight)))
200 {
201 ResolutionsCount++;
202 }
203 }
204
205 newEntry->Resolutions = HeapAlloc(GetProcessHeap(), 0, ResolutionsCount * sizeof(RESOLUTION_INFO));
206 if (!newEntry->Resolutions) goto ByeBye;
207
208 newEntry->ResolutionsCount = ResolutionsCount;
209
210 /* Fill resolutions infos */
211 for (Current = newEntry->Settings, i = 0; Current != NULL; Current = Current->Flink)
212 {
213 if (Current->Flink == NULL ||
214 (Current->Flink != NULL &&
215 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) ||
216 (Current->dmPelsHeight != Current->Flink->dmPelsHeight))))
217 {
218 newEntry->Resolutions[i].dmPelsWidth = Current->dmPelsWidth;
219 newEntry->Resolutions[i].dmPelsHeight = Current->dmPelsHeight;
220 i++;
221 }
222 }
223 descriptionSize = (_tcslen(DisplayDevice->DeviceString) + 1) * sizeof(TCHAR);
224 description = HeapAlloc(GetProcessHeap(), 0, descriptionSize);
225 if (!description) goto ByeBye;
226
227 nameSize = (_tcslen(DisplayDevice->DeviceName) + 1) * sizeof(TCHAR);
228 name = HeapAlloc(GetProcessHeap(), 0, nameSize);
229 if (!name) goto ByeBye;
230
231 keySize = (_tcslen(DisplayDevice->DeviceKey) + 1) * sizeof(TCHAR);
232 key = HeapAlloc(GetProcessHeap(), 0, keySize);
233 if (!key) goto ByeBye;
234
235 devidSize = (_tcslen(DisplayDevice->DeviceID) + 1) * sizeof(TCHAR);
236 devid = HeapAlloc(GetProcessHeap(), 0, devidSize);
237 if (!devid) goto ByeBye;
238
239 memcpy(description, DisplayDevice->DeviceString, descriptionSize);
240 memcpy(name, DisplayDevice->DeviceName, nameSize);
241 memcpy(key, DisplayDevice->DeviceKey, keySize);
242 memcpy(devid, DisplayDevice->DeviceID, devidSize);
243 newEntry->DeviceDescription = description;
244 newEntry->DeviceName = name;
245 newEntry->DeviceKey = key;
246 newEntry->DeviceID = devid;
247 newEntry->DeviceStateFlags = DisplayDevice->StateFlags;
248 newEntry->Flink = pData->DisplayDeviceList;
249 pData->DisplayDeviceList = newEntry;
250 return TRUE;
251
252 ByeBye:
253 if (newEntry != NULL)
254 {
255 if (newEntry->Settings != NULL)
256 {
257 Current = newEntry->Settings;
258 while (Current != NULL)
259 {
260 PSETTINGS_ENTRY Next = Current->Flink;
261 HeapFree(GetProcessHeap(), 0, Current);
262 Current = Next;
263 }
264 }
265 if (newEntry->Resolutions != NULL)
266 HeapFree(GetProcessHeap(), 0, newEntry->Resolutions);
267 HeapFree(GetProcessHeap(), 0, newEntry);
268 }
269 if (description != NULL)
270 HeapFree(GetProcessHeap(), 0, description);
271 if (name != NULL)
272 HeapFree(GetProcessHeap(), 0, name);
273 if (key != NULL)
274 HeapFree(GetProcessHeap(), 0, key);
275 return FALSE;
276 }
277
278 static VOID
OnDisplayDeviceChanged(IN HWND hwndDlg,IN PSETTINGS_DATA pData,IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)279 OnDisplayDeviceChanged(IN HWND hwndDlg, IN PSETTINGS_DATA pData, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
280 {
281 PSETTINGS_ENTRY Current;
282 DWORD index;
283
284 pData->CurrentDisplayDevice = pDeviceEntry; /* Update variable */
285
286 /* Fill color depths combo box */
287 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_RESETCONTENT, 0, 0);
288 for (Current = pDeviceEntry->Settings; Current != NULL; Current = Current->Flink)
289 {
290 TCHAR Buffer[64];
291 if (LoadString(hApplet, (2900 + Current->dmBitsPerPel), Buffer, _countof(Buffer)))
292 {
293 index = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
294 if (index == (DWORD)CB_ERR)
295 {
296 index = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_ADDSTRING, 0, (LPARAM)Buffer);
297 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SETITEMDATA, index, Current->dmBitsPerPel);
298 }
299 }
300 }
301
302 /* Fill device description */
303 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pDeviceEntry->DeviceDescription);
304
305 /* Fill resolutions slider */
306 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_CLEARTICS, TRUE, 0);
307 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETRANGE, TRUE, MAKELONG(0, pDeviceEntry->ResolutionsCount - 1));
308
309 UpdateDisplay(hwndDlg, pData, TRUE);
310 }
311
312 static VOID
SettingsOnInitDialog(IN HWND hwndDlg)313 SettingsOnInitDialog(IN HWND hwndDlg)
314 {
315 BITMAP bitmap;
316 DWORD Result = 0;
317 DWORD iDevNum = 0;
318 DWORD i;
319 DISPLAY_DEVICE displayDevice;
320 PSETTINGS_DATA pData;
321
322 pData = HeapAlloc(GetProcessHeap(), 0, sizeof(SETTINGS_DATA));
323 if (pData == NULL)
324 return;
325
326 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pData);
327
328 /* Get video cards list */
329 pData->DisplayDeviceList = NULL;
330 displayDevice.cb = sizeof(displayDevice);
331 while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
332 {
333 if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0)
334 {
335 if (AddDisplayDevice(pData, &displayDevice))
336 Result++;
337 }
338 iDevNum++;
339 }
340
341 if (Result == 0)
342 {
343 /* No adapter found */
344 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_BPP), FALSE);
345 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION), FALSE);
346 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT), FALSE);
347 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_ADVANCED), FALSE);
348 ShowWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_SPECTRUM), SW_HIDE);
349
350 /* Do not initialize the color spectrum bitmaps */
351 memset(pData->hSpectrumBitmaps, 0, sizeof(pData->hSpectrumBitmaps));
352 return;
353 }
354 else if (Result == 1)
355 {
356 MONSL_MONINFO monitors;
357
358 /* Single video adapter */
359 OnDisplayDeviceChanged(hwndDlg, pData, pData->DisplayDeviceList);
360
361 ShowWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_MONTEXT), SW_HIDE);
362 ShowWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_MONSEL), SW_HIDE);
363
364 monitors.Position.x = monitors.Position.y = 0;
365 monitors.Size.cx = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
366 monitors.Size.cy = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
367 monitors.Flags = 0;
368 SendDlgItemMessage(hwndDlg,
369 IDC_SETTINGS_MONSEL,
370 MSLM_SETMONITORSINFO,
371 1,
372 (LPARAM)&monitors);
373 }
374 else /* FIXME: Incomplete! */
375 {
376 PMONSL_MONINFO pMonitors;
377 DWORD i;
378
379 OnDisplayDeviceChanged(hwndDlg, pData, pData->DisplayDeviceList);
380
381 ShowWindow(GetDlgItem(hwndDlg, IDC_RESOLUTION_PREVIEW), SW_HIDE);
382
383 pMonitors = (PMONSL_MONINFO)HeapAlloc(GetProcessHeap(), 0, sizeof(MONSL_MONINFO) * Result);
384 if (pMonitors)
385 {
386 DWORD hack = 1280;
387 for (i = 0; i < Result; i++)
388 {
389 pMonitors[i].Position.x = hack * i;
390 pMonitors[i].Position.y = 0;
391 pMonitors[i].Size.cx = pData->DisplayDeviceList->CurrentSettings->dmPelsWidth;
392 pMonitors[i].Size.cy = pData->DisplayDeviceList->CurrentSettings->dmPelsHeight;
393 pMonitors[i].Flags = 0;
394 }
395
396 SendDlgItemMessage(hwndDlg,
397 IDC_SETTINGS_MONSEL,
398 MSLM_SETMONITORSINFO,
399 Result,
400 (LPARAM)pMonitors);
401
402 HeapFree(GetProcessHeap(), 0, pMonitors);
403 }
404 }
405
406 /* Initialize the color spectrum bitmaps */
407 for (i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
408 {
409 pData->hSpectrumBitmaps[i] = LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_SPECTRUM_4 + i), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
410
411 if (pData->hSpectrumBitmaps[i] != NULL)
412 {
413 if (GetObjectW(pData->hSpectrumBitmaps[i], sizeof(BITMAP), &bitmap) != 0)
414 {
415 pData->cxSource[i] = bitmap.bmWidth;
416 pData->cySource[i] = bitmap.bmHeight;
417 }
418 else
419 {
420 pData->cxSource[i] = 0;
421 pData->cySource[i] = 0;
422 }
423 }
424 }
425 }
426
427 static VOID
ShowResolutionPreview(IN LPDRAWITEMSTRUCT draw,IN PSETTINGS_DATA pData)428 ShowResolutionPreview(IN LPDRAWITEMSTRUCT draw, IN PSETTINGS_DATA pData)
429 {
430 HBRUSH hBrush;
431 HDC hDC;
432 HGDIOBJ hOldObj;
433 RECT rcItem = {
434 MONITOR_LEFT,
435 MONITOR_TOP,
436 MONITOR_RIGHT,
437 MONITOR_BOTTOM
438 };
439
440 hDC = CreateCompatibleDC(draw->hDC);
441 hOldObj = SelectObject(hDC, g_GlobalData.hMonitorBitmap);
442
443 /* FIXME: Draw resolution preview bitmap inside monitor. */
444 hBrush = CreateSolidBrush(g_GlobalData.desktop_color);
445 FillRect(hDC, &rcItem, hBrush);
446 DeleteObject(hBrush);
447
448 GdiTransparentBlt(draw->hDC,
449 draw->rcItem.left, draw->rcItem.top,
450 draw->rcItem.right - draw->rcItem.left + 1,
451 draw->rcItem.bottom - draw->rcItem.top + 1,
452 hDC,
453 0, 0,
454 g_GlobalData.bmMonWidth, g_GlobalData.bmMonHeight,
455 MONITOR_ALPHA);
456
457 SelectObject(hDC, hOldObj);
458 DeleteDC(hDC);
459 }
460
461 /* Get the ID for SETTINGS_DATA::hSpectrumBitmaps */
462 static VOID
ShowColorSpectrum(IN HDC hDC,IN LPRECT client,IN DWORD BitsPerPel,IN PSETTINGS_DATA pData)463 ShowColorSpectrum(IN HDC hDC, IN LPRECT client, IN DWORD BitsPerPel, IN PSETTINGS_DATA pData)
464 {
465 HDC hdcMem;
466 INT iBitmap;
467
468 hdcMem = CreateCompatibleDC(hDC);
469
470 if (!hdcMem)
471 return;
472
473 switch(BitsPerPel)
474 {
475 case 4: iBitmap = 0; break;
476 case 8: iBitmap = 1; break;
477 default: iBitmap = 2;
478 }
479
480 if (SelectObject(hdcMem, pData->hSpectrumBitmaps[iBitmap]))
481 {
482 StretchBlt(hDC,
483 client->left, client->top,
484 client->right - client->left,
485 client->bottom - client->top,
486 hdcMem, 0, 0,
487 pData->cxSource[iBitmap],
488 pData->cySource[iBitmap], SRCCOPY);
489 }
490
491 DeleteDC(hdcMem);
492 }
493
494 static VOID
OnBPPChanged(IN HWND hwndDlg,IN PSETTINGS_DATA pData)495 OnBPPChanged(IN HWND hwndDlg, IN PSETTINGS_DATA pData)
496 {
497 /* If new BPP is not compatible with resolution:
498 * 1) try to find the nearest smaller matching resolution
499 * 2) otherwise, get the nearest bigger resolution
500 */
501 PSETTINGS_ENTRY Current;
502 DWORD dmNewBitsPerPel;
503 DWORD index;
504 HDC hSpectrumDC;
505 HWND hSpectrumControl;
506 RECT client;
507
508 index = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETCURSEL, 0, 0);
509 dmNewBitsPerPel = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
510
511 /* Show a new spectrum bitmap */
512 hSpectrumControl = GetDlgItem(hwndDlg, IDC_SETTINGS_SPECTRUM);
513 hSpectrumDC = GetDC(hSpectrumControl);
514 if (hSpectrumDC == NULL)
515 return;
516
517 GetClientRect(hSpectrumControl, &client);
518 ShowColorSpectrum(hSpectrumDC, &client, dmNewBitsPerPel, pData);
519 ReleaseDC(hSpectrumControl, hSpectrumDC);
520
521 /* Find if new parameters are valid */
522 Current = pData->CurrentDisplayDevice->CurrentSettings;
523 if (dmNewBitsPerPel == Current->dmBitsPerPel)
524 {
525 /* No change */
526 return;
527 }
528
529 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
530
531 if (dmNewBitsPerPel < Current->dmBitsPerPel)
532 {
533 Current = Current->Blink;
534 while (Current != NULL)
535 {
536 if (Current->dmBitsPerPel == dmNewBitsPerPel
537 && Current->dmPelsHeight == pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
538 && Current->dmPelsWidth == pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
539 {
540 pData->CurrentDisplayDevice->CurrentSettings = Current;
541 UpdateDisplay(hwndDlg, pData, TRUE);
542 return;
543 }
544 Current = Current->Blink;
545 }
546 }
547 else
548 {
549 Current = Current->Flink;
550 while (Current != NULL)
551 {
552 if (Current->dmBitsPerPel == dmNewBitsPerPel
553 && Current->dmPelsHeight == pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
554 && Current->dmPelsWidth == pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
555 {
556 pData->CurrentDisplayDevice->CurrentSettings = Current;
557 UpdateDisplay(hwndDlg, pData, TRUE);
558 return;
559 }
560 Current = Current->Flink;
561 }
562 }
563
564 /* Search smaller resolution compatible with current color depth */
565 Current = pData->CurrentDisplayDevice->CurrentSettings->Blink;
566 while (Current != NULL)
567 {
568 if (Current->dmBitsPerPel == dmNewBitsPerPel)
569 {
570 pData->CurrentDisplayDevice->CurrentSettings = Current;
571 UpdateDisplay(hwndDlg, pData, TRUE);
572 return;
573 }
574 Current = Current->Blink;
575 }
576
577 /* Search bigger resolution compatible with current color depth */
578 Current = pData->CurrentDisplayDevice->CurrentSettings->Flink;
579 while (Current != NULL)
580 {
581 if (Current->dmBitsPerPel == dmNewBitsPerPel)
582 {
583 pData->CurrentDisplayDevice->CurrentSettings = Current;
584 UpdateDisplay(hwndDlg, pData, TRUE);
585 return;
586 }
587 Current = Current->Flink;
588 }
589
590 /* We shouldn't go there */
591 }
592
593 static VOID
OnResolutionChanged(IN HWND hwndDlg,IN PSETTINGS_DATA pData,IN DWORD NewPosition,IN BOOL bUpdateThumb)594 OnResolutionChanged(IN HWND hwndDlg, IN PSETTINGS_DATA pData, IN DWORD NewPosition,
595 IN BOOL bUpdateThumb)
596 {
597 /* If new resolution is not compatible with color depth:
598 * 1) try to find the nearest bigger matching color depth
599 * 2) otherwise, get the nearest smaller color depth
600 */
601 PSETTINGS_ENTRY Current;
602 DWORD dmNewPelsHeight = pData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
603 DWORD dmNewPelsWidth = pData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
604 DWORD dmBitsPerPel;
605 DWORD dmDisplayFrequency;
606
607 /* Find if new parameters are valid */
608 Current = pData->CurrentDisplayDevice->CurrentSettings;
609 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
610 {
611 /* No change */
612 return;
613 }
614
615 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
616 InvalidateRect(GetDlgItem(hwndDlg, IDC_RESOLUTION_PREVIEW), NULL, TRUE);
617
618 dmBitsPerPel = Current->dmBitsPerPel;
619 dmDisplayFrequency = Current->dmDisplayFrequency;
620
621 if (CompareSettings(Current, dmNewPelsWidth,
622 dmNewPelsHeight, dmBitsPerPel,
623 dmDisplayFrequency) < 0)
624 {
625 Current = Current->Blink;
626 while (Current != NULL)
627 {
628 if (Current->dmPelsHeight == dmNewPelsHeight
629 && Current->dmPelsWidth == dmNewPelsWidth
630 && Current->dmBitsPerPel == dmBitsPerPel)
631 {
632 pData->CurrentDisplayDevice->CurrentSettings = Current;
633 UpdateDisplay(hwndDlg, pData, bUpdateThumb);
634 return;
635 }
636 Current = Current->Blink;
637 }
638 }
639 else
640 {
641 Current = Current->Flink;
642 while (Current != NULL)
643 {
644 if (Current->dmPelsHeight == dmNewPelsHeight
645 && Current->dmPelsWidth == dmNewPelsWidth
646 && Current->dmBitsPerPel == dmBitsPerPel)
647 {
648 pData->CurrentDisplayDevice->CurrentSettings = Current;
649 UpdateDisplay(hwndDlg, pData, bUpdateThumb);
650 return;
651 }
652 Current = Current->Flink;
653 }
654 }
655
656 /* Search bigger color depth compatible with current resolution */
657 Current = pData->CurrentDisplayDevice->CurrentSettings->Flink;
658 while (Current != NULL)
659 {
660 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
661 {
662 pData->CurrentDisplayDevice->CurrentSettings = Current;
663 UpdateDisplay(hwndDlg, pData, bUpdateThumb);
664 return;
665 }
666 Current = Current->Flink;
667 }
668
669 /* Search smaller color depth compatible with current resolution */
670 Current = pData->CurrentDisplayDevice->CurrentSettings->Blink;
671 while (Current != NULL)
672 {
673 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
674 {
675 pData->CurrentDisplayDevice->CurrentSettings = Current;
676 UpdateDisplay(hwndDlg, pData, bUpdateThumb);
677 return;
678 }
679 Current = Current->Blink;
680 }
681
682 /* We shouldn't go there */
683 }
684
685 /* Property sheet page callback */
686 UINT CALLBACK
SettingsPageCallbackProc(HWND hwnd,UINT uMsg,LPPROPSHEETPAGE ppsp)687 SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
688 {
689 UINT Ret = 0;
690
691 switch (uMsg)
692 {
693 case PSPCB_CREATE:
694 Ret = RegisterMonitorSelectionControl(hApplet);
695 break;
696
697 case PSPCB_RELEASE:
698 UnregisterMonitorSelectionControl(hApplet);
699 break;
700 }
701
702 return Ret;
703 }
704
705 static INT_PTR CALLBACK
ConfirmDlgProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)706 ConfirmDlgProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
707 {
708 PTIMEOUTDATA pData;
709
710 pData = (PTIMEOUTDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
711
712 switch(uMsg)
713 {
714 case WM_INITDIALOG:
715 /* Allocate the local dialog data */
716 pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEOUTDATA));
717 if (pData == NULL)
718 return FALSE;
719
720 /* Link the dialog data to the dialog */
721 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pData);
722
723 /* Timeout in seconds */
724 pData->nTimeout = 15;
725
726 /* Load the raw timeout string */
727 LoadString(hApplet, IDS_TIMEOUTTEXT, pData->szRawBuffer, _countof(pData->szRawBuffer));
728
729 /* Cook the timeout string and show it */
730 _stprintf(pData->szCookedBuffer, pData->szRawBuffer, pData->nTimeout);
731 SetDlgItemText(hwndDlg, IDC_TIMEOUTTEXT, pData->szCookedBuffer);
732
733 /* Start the timer (ticks every second)*/
734 SetTimer(hwndDlg, 1, 1000, NULL);
735 break;
736
737 case WM_TIMER:
738 /* Update the timepout value */
739 pData->nTimeout--;
740
741 /* Update the timeout text */
742 _stprintf(pData->szCookedBuffer, pData->szRawBuffer, pData->nTimeout);
743 SetDlgItemText(hwndDlg, IDC_TIMEOUTTEXT, pData->szCookedBuffer);
744
745 /* Kill the timer and return a 'No', if we ran out of time */
746 if (pData->nTimeout == 0)
747 {
748 KillTimer(hwndDlg, 1);
749 EndDialog(hwndDlg, IDNO);
750 }
751 break;
752
753 case WM_COMMAND:
754 /* Kill the timer and return the clicked button id */
755 KillTimer(hwndDlg, 1);
756 EndDialog(hwndDlg, LOWORD(wParam));
757 break;
758
759 case WM_DESTROY:
760 /* Free the local dialog data */
761 HeapFree(GetProcessHeap(), 0, pData);
762 break;
763 }
764
765 return FALSE;
766 }
767
768 BOOL
SwitchDisplayMode(HWND hwndDlg,PWSTR DeviceName,PSETTINGS_ENTRY seInit,PSETTINGS_ENTRY seNew,OUT PLONG rc)769 SwitchDisplayMode(HWND hwndDlg, PWSTR DeviceName, PSETTINGS_ENTRY seInit, PSETTINGS_ENTRY seNew, OUT PLONG rc)
770 {
771 TCHAR Message[1024], Title[256];
772 DEVMODE devmode;
773
774 RtlZeroMemory(&devmode, sizeof(devmode));
775 devmode.dmSize = (WORD)sizeof(devmode);
776 devmode.dmPelsWidth = seNew->dmPelsWidth;
777 devmode.dmPelsHeight = seNew->dmPelsHeight;
778 devmode.dmBitsPerPel = seNew->dmBitsPerPel;
779 devmode.dmDisplayFrequency = seNew->dmDisplayFrequency;
780 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
781
782 *rc = ChangeDisplaySettingsEx(DeviceName,
783 &devmode,
784 NULL,
785 CDS_UPDATEREGISTRY,
786 NULL);
787 switch (*rc)
788 {
789 case DISP_CHANGE_SUCCESSFUL:
790 break;
791
792 case DISP_CHANGE_RESTART:
793 LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, _countof(Title));
794 LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, _countof(Message));
795 MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION);
796 return FALSE;
797
798 case DISP_CHANGE_FAILED:
799 default:
800 LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, _countof(Title));
801 LoadString(hApplet, IDS_APPLY_FAILED, Message, _countof(Message));
802 MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP);
803 return FALSE;
804 }
805
806 if (DialogBox(hApplet, MAKEINTRESOURCE(IDD_CONFIRMSETTINGS), hwndDlg, ConfirmDlgProc) == IDYES)
807 {
808 return TRUE;
809 }
810 else
811 {
812 devmode.dmPelsWidth = seInit->dmPelsWidth;
813 devmode.dmPelsHeight = seInit->dmPelsHeight;
814 devmode.dmBitsPerPel = seInit->dmBitsPerPel;
815 devmode.dmDisplayFrequency = seInit->dmDisplayFrequency;
816
817 *rc = ChangeDisplaySettingsEx(DeviceName,
818 &devmode,
819 NULL,
820 CDS_UPDATEREGISTRY,
821 NULL);
822 switch (*rc)
823 {
824 case DISP_CHANGE_SUCCESSFUL:
825 return FALSE;
826
827 case DISP_CHANGE_RESTART:
828 LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, _countof(Title));
829 LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, _countof(Message));
830 MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION);
831 return FALSE;
832
833 case DISP_CHANGE_FAILED:
834 default:
835 LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, _countof(Title));
836 LoadString(hApplet, IDS_APPLY_FAILED, Message, _countof(Message));
837 MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP);
838 return FALSE;
839 }
840 }
841 }
842
843 static
844 PSETTINGS_ENTRY
FindBestElement(_In_ PDISPLAY_DEVICE_ENTRY pDevice)845 FindBestElement(
846 _In_ PDISPLAY_DEVICE_ENTRY pDevice)
847 {
848 PSETTINGS_ENTRY Request = &pDevice->InitialSettings, BestEntry = NULL, Current;
849 LONG Distance, NearestDistance = MAXLONG;
850
851 /* Find the best entry in the list */
852 for (Current = pDevice->Settings; Current; Current = Current->Flink)
853 {
854 Distance = 0x100000 * labs(Current->dmBitsPerPel - Request->dmBitsPerPel ) +
855 0x100 * labs(Current->dmPelsWidth - Request->dmPelsWidth ) +
856 0x100 * labs(Current->dmPelsHeight - Request->dmPelsHeight ) +
857 labs(Current->dmDisplayFrequency - Request->dmDisplayFrequency);
858 if (Distance == 0)
859 return Current;
860
861 if (Distance < NearestDistance)
862 {
863 BestEntry = Current;
864 NearestDistance = Distance;
865 }
866 }
867
868 return BestEntry;
869 }
870
871 static VOID
ApplyDisplaySettings(HWND hwndDlg,PSETTINGS_DATA pData)872 ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData)
873 {
874 BOOL Ret;
875 LONG rc;
876
877 Ret = SwitchDisplayMode(hwndDlg,
878 pData->CurrentDisplayDevice->DeviceName,
879 &pData->CurrentDisplayDevice->InitialSettings,
880 pData->CurrentDisplayDevice->CurrentSettings,
881 &rc);
882
883 if (rc != DISP_CHANGE_SUCCESSFUL)
884 return;
885
886 if (Ret)
887 {
888 pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
889 pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
890 pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
891 pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency = pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency;
892 }
893 else
894 {
895 pData->CurrentDisplayDevice->CurrentSettings = FindBestElement(pData->CurrentDisplayDevice);
896 UpdateDisplay(hwndDlg, pData, TRUE);
897 }
898 }
899
900 /* Property page dialog callback */
901 INT_PTR CALLBACK
SettingsPageProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)902 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
903 {
904 PSETTINGS_DATA pData;
905
906 pData = (PSETTINGS_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
907
908 switch(uMsg)
909 {
910 case WM_INITDIALOG:
911 {
912 SettingsOnInitDialog(hwndDlg);
913 break;
914 }
915 case WM_DRAWITEM:
916 {
917 LPDRAWITEMSTRUCT lpDrawItem;
918 lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
919
920 switch (lpDrawItem->CtlID)
921 {
922 case IDC_RESOLUTION_PREVIEW:
923 {
924 ShowResolutionPreview(lpDrawItem, pData);
925 break;
926 }
927 case IDC_SETTINGS_SPECTRUM:
928 {
929 ShowColorSpectrum(lpDrawItem->hDC, &lpDrawItem->rcItem, pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel, pData);
930 break;
931 }
932 }
933 break;
934 }
935 case WM_COMMAND:
936 {
937 DWORD controlId = LOWORD(wParam);
938 DWORD command = HIWORD(wParam);
939
940 if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
941 {
942 if (DisplayAdvancedSettings(hwndDlg, pData->CurrentDisplayDevice))
943 {
944 DEVMODE devmode;
945 ZeroMemory(&devmode, sizeof(devmode));
946 devmode.dmSize = (WORD)sizeof(devmode);
947 if (EnumDisplaySettingsExW(pData->CurrentDisplayDevice->DeviceName,
948 ENUM_CURRENT_SETTINGS, &devmode, 0))
949 {
950 PSETTINGS_ENTRY pInitialSettings = &pData->CurrentDisplayDevice->InitialSettings;
951 pInitialSettings->dmPelsWidth = devmode.dmPelsWidth;
952 pInitialSettings->dmPelsHeight = devmode.dmPelsHeight;
953 pInitialSettings->dmBitsPerPel = devmode.dmBitsPerPel;
954 pInitialSettings->dmDisplayFrequency = devmode.dmDisplayFrequency;
955 pData->CurrentDisplayDevice->CurrentSettings =
956 FindBestElement(pData->CurrentDisplayDevice);
957 UpdateDisplay(hwndDlg, pData, TRUE);
958 }
959 }
960 }
961 else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
962 OnBPPChanged(hwndDlg, pData);
963 break;
964 }
965 case WM_HSCROLL:
966 {
967 switch (LOWORD(wParam))
968 {
969 case TB_LINEUP:
970 case TB_LINEDOWN:
971 case TB_PAGEUP:
972 case TB_PAGEDOWN:
973 case TB_TOP:
974 case TB_BOTTOM:
975 case TB_ENDTRACK:
976 {
977 DWORD newPosition = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
978 OnResolutionChanged(hwndDlg, pData, newPosition, TRUE);
979 break;
980 }
981
982 case TB_THUMBTRACK:
983 OnResolutionChanged(hwndDlg, pData, HIWORD(wParam), FALSE);
984 break;
985 }
986 break;
987 }
988 case WM_NOTIFY:
989 {
990 LPNMHDR lpnm = (LPNMHDR)lParam;
991 if (lpnm->code == (UINT)PSN_APPLY)
992 {
993 if (pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth != pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth
994 || pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight != pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight
995 || pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
996 {
997 /* Apply new settings */
998 ApplyDisplaySettings(hwndDlg, pData);
999 }
1000 }
1001 else if (lpnm->code == MSLN_MONITORCHANGED)
1002 {
1003 PMONSL_MONNMMONITORCHANGING lpnmi = (PMONSL_MONNMMONITORCHANGING)lParam;
1004 PDISPLAY_DEVICE_ENTRY Current = pData->DisplayDeviceList;
1005 ULONG i;
1006 for (i = 0; i < lpnmi->hdr.Index; i++)
1007 Current = Current->Flink;
1008 OnDisplayDeviceChanged(hwndDlg, pData, Current);
1009 }
1010 break;
1011 }
1012
1013 case WM_CONTEXTMENU:
1014 {
1015 HWND hwndMonSel;
1016 HMENU hPopup;
1017 UINT uiCmd;
1018 POINT pt, ptClient;
1019 INT Index;
1020
1021 pt.x = (SHORT)LOWORD(lParam);
1022 pt.y = (SHORT)HIWORD(lParam);
1023
1024 hwndMonSel = GetDlgItem(hwndDlg, IDC_SETTINGS_MONSEL);
1025 if ((HWND)wParam == hwndMonSel)
1026 {
1027 if (pt.x == -1 && pt.y == -1)
1028 {
1029 RECT rcMon;
1030
1031 Index = (INT)SendMessage(hwndMonSel,
1032 MSLM_GETCURSEL,
1033 0,
1034 0);
1035
1036 if (Index >= 0 &&
1037 (INT)SendMessage(hwndMonSel,
1038 MSLM_GETMONITORRECT,
1039 Index,
1040 (LPARAM)&rcMon) > 0)
1041 {
1042 pt.x = rcMon.left + ((rcMon.right - rcMon.left) / 2);
1043 pt.y = rcMon.top + ((rcMon.bottom - rcMon.top) / 2);
1044 }
1045 else
1046 pt.x = pt.y = 0;
1047
1048 MapWindowPoints(hwndMonSel, NULL, &pt, 1);
1049 }
1050 else
1051 {
1052 ptClient = pt;
1053 MapWindowPoints(NULL, hwndMonSel, &ptClient, 1);
1054
1055 Index = (INT)SendMessage(hwndMonSel,
1056 MSLM_HITTEST,
1057 (WPARAM)&ptClient,
1058 0);
1059 }
1060
1061 if (Index >= 0)
1062 {
1063 hPopup = LoadPopupMenu(hApplet,
1064 MAKEINTRESOURCE(IDM_MONITOR_MENU));
1065 if (hPopup != NULL)
1066 {
1067 /* FIXME: Enable/Disable menu items */
1068 EnableMenuItem(hPopup,
1069 ID_MENU_ATTACHED,
1070 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1071 EnableMenuItem(hPopup,
1072 ID_MENU_PRIMARY,
1073 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1074 EnableMenuItem(hPopup,
1075 ID_MENU_IDENTIFY,
1076 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1077 EnableMenuItem(hPopup,
1078 ID_MENU_PROPERTIES,
1079 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1080
1081 uiCmd = (UINT)TrackPopupMenu(hPopup,
1082 TPM_RETURNCMD | TPM_RIGHTBUTTON,
1083 pt.x,
1084 pt.y,
1085 0,
1086 hwndDlg,
1087 NULL);
1088
1089 switch (uiCmd)
1090 {
1091 case ID_MENU_ATTACHED:
1092 case ID_MENU_PRIMARY:
1093 case ID_MENU_IDENTIFY:
1094 case ID_MENU_PROPERTIES:
1095 /* FIXME: Implement */
1096 break;
1097 }
1098
1099 DestroyMenu(hPopup);
1100 }
1101 }
1102 }
1103 break;
1104 }
1105
1106 case WM_DESTROY:
1107 {
1108 DWORD i;
1109 PDISPLAY_DEVICE_ENTRY Current = pData->DisplayDeviceList;
1110
1111 while (Current != NULL)
1112 {
1113 PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
1114 PSETTINGS_ENTRY CurrentSettings = Current->Settings;
1115 while (CurrentSettings != NULL)
1116 {
1117 PSETTINGS_ENTRY NextSettings = CurrentSettings->Flink;
1118 HeapFree(GetProcessHeap(), 0, CurrentSettings);
1119 CurrentSettings = NextSettings;
1120 }
1121 HeapFree(GetProcessHeap(), 0, Current);
1122 Current = Next;
1123 }
1124
1125 for (i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
1126 {
1127 if (pData->hSpectrumBitmaps[i])
1128 DeleteObject(pData->hSpectrumBitmaps[i]);
1129 }
1130
1131 HeapFree(GetProcessHeap(), 0, pData);
1132 }
1133 }
1134 return FALSE;
1135 }
1136