Merging r37048, r37051, r37052, r37055 from the-real-msvc branch
[reactos.git] / reactos / dll / cpl / desk / settings.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: lib/cpl/desk/settings.c
5 * PURPOSE: Settings property page
6 *
7 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
8 * Hervé Poussineau (hpoussin@reactos.org)
9 */
10
11 #include "desk.h"
12 #include "monslctl.h"
13
14 typedef struct _GLOBAL_DATA
15 {
16 PDISPLAY_DEVICE_ENTRY DisplayDeviceList;
17 PDISPLAY_DEVICE_ENTRY CurrentDisplayDevice;
18 HBITMAP hSpectrumBitmaps[NUM_SPECTRUM_BITMAPS];
19 int cxSource[NUM_SPECTRUM_BITMAPS];
20 int cySource[NUM_SPECTRUM_BITMAPS];
21 } GLOBAL_DATA, *PGLOBAL_DATA;
22
23
24 static VOID
25 UpdateDisplay(IN HWND hwndDlg, PGLOBAL_DATA pGlobalData, IN BOOL bUpdateThumb)
26 {
27 TCHAR Buffer[64];
28 TCHAR Pixel[64];
29 DWORD index;
30
31 LoadString(hApplet, IDS_PIXEL, Pixel, sizeof(Pixel) / sizeof(TCHAR));
32 _stprintf(Buffer, Pixel, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight, Pixel);
33 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT, WM_SETTEXT, 0, (LPARAM)Buffer);
34
35 for (index = 0; index < pGlobalData->CurrentDisplayDevice->ResolutionsCount; index++)
36 {
37 if (pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth &&
38 pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight)
39 {
40 if (bUpdateThumb)
41 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETPOS, TRUE, index);
42 break;
43 }
44 }
45 if (LoadString(hApplet, (2900 + pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
46 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)Buffer);
47 }
48
49 static PSETTINGS_ENTRY
50 GetPossibleSettings(IN LPCTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings)
51 {
52 DEVMODE devmode;
53 DWORD NbSettings = 0;
54 DWORD iMode = 0;
55 DWORD dwFlags = 0;
56 PSETTINGS_ENTRY Settings = NULL;
57 HDC hDC;
58 PSETTINGS_ENTRY Current;
59 DWORD bpp, xres, yres, checkbpp;
60 DWORD curDispFreq;
61
62 /* Get current settings */
63 *CurrentSettings = NULL;
64 hDC = CreateIC(NULL, DeviceName, NULL, NULL);
65 bpp = GetDeviceCaps(hDC, PLANES);
66 bpp *= GetDeviceCaps(hDC, BITSPIXEL);
67 xres = GetDeviceCaps(hDC, HORZRES);
68 yres = GetDeviceCaps(hDC, VERTRES);
69 DeleteDC(hDC);
70
71 /* List all settings */
72 devmode.dmSize = (WORD)sizeof(DEVMODE);
73 devmode.dmDriverExtra = 0;
74
75 if (!EnumDisplaySettingsEx(DeviceName, ENUM_CURRENT_SETTINGS, &devmode, dwFlags))
76 return NULL;
77
78 curDispFreq = devmode.dmDisplayFrequency;
79
80 while (EnumDisplaySettingsEx(DeviceName, iMode, &devmode, dwFlags))
81 {
82 if ((devmode.dmBitsPerPel == 4 ||
83 devmode.dmBitsPerPel == 8 ||
84 devmode.dmBitsPerPel == 16 ||
85 devmode.dmBitsPerPel == 24 ||
86 devmode.dmBitsPerPel == 32) &&
87 devmode.dmDisplayFrequency == curDispFreq)
88 {
89 checkbpp=1;
90 }
91 else
92 checkbpp=0;
93
94 if (devmode.dmPelsWidth < 640 ||
95 devmode.dmPelsHeight < 480 || checkbpp == 0)
96 {
97 iMode++;
98 continue;
99 }
100
101 Current = HeapAlloc(GetProcessHeap(), 0, sizeof(SETTINGS_ENTRY));
102 if (Current != NULL)
103 {
104 /* Sort resolutions by increasing height, and BPP */
105 PSETTINGS_ENTRY Previous = NULL;
106 PSETTINGS_ENTRY Next = Settings;
107 Current->dmPelsWidth = devmode.dmPelsWidth;
108 Current->dmPelsHeight = devmode.dmPelsHeight;
109 Current->dmBitsPerPel = devmode.dmBitsPerPel;
110 while (Next != NULL && (
111 Next->dmPelsWidth < Current->dmPelsWidth ||
112 (Next->dmPelsWidth == Current->dmPelsWidth && Next->dmPelsHeight < Current->dmPelsHeight) ||
113 (Next->dmPelsHeight == Current->dmPelsHeight &&
114 Next->dmPelsWidth == Current->dmPelsWidth &&
115 Next->dmBitsPerPel < Current->dmBitsPerPel )))
116 {
117 Previous = Next;
118 Next = Next->Flink;
119 }
120 Current->Blink = Previous;
121 Current->Flink = Next;
122 if (Previous == NULL)
123 Settings = Current;
124 else
125 Previous->Flink = Current;
126 if (Next != NULL)
127 Next->Blink = Current;
128 if (devmode.dmPelsWidth == xres && devmode.dmPelsHeight == yres && devmode.dmBitsPerPel == bpp)
129 {
130 *CurrentSettings = Current;
131 }
132 NbSettings++;
133 }
134 iMode++;
135 }
136
137 *pSettingsCount = NbSettings;
138 return Settings;
139 }
140
141 static BOOL
142 AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN const DISPLAY_DEVICE *DisplayDevice)
143 {
144 PDISPLAY_DEVICE_ENTRY newEntry = NULL;
145 LPTSTR description = NULL;
146 LPTSTR name = NULL;
147 LPTSTR key = NULL;
148 LPTSTR devid = NULL;
149 DWORD descriptionSize, nameSize, keySize, devidSize;
150 PSETTINGS_ENTRY Current;
151 DWORD ResolutionsCount = 1;
152 DWORD i;
153
154 newEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(DISPLAY_DEVICE_ENTRY));
155 memset(newEntry, 0, sizeof(DISPLAY_DEVICE_ENTRY));
156 if (!newEntry) goto ByeBye;
157
158 newEntry->Settings = GetPossibleSettings(DisplayDevice->DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings);
159 if (!newEntry->Settings) goto ByeBye;
160
161 newEntry->InitialSettings.dmPelsWidth = newEntry->CurrentSettings->dmPelsWidth;
162 newEntry->InitialSettings.dmPelsHeight = newEntry->CurrentSettings->dmPelsHeight;
163 newEntry->InitialSettings.dmBitsPerPel = newEntry->CurrentSettings->dmBitsPerPel;
164
165 /* Count different resolutions */
166 for (Current = newEntry->Settings; Current != NULL; Current = Current->Flink)
167 {
168 if (Current->Flink != NULL &&
169 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) &&
170 (Current->dmPelsHeight != Current->Flink->dmPelsHeight)))
171 {
172 ResolutionsCount++;
173 }
174 }
175
176 newEntry->Resolutions = HeapAlloc(GetProcessHeap(), 0, ResolutionsCount * sizeof(RESOLUTION_INFO));
177 if (!newEntry->Resolutions) goto ByeBye;
178
179 newEntry->ResolutionsCount = ResolutionsCount;
180
181 /* Fill resolutions infos */
182 for (Current = newEntry->Settings, i = 0; Current != NULL; Current = Current->Flink)
183 {
184 if (Current->Flink == NULL ||
185 (Current->Flink != NULL &&
186 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) &&
187 (Current->dmPelsHeight != Current->Flink->dmPelsHeight))))
188 {
189 newEntry->Resolutions[i].dmPelsWidth = Current->dmPelsWidth;
190 newEntry->Resolutions[i].dmPelsHeight = Current->dmPelsHeight;
191 i++;
192 }
193 }
194 descriptionSize = (_tcslen(DisplayDevice->DeviceString) + 1) * sizeof(TCHAR);
195 description = HeapAlloc(GetProcessHeap(), 0, descriptionSize);
196 if (!description) goto ByeBye;
197
198 nameSize = (_tcslen(DisplayDevice->DeviceName) + 1) * sizeof(TCHAR);
199 name = HeapAlloc(GetProcessHeap(), 0, nameSize);
200 if (!name) goto ByeBye;
201
202 keySize = (_tcslen(DisplayDevice->DeviceKey) + 1) * sizeof(TCHAR);
203 key = HeapAlloc(GetProcessHeap(), 0, keySize);
204 if (!key) goto ByeBye;
205
206 devidSize = (_tcslen(DisplayDevice->DeviceID) + 1) * sizeof(TCHAR);
207 devid = HeapAlloc(GetProcessHeap(), 0, devidSize);
208 if (!devid) goto ByeBye;
209
210 memcpy(description, DisplayDevice->DeviceString, descriptionSize);
211 memcpy(name, DisplayDevice->DeviceName, nameSize);
212 memcpy(key, DisplayDevice->DeviceKey, keySize);
213 memcpy(devid, DisplayDevice->DeviceID, devidSize);
214 newEntry->DeviceDescription = description;
215 newEntry->DeviceName = name;
216 newEntry->DeviceKey = key;
217 newEntry->DeviceID = devid;
218 newEntry->DeviceStateFlags = DisplayDevice->StateFlags;
219 newEntry->Flink = pGlobalData->DisplayDeviceList;
220 pGlobalData->DisplayDeviceList = newEntry;
221 return TRUE;
222
223 ByeBye:
224 if (newEntry != NULL)
225 {
226 if (newEntry->Settings != NULL)
227 {
228 Current = newEntry->Settings;
229 while (Current != NULL)
230 {
231 PSETTINGS_ENTRY Next = Current->Flink;
232 HeapFree(GetProcessHeap(), 0, Current);
233 Current = Next;
234 }
235 }
236 if (newEntry->Resolutions != NULL)
237 HeapFree(GetProcessHeap(), 0, newEntry->Resolutions);
238 HeapFree(GetProcessHeap(), 0, newEntry);
239 }
240 if (description != NULL)
241 HeapFree(GetProcessHeap(), 0, description);
242 if (name != NULL)
243 HeapFree(GetProcessHeap(), 0, name);
244 if (key != NULL)
245 HeapFree(GetProcessHeap(), 0, key);
246 return FALSE;
247 }
248
249 static VOID
250 OnDisplayDeviceChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
251 {
252 PSETTINGS_ENTRY Current;
253 DWORD index;
254
255 pGlobalData->CurrentDisplayDevice = pDeviceEntry; /* Update global variable */
256
257 /* Fill color depths combo box */
258 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_RESETCONTENT, 0, 0);
259 for (Current = pDeviceEntry->Settings; Current != NULL; Current = Current->Flink)
260 {
261 TCHAR Buffer[64];
262 if (LoadString(hApplet, (2900 + Current->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
263 {
264 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
265 if (index == (DWORD)CB_ERR)
266 {
267 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_ADDSTRING, 0, (LPARAM)Buffer);
268 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SETITEMDATA, index, Current->dmBitsPerPel);
269 }
270 }
271 }
272
273 /* Fill resolutions slider */
274 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_CLEARTICS, TRUE, 0);
275 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETRANGE, TRUE, MAKELONG(0, pDeviceEntry->ResolutionsCount - 1));
276
277 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
278 }
279
280 static VOID
281 OnInitDialog(IN HWND hwndDlg)
282 {
283 BITMAP bitmap;
284 DWORD Result = 0;
285 DWORD iDevNum = 0;
286 INT i;
287 DISPLAY_DEVICE displayDevice;
288 PGLOBAL_DATA pGlobalData;
289
290 pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA));
291 if (pGlobalData == NULL)
292 return;
293
294 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
295
296 /* Get video cards list */
297 displayDevice.cb = (DWORD)sizeof(DISPLAY_DEVICE);
298 while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0x1))
299 {
300 if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0)
301 {
302 if (AddDisplayDevice(pGlobalData, &displayDevice))
303 Result++;
304 }
305 iDevNum++;
306 }
307 if (Result == 0)
308 {
309 /* No adapter found */
310 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_BPP), FALSE);
311 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION), FALSE);
312 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT), FALSE);
313 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_ADVANCED), FALSE);
314 }
315 else if (Result == 1)
316 {
317 MONSL_MONINFO monitors;
318
319 /* Single video adapter */
320 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
321 OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
322
323 monitors.Position.x = monitors.Position.y = 0;
324 monitors.Size.cx = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
325 monitors.Size.cy = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
326 monitors.Flags = 0;
327 SendDlgItemMessage(hwndDlg,
328 IDC_SETTINGS_MONSEL,
329 MSLM_SETMONITORSINFO,
330 1,
331 (LPARAM)&monitors);
332 }
333 else /* FIXME: incomplete! */
334 {
335 PMONSL_MONINFO pMonitors;
336 INT i;
337
338 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
339 OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
340
341 pMonitors = (PMONSL_MONINFO)HeapAlloc(GetProcessHeap(), 0, sizeof(MONSL_MONINFO) * Result);
342 if (pMonitors)
343 {
344 INT hack = 1280;
345 for (i = 0; i < Result; i++)
346 {
347 pMonitors[i].Position.x = hack * i;
348 pMonitors[i].Position.y = 0;
349 pMonitors[i].Size.cx = pGlobalData->DisplayDeviceList->CurrentSettings->dmPelsWidth;
350 pMonitors[i].Size.cy = pGlobalData->DisplayDeviceList->CurrentSettings->dmPelsHeight;
351 pMonitors[i].Flags = 0;
352 }
353
354 SendDlgItemMessage(hwndDlg,
355 IDC_SETTINGS_MONSEL,
356 MSLM_SETMONITORSINFO,
357 Result,
358 (LPARAM)pMonitors);
359
360 HeapFree(GetProcessHeap(), 0, pMonitors);
361 }
362 }
363
364 /* Initialize the color spectrum bitmaps */
365 for(i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
366 {
367 pGlobalData->hSpectrumBitmaps[i] = LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_SPECTRUM_4 + i), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
368
369 if (pGlobalData->hSpectrumBitmaps[i] != NULL)
370 {
371 if (GetObjectW(pGlobalData->hSpectrumBitmaps[i], sizeof(BITMAP), &bitmap) != 0)
372 {
373 pGlobalData->cxSource[i] = bitmap.bmWidth;
374 pGlobalData->cySource[i] = bitmap.bmHeight;
375 }
376 else
377 {
378 pGlobalData->cxSource[i] = 0;
379 pGlobalData->cySource[i] = 0;
380 }
381 }
382 }
383 }
384
385 /* Get the ID for GLOBAL_DATA::hSpectrumBitmaps */
386 static VOID
387 ShowColorSpectrum(IN HDC hDC, IN LPRECT client, IN DWORD BitsPerPel, IN PGLOBAL_DATA pGlobalData)
388 {
389 HDC hdcMem;
390 INT iBitmap;
391
392 hdcMem = CreateCompatibleDC(hDC);
393
394 if (!hdcMem)
395 return;
396
397 switch(BitsPerPel)
398 {
399 case 4: iBitmap = 0; break;
400 case 8: iBitmap = 1; break;
401 default: iBitmap = 2;
402 }
403
404 SelectObject(hdcMem, pGlobalData->hSpectrumBitmaps[iBitmap]);
405 StretchBlt(hDC,
406 client->left, client->top, client->right - client->left, client->bottom - client->top,
407 hdcMem, 0, 0,
408 pGlobalData->cxSource[iBitmap],
409 pGlobalData->cySource[iBitmap], SRCCOPY);
410 DeleteDC(hdcMem);
411 }
412
413 static VOID
414 OnBPPChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData)
415 {
416 /* if new BPP is not compatible with resolution:
417 * 1) try to find the nearest smaller matching resolution
418 * 2) otherwise, get the nearest bigger resolution
419 */
420 PSETTINGS_ENTRY Current;
421 DWORD dmNewBitsPerPel;
422 DWORD index;
423 HDC hSpectrumDC;
424 HWND hSpectrumControl;
425 RECT client;
426
427 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETCURSEL, 0, 0);
428 dmNewBitsPerPel = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
429
430 /* Show a new spectrum bitmap */
431 hSpectrumControl = GetDlgItem(hwndDlg, IDC_SETTINGS_SPECTRUM);
432 hSpectrumDC = GetDC(hSpectrumControl);
433 GetClientRect(hSpectrumControl, &client);
434 ShowColorSpectrum(hSpectrumDC, &client, dmNewBitsPerPel, pGlobalData);
435
436 /* find if new parameters are valid */
437 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
438 if (dmNewBitsPerPel == Current->dmBitsPerPel)
439 {
440 /* no change */
441 return;
442 }
443
444 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
445
446 if (dmNewBitsPerPel < Current->dmBitsPerPel)
447 {
448 Current = Current->Blink;
449 while (Current != NULL)
450 {
451 if (Current->dmBitsPerPel == dmNewBitsPerPel
452 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
453 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
454 {
455 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
456 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
457 return;
458 }
459 Current = Current->Blink;
460 }
461 }
462 else
463 {
464 Current = Current->Flink;
465 while (Current != NULL)
466 {
467 if (Current->dmBitsPerPel == dmNewBitsPerPel
468 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
469 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
470 {
471 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
472 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
473 return;
474 }
475 Current = Current->Flink;
476 }
477 }
478
479 /* search smaller resolution compatible with current color depth */
480 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
481 while (Current != NULL)
482 {
483 if (Current->dmBitsPerPel == dmNewBitsPerPel)
484 {
485 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
486 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
487 return;
488 }
489 Current = Current->Blink;
490 }
491
492 /* search bigger resolution compatible with current color depth */
493 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
494 while (Current != NULL)
495 {
496 if (Current->dmBitsPerPel == dmNewBitsPerPel)
497 {
498 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
499 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
500 return;
501 }
502 Current = Current->Flink;
503 }
504
505 /* we shouldn't go there */
506 }
507
508 static VOID
509 OnResolutionChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN DWORD NewPosition,
510 IN BOOL bUpdateThumb)
511 {
512 /* if new resolution is not compatible with color depth:
513 * 1) try to find the nearest bigger matching color depth
514 * 2) otherwise, get the nearest smaller color depth
515 */
516 PSETTINGS_ENTRY Current;
517 DWORD dmNewPelsHeight = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
518 DWORD dmNewPelsWidth = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
519
520 /* find if new parameters are valid */
521 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
522 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
523 {
524 /* no change */
525 return;
526 }
527
528 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
529
530 if (dmNewPelsHeight < Current->dmPelsHeight)
531 {
532 Current = Current->Blink;
533 while (Current != NULL)
534 {
535 if (Current->dmPelsHeight == dmNewPelsHeight
536 && Current->dmPelsWidth == dmNewPelsWidth
537 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
538 {
539 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
540 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
541 return;
542 }
543 Current = Current->Blink;
544 }
545 }
546 else
547 {
548 Current = Current->Flink;
549 while (Current != NULL)
550 {
551 if (Current->dmPelsHeight == dmNewPelsHeight
552 && Current->dmPelsWidth == dmNewPelsWidth
553 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
554 {
555 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
556 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
557 return;
558 }
559 Current = Current->Flink;
560 }
561 }
562
563 /* search bigger color depth compatible with current resolution */
564 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
565 while (Current != NULL)
566 {
567 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
568 {
569 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
570 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
571 return;
572 }
573 Current = Current->Flink;
574 }
575
576 /* search smaller color depth compatible with current resolution */
577 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
578 while (Current != NULL)
579 {
580 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
581 {
582 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
583 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
584 return;
585 }
586 Current = Current->Blink;
587 }
588
589 /* we shouldn't go there */
590 }
591
592 /* Property sheet page callback */
593 UINT CALLBACK
594 SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
595 {
596 UINT Ret = 0;
597
598 switch (uMsg)
599 {
600 case PSPCB_CREATE:
601 Ret = RegisterMonitorSelectionControl(hApplet);
602 break;
603
604 case PSPCB_RELEASE:
605 UnregisterMonitorSelectionControl(hApplet);
606 break;
607 }
608
609 return Ret;
610 }
611
612 /* Property page dialog callback */
613 INT_PTR CALLBACK
614 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
615 {
616 PGLOBAL_DATA pGlobalData;
617
618 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
619
620 switch(uMsg)
621 {
622 case WM_INITDIALOG:
623 {
624 OnInitDialog(hwndDlg);
625 break;
626 }
627 case WM_DRAWITEM:
628 {
629 LPDRAWITEMSTRUCT lpDrawItem;
630 lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
631
632 if (lpDrawItem->CtlID == IDC_SETTINGS_SPECTRUM)
633 ShowColorSpectrum(lpDrawItem->hDC, &lpDrawItem->rcItem, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel, pGlobalData);
634
635 break;
636 }
637 case WM_COMMAND:
638 {
639 DWORD controlId = LOWORD(wParam);
640 DWORD command = HIWORD(wParam);
641
642 if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
643 DisplayAdvancedSettings(hwndDlg, pGlobalData->CurrentDisplayDevice);
644 else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
645 OnBPPChanged(hwndDlg, pGlobalData);
646 break;
647 }
648 case WM_HSCROLL:
649 {
650 switch (LOWORD(wParam))
651 {
652 case TB_LINEUP:
653 case TB_LINEDOWN:
654 case TB_PAGEUP:
655 case TB_PAGEDOWN:
656 case TB_TOP:
657 case TB_BOTTOM:
658 case TB_ENDTRACK:
659 {
660 DWORD newPosition = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
661 OnResolutionChanged(hwndDlg, pGlobalData, newPosition, TRUE);
662 break;
663 }
664
665 case TB_THUMBTRACK:
666 OnResolutionChanged(hwndDlg, pGlobalData, HIWORD(wParam), FALSE);
667 break;
668 }
669 break;
670 }
671 case WM_NOTIFY:
672 {
673 LPNMHDR lpnm = (LPNMHDR)lParam;
674 if (lpnm->code == (UINT)PSN_APPLY)
675 {
676 if (pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth
677 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight
678 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
679 {
680 /* FIXME: Need to test changes */
681 /* Apply new settings */
682 LONG rc;
683 DEVMODE devmode;
684 RtlZeroMemory(&devmode, sizeof(DEVMODE));
685 devmode.dmSize = (WORD)sizeof(DEVMODE);
686 devmode.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
687 devmode.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
688 devmode.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
689 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
690 rc = ChangeDisplaySettingsEx(
691 pGlobalData->CurrentDisplayDevice->DeviceName,
692 &devmode,
693 NULL,
694 CDS_UPDATEREGISTRY,
695 NULL);
696 switch (rc)
697 {
698 case DISP_CHANGE_SUCCESSFUL:
699 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
700 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
701 pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
702 break;
703 case DISP_CHANGE_FAILED:
704 MessageBox(NULL, TEXT("Failed to apply new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
705 break;
706 case DISP_CHANGE_RESTART:
707 MessageBox(NULL, TEXT("You need to restart your computer to apply changes."), TEXT("Display settings"), MB_OK | MB_ICONINFORMATION);
708 break;
709 default:
710 MessageBox(NULL, TEXT("Unknown error when applying new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
711 break;
712 }
713 }
714 }
715 break;
716 }
717
718 case WM_CONTEXTMENU:
719 {
720 HWND hwndMonSel;
721 HMENU hPopup;
722 UINT uiCmd;
723 POINT pt, ptClient;
724 INT Index;
725
726 pt.x = (SHORT)LOWORD(lParam);
727 pt.y = (SHORT)HIWORD(lParam);
728
729 hwndMonSel = GetDlgItem(hwndDlg,
730 IDC_SETTINGS_MONSEL);
731 if ((HWND)wParam == hwndMonSel)
732 {
733 if (pt.x == -1 && pt.y == -1)
734 {
735 RECT rcMon;
736
737 Index = (INT)SendMessage(hwndMonSel,
738 MSLM_GETCURSEL,
739 0,
740 0);
741
742 if (Index >= 0 &&
743 (INT)SendMessage(hwndMonSel,
744 MSLM_GETMONITORRECT,
745 Index,
746 (LPARAM)&rcMon) > 0)
747 {
748 pt.x = rcMon.left + ((rcMon.right - rcMon.left) / 2);
749 pt.y = rcMon.top + ((rcMon.bottom - rcMon.top) / 2);
750 }
751 else
752 pt.x = pt.y = 0;
753
754 MapWindowPoints(hwndMonSel,
755 NULL,
756 &pt,
757 1);
758 }
759 else
760 {
761 ptClient = pt;
762 MapWindowPoints(NULL,
763 hwndMonSel,
764 &ptClient,
765 1);
766
767 Index = (INT)SendMessage(hwndMonSel,
768 MSLM_HITTEST,
769 (WPARAM)&ptClient,
770 0);
771 }
772
773 if (Index >= 0)
774 {
775 hPopup = LoadPopupMenu(hApplet,
776 MAKEINTRESOURCE(IDM_MONITOR_MENU));
777 if (hPopup != NULL)
778 {
779 /* FIXME: Enable/Disable menu items */
780 EnableMenuItem(hPopup,
781 ID_MENU_ATTACHED,
782 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
783 EnableMenuItem(hPopup,
784 ID_MENU_PRIMARY,
785 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
786 EnableMenuItem(hPopup,
787 ID_MENU_IDENTIFY,
788 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
789 EnableMenuItem(hPopup,
790 ID_MENU_PROPERTIES,
791 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
792
793 uiCmd = (UINT)TrackPopupMenu(hPopup,
794 TPM_RETURNCMD | TPM_RIGHTBUTTON,
795 pt.x,
796 pt.y,
797 0,
798 hwndDlg,
799 NULL);
800
801 switch (uiCmd)
802 {
803 case ID_MENU_ATTACHED:
804 case ID_MENU_PRIMARY:
805 case ID_MENU_IDENTIFY:
806 case ID_MENU_PROPERTIES:
807 /* FIXME: Implement */
808 break;
809 }
810
811 DestroyMenu(hPopup);
812 }
813 }
814 }
815 break;
816 }
817
818 case WM_DESTROY:
819 {
820 INT i;
821 PDISPLAY_DEVICE_ENTRY Current = pGlobalData->DisplayDeviceList;
822
823 while (Current != NULL)
824 {
825 PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
826 PSETTINGS_ENTRY CurrentSettings = Current->Settings;
827 while (CurrentSettings != NULL)
828 {
829 PSETTINGS_ENTRY NextSettings = CurrentSettings->Flink;
830 HeapFree(GetProcessHeap(), 0, CurrentSettings);
831 CurrentSettings = NextSettings;
832 }
833 HeapFree(GetProcessHeap(), 0, Current);
834 Current = Next;
835 }
836
837 HeapFree(GetProcessHeap(), 0, pGlobalData);
838
839 for (i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
840 {
841 if (pGlobalData->hSpectrumBitmaps[i])
842 DeleteObject(pGlobalData->hSpectrumBitmaps[i]);
843 }
844 }
845 }
846 return FALSE;
847 }