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