Add a (not yet functional) control to allow the user to arrange the monitors
[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 hBitmap;
19 int cxSource;
20 int cySource;
21 } GLOBAL_DATA, *PGLOBAL_DATA;
22
23 static VOID
24 UpdateDisplay(IN HWND hwndDlg, PGLOBAL_DATA pGlobalData, 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, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight, Pixel);
32 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT, WM_SETTEXT, 0, (LPARAM)Buffer);
33
34 for (index = 0; index < pGlobalData->CurrentDisplayDevice->ResolutionsCount; index++)
35 {
36 if (pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth &&
37 pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsHeight == pGlobalData->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 + pGlobalData->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
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==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 while (Next != NULL && (
110 Next->dmPelsWidth < Current->dmPelsWidth ||
111 (Next->dmPelsWidth == Current->dmPelsWidth && Next->dmPelsHeight < Current->dmPelsHeight) ||
112 (Next->dmPelsHeight == Current->dmPelsHeight &&
113 Next->dmPelsWidth == Current->dmPelsWidth &&
114 Next->dmBitsPerPel < Current->dmBitsPerPel )))
115 {
116 Previous = Next;
117 Next = Next->Flink;
118 }
119 Current->Blink = Previous;
120 Current->Flink = Next;
121 if (Previous == NULL)
122 Settings = Current;
123 else
124 Previous->Flink = Current;
125 if (Next != NULL)
126 Next->Blink = Current;
127 if (devmode.dmPelsWidth == xres && devmode.dmPelsHeight == yres && devmode.dmBitsPerPel == bpp)
128 {
129 *CurrentSettings = Current;
130 }
131 NbSettings++;
132 }
133 iMode++;
134 }
135
136 *pSettingsCount = NbSettings;
137 return Settings;
138 }
139
140 static BOOL
141 AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN const DISPLAY_DEVICE *DisplayDevice)
142 {
143 PDISPLAY_DEVICE_ENTRY newEntry = NULL;
144 LPTSTR description = NULL;
145 LPTSTR name = NULL;
146 LPTSTR key = NULL;
147 LPTSTR devid = NULL;
148 DWORD descriptionSize, nameSize, keySize, devidSize;
149 PSETTINGS_ENTRY Current;
150 DWORD ResolutionsCount = 1;
151 DWORD i;
152
153 newEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(DISPLAY_DEVICE_ENTRY));
154 memset(newEntry, 0, 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 = pGlobalData->DisplayDeviceList;
219 pGlobalData->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 if (devid != NULL)
246 HeapFree(GetProcessHeap(), 0, devid);
247 return FALSE;
248 }
249
250 static VOID
251 OnDisplayDeviceChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
252 {
253 PSETTINGS_ENTRY Current;
254 DWORD index;
255
256 pGlobalData->CurrentDisplayDevice = pDeviceEntry; /* Update global variable */
257
258 /* Fill color depths combo box */
259 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_RESETCONTENT, 0, 0);
260 for (Current = pDeviceEntry->Settings; Current != NULL; Current = Current->Flink)
261 {
262 TCHAR Buffer[64];
263 if (LoadString(hApplet, (2900 + Current->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
264 {
265 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
266 if (index == (DWORD)CB_ERR)
267 {
268 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_ADDSTRING, 0, (LPARAM)Buffer);
269 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SETITEMDATA, index, Current->dmBitsPerPel);
270 }
271 }
272 }
273
274 /* Fill resolutions slider */
275 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_CLEARTICS, TRUE, 0);
276 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETRANGE, TRUE, MAKELONG(0, pDeviceEntry->ResolutionsCount - 1));
277
278 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
279 }
280
281 static VOID
282 OnInitDialog(IN HWND hwndDlg)
283 {
284 DWORD Result = 0;
285 DWORD iDevNum = 0;
286 DISPLAY_DEVICE displayDevice;
287 BITMAP bitmap;
288 PGLOBAL_DATA pGlobalData;
289
290 pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 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 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(pGlobalData, &displayDevice))
303 Result++;
304 }
305 iDevNum++;
306 }
307 if (Result == 0)
308 {
309 /* No adapter found */
310 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_BPP), FALSE);
311 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION), FALSE);
312 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT), FALSE);
313 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_ADVANCED), FALSE);
314 }
315 else if (Result == 1)
316 {
317 /* Single video adapter */
318 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
319 OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
320 }
321 else
322 {
323 /* FIXME: multi video adapter */
324 /* FIXME: choose selected adapter being the primary one */
325 }
326
327 pGlobalData->hBitmap = LoadImage(hApplet, MAKEINTRESOURCE(IDC_MONITOR), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
328 if (pGlobalData->hBitmap != NULL)
329 {
330 GetObject(pGlobalData->hBitmap, sizeof(BITMAP), &bitmap);
331
332 pGlobalData->cxSource = bitmap.bmWidth;
333 pGlobalData->cySource = bitmap.bmHeight;
334 }
335 }
336
337 static VOID
338 OnBPPChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData)
339 {
340 /* if new BPP is not compatible with resolution:
341 * 1) try to find the nearest smaller matching resolution
342 * 2) otherwise, get the nearest bigger resolution
343 */
344 PSETTINGS_ENTRY Current;
345 DWORD dmNewBitsPerPel;
346 DWORD index;
347 TCHAR Buffer[64];
348
349 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, WM_GETTEXT, (WPARAM)(sizeof(Buffer) / sizeof(TCHAR)), (LPARAM)Buffer);
350 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
351 dmNewBitsPerPel = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
352
353 /* find if new parameters are valid */
354 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
355 if (dmNewBitsPerPel == Current->dmBitsPerPel)
356 {
357 /* no change */
358 return;
359 }
360
361 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
362
363 if (dmNewBitsPerPel < Current->dmBitsPerPel)
364 {
365 Current = Current->Blink;
366 while (Current != NULL)
367 {
368 if (Current->dmBitsPerPel == dmNewBitsPerPel
369 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
370 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
371 {
372 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
373 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
374 return;
375 }
376 Current = Current->Blink;
377 }
378 }
379 else
380 {
381 Current = Current->Flink;
382 while (Current != NULL)
383 {
384 if (Current->dmBitsPerPel == dmNewBitsPerPel
385 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
386 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
387 {
388 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
389 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
390 return;
391 }
392 Current = Current->Flink;
393 }
394 }
395
396 /* search smaller resolution compatible with current color depth */
397 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
398 while (Current != NULL)
399 {
400 if (Current->dmBitsPerPel == dmNewBitsPerPel)
401 {
402 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
403 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
404 return;
405 }
406 Current = Current->Blink;
407 }
408
409 /* search bigger resolution compatible with current color depth */
410 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
411 while (Current != NULL)
412 {
413 if (Current->dmBitsPerPel == dmNewBitsPerPel)
414 {
415 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
416 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
417 return;
418 }
419 Current = Current->Flink;
420 }
421
422 /* we shouldn't go there */
423 }
424
425 static VOID
426 OnResolutionChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN DWORD NewPosition,
427 IN BOOL bUpdateThumb)
428 {
429 /* if new resolution is not compatible with color depth:
430 * 1) try to find the nearest bigger matching color depth
431 * 2) otherwise, get the nearest smaller color depth
432 */
433 PSETTINGS_ENTRY Current;
434 DWORD dmNewPelsHeight = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
435 DWORD dmNewPelsWidth = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
436
437 /* find if new parameters are valid */
438 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
439 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
440 {
441 /* no change */
442 return;
443 }
444
445 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
446
447 if (dmNewPelsHeight < Current->dmPelsHeight)
448 {
449 Current = Current->Blink;
450 while (Current != NULL)
451 {
452 if (Current->dmPelsHeight == dmNewPelsHeight
453 && Current->dmPelsWidth == dmNewPelsWidth
454 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
455 {
456 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
457 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
458 return;
459 }
460 Current = Current->Blink;
461 }
462 }
463 else
464 {
465 Current = Current->Flink;
466 while (Current != NULL)
467 {
468 if (Current->dmPelsHeight == dmNewPelsHeight
469 && Current->dmPelsWidth == dmNewPelsWidth
470 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
471 {
472 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
473 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
474 return;
475 }
476 Current = Current->Flink;
477 }
478 }
479
480 /* search bigger color depth compatible with current resolution */
481 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
482 while (Current != NULL)
483 {
484 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
485 {
486 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
487 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
488 return;
489 }
490 Current = Current->Flink;
491 }
492
493 /* search smaller color depth compatible with current resolution */
494 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
495 while (Current != NULL)
496 {
497 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
498 {
499 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
500 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
501 return;
502 }
503 Current = Current->Blink;
504 }
505
506 /* we shouldn't go there */
507 }
508
509 /* Property sheet page callback */
510 UINT CALLBACK
511 SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
512 {
513 UINT Ret = 0;
514
515 switch (uMsg)
516 {
517 case PSPCB_CREATE:
518 Ret = RegisterMonitorSelectionControl(hApplet);
519 break;
520
521 case PSPCB_RELEASE:
522 UnregisterMonitorSelectionControl(hApplet);
523 break;
524 }
525
526 return Ret;
527 }
528
529 /* Property page dialog callback */
530 INT_PTR CALLBACK
531 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
532 {
533 PGLOBAL_DATA pGlobalData;
534
535 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
536
537 switch(uMsg)
538 {
539 case WM_INITDIALOG:
540 OnInitDialog(hwndDlg);
541 break;
542 case WM_COMMAND:
543 {
544 DWORD controlId = LOWORD(wParam);
545 DWORD command = HIWORD(wParam);
546
547 if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
548 DisplayAdvancedSettings(hwndDlg, pGlobalData->CurrentDisplayDevice);
549 else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
550 OnBPPChanged(hwndDlg, pGlobalData);
551 break;
552 }
553 case WM_HSCROLL:
554 {
555 switch (LOWORD(wParam))
556 {
557 case TB_LINEUP:
558 case TB_LINEDOWN:
559 case TB_PAGEUP:
560 case TB_PAGEDOWN:
561 case TB_TOP:
562 case TB_BOTTOM:
563 case TB_ENDTRACK:
564 {
565 DWORD newPosition = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
566 OnResolutionChanged(hwndDlg, pGlobalData, newPosition, TRUE);
567 break;
568 }
569
570 case TB_THUMBTRACK:
571 OnResolutionChanged(hwndDlg, pGlobalData, HIWORD(wParam), FALSE);
572 break;
573 }
574 break;
575 }
576 case WM_NOTIFY:
577 {
578 LPNMHDR lpnm = (LPNMHDR)lParam;
579 if (lpnm->code == (UINT)PSN_APPLY)
580 {
581 if (pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth
582 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight
583 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
584 {
585 /* FIXME: Need to test changes */
586 /* Apply new settings */
587 LONG rc;
588 DEVMODE devmode;
589 RtlZeroMemory(&devmode, sizeof(DEVMODE));
590 devmode.dmSize = (WORD)sizeof(DEVMODE);
591 devmode.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
592 devmode.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
593 devmode.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
594 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
595 rc = ChangeDisplaySettingsEx(
596 pGlobalData->CurrentDisplayDevice->DeviceName,
597 &devmode,
598 NULL,
599 CDS_UPDATEREGISTRY,
600 NULL);
601 switch (rc)
602 {
603 case DISP_CHANGE_SUCCESSFUL:
604 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
605 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
606 pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
607 break;
608 case DISP_CHANGE_FAILED:
609 MessageBox(NULL, TEXT("Failed to apply new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
610 break;
611 case DISP_CHANGE_RESTART:
612 MessageBox(NULL, TEXT("You need to restart your computer to apply changes."), TEXT("Display settings"), MB_OK | MB_ICONINFORMATION);
613 break;
614 default:
615 MessageBox(NULL, TEXT("Unknown error when applying new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
616 break;
617 }
618 }
619 }
620 break;
621 }
622
623 case WM_PAINT:
624 {
625 PAINTSTRUCT ps;
626 HDC hdc, hdcMem;
627
628 hdc = BeginPaint(hwndDlg, &ps);
629
630 hdcMem = CreateCompatibleDC(hdc);
631 SelectObject(hdcMem, pGlobalData->hBitmap);
632 /*
633 TransparentBlt(hdc, 98, 0,
634 pGlobalData->cxSource,
635 pGlobalData->cySource, hdcMem, 0, 0,
636 pGlobalData->cxSource,
637 pGlobalData->cySource, 0xFF80FF);
638 */
639 DeleteDC(hdcMem);
640 EndPaint(hwndDlg, &ps);
641
642 break;
643 }
644
645 case WM_DESTROY:
646 {
647 PDISPLAY_DEVICE_ENTRY Current = pGlobalData->DisplayDeviceList;
648 while (Current != NULL)
649 {
650 PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
651 PSETTINGS_ENTRY CurrentSettings = Current->Settings;
652 while (CurrentSettings != NULL)
653 {
654 PSETTINGS_ENTRY NextSettings = CurrentSettings->Flink;
655 HeapFree(GetProcessHeap(), 0, CurrentSettings);
656 CurrentSettings = NextSettings;
657 }
658 HeapFree(GetProcessHeap(), 0, Current);
659 Current = Next;
660 }
661
662 DeleteObject(pGlobalData->hBitmap);
663
664 HeapFree(GetProcessHeap(), 0, pGlobalData);
665 }
666 }
667 return FALSE;
668 }