Sync with trunk head
[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 #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 Current->dmDisplayFrequency = devmode.dmDisplayFrequency;
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(), HEAP_ZERO_MEMORY, 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 DWORD i;
287 DISPLAY_DEVICE displayDevice;
288 PGLOBAL_DATA pGlobalData;
289
290 pGlobalData = HeapAlloc(GetProcessHeap(), 0, 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 pGlobalData->DisplayDeviceList = NULL;
298 displayDevice.cb = (DWORD)sizeof(DISPLAY_DEVICE);
299 while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0x1))
300 {
301 if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0)
302 {
303 if (AddDisplayDevice(pGlobalData, &displayDevice))
304 Result++;
305 }
306 iDevNum++;
307 }
308
309 if (Result == 0)
310 {
311 /* No adapter found */
312 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_BPP), FALSE);
313 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION), FALSE);
314 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT), FALSE);
315 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_ADVANCED), FALSE);
316 ShowWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_SPECTRUM), SW_HIDE);
317
318 /* Do not initialize the color spectrum bitmaps */
319 memset(pGlobalData->hSpectrumBitmaps, 0, sizeof(pGlobalData->hSpectrumBitmaps));
320 return;
321 }
322 else if (Result == 1)
323 {
324 MONSL_MONINFO monitors;
325
326 /* Single video adapter */
327 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
328 OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
329
330 monitors.Position.x = monitors.Position.y = 0;
331 monitors.Size.cx = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
332 monitors.Size.cy = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
333 monitors.Flags = 0;
334 SendDlgItemMessage(hwndDlg,
335 IDC_SETTINGS_MONSEL,
336 MSLM_SETMONITORSINFO,
337 1,
338 (LPARAM)&monitors);
339 }
340 else /* FIXME: incomplete! */
341 {
342 PMONSL_MONINFO pMonitors;
343 DWORD i;
344
345 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
346 OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
347
348 pMonitors = (PMONSL_MONINFO)HeapAlloc(GetProcessHeap(), 0, sizeof(MONSL_MONINFO) * Result);
349 if (pMonitors)
350 {
351 DWORD hack = 1280;
352 for (i = 0; i < Result; i++)
353 {
354 pMonitors[i].Position.x = hack * i;
355 pMonitors[i].Position.y = 0;
356 pMonitors[i].Size.cx = pGlobalData->DisplayDeviceList->CurrentSettings->dmPelsWidth;
357 pMonitors[i].Size.cy = pGlobalData->DisplayDeviceList->CurrentSettings->dmPelsHeight;
358 pMonitors[i].Flags = 0;
359 }
360
361 SendDlgItemMessage(hwndDlg,
362 IDC_SETTINGS_MONSEL,
363 MSLM_SETMONITORSINFO,
364 Result,
365 (LPARAM)pMonitors);
366
367 HeapFree(GetProcessHeap(), 0, pMonitors);
368 }
369 }
370
371 /* Initialize the color spectrum bitmaps */
372 for(i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
373 {
374 pGlobalData->hSpectrumBitmaps[i] = LoadImageW(hApplet, MAKEINTRESOURCEW(IDB_SPECTRUM_4 + i), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
375
376 if (pGlobalData->hSpectrumBitmaps[i] != NULL)
377 {
378 if (GetObjectW(pGlobalData->hSpectrumBitmaps[i], sizeof(BITMAP), &bitmap) != 0)
379 {
380 pGlobalData->cxSource[i] = bitmap.bmWidth;
381 pGlobalData->cySource[i] = bitmap.bmHeight;
382 }
383 else
384 {
385 pGlobalData->cxSource[i] = 0;
386 pGlobalData->cySource[i] = 0;
387 }
388 }
389 }
390 }
391
392 /* Get the ID for GLOBAL_DATA::hSpectrumBitmaps */
393 static VOID
394 ShowColorSpectrum(IN HDC hDC, IN LPRECT client, IN DWORD BitsPerPel, IN PGLOBAL_DATA pGlobalData)
395 {
396 HDC hdcMem;
397 INT iBitmap;
398
399 hdcMem = CreateCompatibleDC(hDC);
400
401 if (!hdcMem)
402 return;
403
404 switch(BitsPerPel)
405 {
406 case 4: iBitmap = 0; break;
407 case 8: iBitmap = 1; break;
408 default: iBitmap = 2;
409 }
410
411 if (SelectObject(hdcMem, pGlobalData->hSpectrumBitmaps[iBitmap]))
412 {
413 StretchBlt(hDC,
414 client->left, client->top,
415 client->right - client->left,
416 client->bottom - client->top,
417 hdcMem, 0, 0,
418 pGlobalData->cxSource[iBitmap],
419 pGlobalData->cySource[iBitmap], SRCCOPY);
420 }
421
422 DeleteDC(hdcMem);
423 }
424
425 static VOID
426 OnBPPChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData)
427 {
428 /* if new BPP is not compatible with resolution:
429 * 1) try to find the nearest smaller matching resolution
430 * 2) otherwise, get the nearest bigger resolution
431 */
432 PSETTINGS_ENTRY Current;
433 DWORD dmNewBitsPerPel;
434 DWORD index;
435 HDC hSpectrumDC;
436 HWND hSpectrumControl;
437 RECT client;
438
439 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETCURSEL, 0, 0);
440 dmNewBitsPerPel = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
441
442 /* Show a new spectrum bitmap */
443 hSpectrumControl = GetDlgItem(hwndDlg, IDC_SETTINGS_SPECTRUM);
444 hSpectrumDC = GetDC(hSpectrumControl);
445 GetClientRect(hSpectrumControl, &client);
446 ShowColorSpectrum(hSpectrumDC, &client, dmNewBitsPerPel, pGlobalData);
447
448 /* find if new parameters are valid */
449 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
450 if (dmNewBitsPerPel == Current->dmBitsPerPel)
451 {
452 /* no change */
453 return;
454 }
455
456 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
457
458 if (dmNewBitsPerPel < Current->dmBitsPerPel)
459 {
460 Current = Current->Blink;
461 while (Current != NULL)
462 {
463 if (Current->dmBitsPerPel == dmNewBitsPerPel
464 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
465 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
466 {
467 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
468 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
469 return;
470 }
471 Current = Current->Blink;
472 }
473 }
474 else
475 {
476 Current = Current->Flink;
477 while (Current != NULL)
478 {
479 if (Current->dmBitsPerPel == dmNewBitsPerPel
480 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
481 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
482 {
483 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
484 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
485 return;
486 }
487 Current = Current->Flink;
488 }
489 }
490
491 /* search smaller resolution compatible with current color depth */
492 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
493 while (Current != NULL)
494 {
495 if (Current->dmBitsPerPel == dmNewBitsPerPel)
496 {
497 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
498 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
499 return;
500 }
501 Current = Current->Blink;
502 }
503
504 /* search bigger resolution compatible with current color depth */
505 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
506 while (Current != NULL)
507 {
508 if (Current->dmBitsPerPel == dmNewBitsPerPel)
509 {
510 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
511 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
512 return;
513 }
514 Current = Current->Flink;
515 }
516
517 /* we shouldn't go there */
518 }
519
520 static VOID
521 OnResolutionChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN DWORD NewPosition,
522 IN BOOL bUpdateThumb)
523 {
524 /* if new resolution is not compatible with color depth:
525 * 1) try to find the nearest bigger matching color depth
526 * 2) otherwise, get the nearest smaller color depth
527 */
528 PSETTINGS_ENTRY Current;
529 DWORD dmNewPelsHeight = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
530 DWORD dmNewPelsWidth = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
531
532 /* find if new parameters are valid */
533 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
534 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
535 {
536 /* no change */
537 return;
538 }
539
540 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
541
542 if (dmNewPelsHeight < Current->dmPelsHeight)
543 {
544 Current = Current->Blink;
545 while (Current != NULL)
546 {
547 if (Current->dmPelsHeight == dmNewPelsHeight
548 && Current->dmPelsWidth == dmNewPelsWidth
549 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
550 {
551 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
552 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
553 return;
554 }
555 Current = Current->Blink;
556 }
557 }
558 else
559 {
560 Current = Current->Flink;
561 while (Current != NULL)
562 {
563 if (Current->dmPelsHeight == dmNewPelsHeight
564 && Current->dmPelsWidth == dmNewPelsWidth
565 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
566 {
567 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
568 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
569 return;
570 }
571 Current = Current->Flink;
572 }
573 }
574
575 /* search bigger color depth compatible with current resolution */
576 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
577 while (Current != NULL)
578 {
579 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
580 {
581 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
582 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
583 return;
584 }
585 Current = Current->Flink;
586 }
587
588 /* search smaller color depth compatible with current resolution */
589 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
590 while (Current != NULL)
591 {
592 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
593 {
594 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
595 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
596 return;
597 }
598 Current = Current->Blink;
599 }
600
601 /* we shouldn't go there */
602 }
603
604 /* Property sheet page callback */
605 UINT CALLBACK
606 SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
607 {
608 UINT Ret = 0;
609
610 switch (uMsg)
611 {
612 case PSPCB_CREATE:
613 Ret = RegisterMonitorSelectionControl(hApplet);
614 break;
615
616 case PSPCB_RELEASE:
617 UnregisterMonitorSelectionControl(hApplet);
618 break;
619 }
620
621 return Ret;
622 }
623
624 /* Property page dialog callback */
625 INT_PTR CALLBACK
626 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
627 {
628 PGLOBAL_DATA pGlobalData;
629 TCHAR Message[1024], Title[256];
630
631 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
632
633 switch(uMsg)
634 {
635 case WM_INITDIALOG:
636 {
637 OnInitDialog(hwndDlg);
638 break;
639 }
640 case WM_DRAWITEM:
641 {
642 LPDRAWITEMSTRUCT lpDrawItem;
643 lpDrawItem = (LPDRAWITEMSTRUCT) lParam;
644
645 if (lpDrawItem->CtlID == IDC_SETTINGS_SPECTRUM)
646 ShowColorSpectrum(lpDrawItem->hDC, &lpDrawItem->rcItem, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel, pGlobalData);
647 break;
648 }
649 case WM_COMMAND:
650 {
651 DWORD controlId = LOWORD(wParam);
652 DWORD command = HIWORD(wParam);
653
654 if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
655 DisplayAdvancedSettings(hwndDlg, pGlobalData->CurrentDisplayDevice);
656 else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
657 OnBPPChanged(hwndDlg, pGlobalData);
658 break;
659 }
660 case WM_HSCROLL:
661 {
662 switch (LOWORD(wParam))
663 {
664 case TB_LINEUP:
665 case TB_LINEDOWN:
666 case TB_PAGEUP:
667 case TB_PAGEDOWN:
668 case TB_TOP:
669 case TB_BOTTOM:
670 case TB_ENDTRACK:
671 {
672 DWORD newPosition = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
673 OnResolutionChanged(hwndDlg, pGlobalData, newPosition, TRUE);
674 break;
675 }
676
677 case TB_THUMBTRACK:
678 OnResolutionChanged(hwndDlg, pGlobalData, HIWORD(wParam), FALSE);
679 break;
680 }
681 break;
682 }
683 case WM_NOTIFY:
684 {
685 LPNMHDR lpnm = (LPNMHDR)lParam;
686 if (lpnm->code == (UINT)PSN_APPLY)
687 {
688 if (pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth
689 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight
690 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
691 {
692 /* FIXME: Need to test changes */
693 /* Apply new settings */
694 LONG rc;
695 DEVMODE devmode;
696 RtlZeroMemory(&devmode, sizeof(DEVMODE));
697 devmode.dmSize = (WORD)sizeof(DEVMODE);
698 devmode.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
699 devmode.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
700 devmode.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
701 devmode.dmDisplayFrequency = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency;
702 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
703 rc = ChangeDisplaySettingsEx(
704 pGlobalData->CurrentDisplayDevice->DeviceName,
705 &devmode,
706 NULL,
707 CDS_UPDATEREGISTRY,
708 NULL);
709 switch (rc)
710 {
711 case DISP_CHANGE_SUCCESSFUL:
712 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
713 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
714 pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
715 break;
716 case DISP_CHANGE_RESTART:
717 LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
718 LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR));
719 MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION);
720 break;
721 case DISP_CHANGE_FAILED:
722 default:
723 LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
724 LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR));
725 MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP);
726 break;
727 }
728 }
729 }
730 break;
731 }
732
733 case WM_CONTEXTMENU:
734 {
735 HWND hwndMonSel;
736 HMENU hPopup;
737 UINT uiCmd;
738 POINT pt, ptClient;
739 INT Index;
740
741 pt.x = (SHORT)LOWORD(lParam);
742 pt.y = (SHORT)HIWORD(lParam);
743
744 hwndMonSel = GetDlgItem(hwndDlg,
745 IDC_SETTINGS_MONSEL);
746 if ((HWND)wParam == hwndMonSel)
747 {
748 if (pt.x == -1 && pt.y == -1)
749 {
750 RECT rcMon;
751
752 Index = (INT)SendMessage(hwndMonSel,
753 MSLM_GETCURSEL,
754 0,
755 0);
756
757 if (Index >= 0 &&
758 (INT)SendMessage(hwndMonSel,
759 MSLM_GETMONITORRECT,
760 Index,
761 (LPARAM)&rcMon) > 0)
762 {
763 pt.x = rcMon.left + ((rcMon.right - rcMon.left) / 2);
764 pt.y = rcMon.top + ((rcMon.bottom - rcMon.top) / 2);
765 }
766 else
767 pt.x = pt.y = 0;
768
769 MapWindowPoints(hwndMonSel,
770 NULL,
771 &pt,
772 1);
773 }
774 else
775 {
776 ptClient = pt;
777 MapWindowPoints(NULL,
778 hwndMonSel,
779 &ptClient,
780 1);
781
782 Index = (INT)SendMessage(hwndMonSel,
783 MSLM_HITTEST,
784 (WPARAM)&ptClient,
785 0);
786 }
787
788 if (Index >= 0)
789 {
790 hPopup = LoadPopupMenu(hApplet,
791 MAKEINTRESOURCE(IDM_MONITOR_MENU));
792 if (hPopup != NULL)
793 {
794 /* FIXME: Enable/Disable menu items */
795 EnableMenuItem(hPopup,
796 ID_MENU_ATTACHED,
797 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
798 EnableMenuItem(hPopup,
799 ID_MENU_PRIMARY,
800 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
801 EnableMenuItem(hPopup,
802 ID_MENU_IDENTIFY,
803 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
804 EnableMenuItem(hPopup,
805 ID_MENU_PROPERTIES,
806 MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
807
808 uiCmd = (UINT)TrackPopupMenu(hPopup,
809 TPM_RETURNCMD | TPM_RIGHTBUTTON,
810 pt.x,
811 pt.y,
812 0,
813 hwndDlg,
814 NULL);
815
816 switch (uiCmd)
817 {
818 case ID_MENU_ATTACHED:
819 case ID_MENU_PRIMARY:
820 case ID_MENU_IDENTIFY:
821 case ID_MENU_PROPERTIES:
822 /* FIXME: Implement */
823 break;
824 }
825
826 DestroyMenu(hPopup);
827 }
828 }
829 }
830 break;
831 }
832
833 case WM_DESTROY:
834 {
835 DWORD i;
836 PDISPLAY_DEVICE_ENTRY Current = pGlobalData->DisplayDeviceList;
837
838 while (Current != NULL)
839 {
840 PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
841 PSETTINGS_ENTRY CurrentSettings = Current->Settings;
842 while (CurrentSettings != NULL)
843 {
844 PSETTINGS_ENTRY NextSettings = CurrentSettings->Flink;
845 HeapFree(GetProcessHeap(), 0, CurrentSettings);
846 CurrentSettings = NextSettings;
847 }
848 HeapFree(GetProcessHeap(), 0, Current);
849 Current = Next;
850 }
851
852 for (i = 0; i < NUM_SPECTRUM_BITMAPS; i++)
853 {
854 if (pGlobalData->hSpectrumBitmaps[i])
855 DeleteObject(pGlobalData->hSpectrumBitmaps[i]);
856 }
857
858 HeapFree(GetProcessHeap(), 0, pGlobalData);
859 }
860 }
861 return FALSE;
862 }