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