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