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