Update the display resolution text while the slider is being moved.
[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
13 /* As slider control can't contain user data, we have to keep an
14 * array of RESOLUTION_INFO to have our own associated data.
15 */
16 typedef struct _RESOLUTION_INFO
17 {
18 DWORD dmPelsWidth;
19 DWORD dmPelsHeight;
20 } RESOLUTION_INFO, *PRESOLUTION_INFO;
21
22 typedef struct _SETTINGS_ENTRY
23 {
24 struct _SETTINGS_ENTRY *Blink;
25 struct _SETTINGS_ENTRY *Flink;
26 DWORD dmBitsPerPel;
27 DWORD dmPelsWidth;
28 DWORD dmPelsHeight;
29 } SETTINGS_ENTRY, *PSETTINGS_ENTRY;
30
31 typedef struct _DISPLAY_DEVICE_ENTRY
32 {
33 struct _DISPLAY_DEVICE_ENTRY *Flink;
34 LPTSTR DeviceDescription;
35 LPTSTR DeviceName;
36 PSETTINGS_ENTRY Settings; /* sorted by increasing dmPelsHeight, BPP */
37 DWORD SettingsCount;
38 PRESOLUTION_INFO Resolutions;
39 DWORD ResolutionsCount;
40 PSETTINGS_ENTRY CurrentSettings; /* Points into Settings list */
41 SETTINGS_ENTRY InitialSettings;
42 } DISPLAY_DEVICE_ENTRY, *PDISPLAY_DEVICE_ENTRY;
43
44 typedef struct _GLOBAL_DATA
45 {
46 PDISPLAY_DEVICE_ENTRY DisplayDeviceList;
47 PDISPLAY_DEVICE_ENTRY CurrentDisplayDevice;
48 HBITMAP hBitmap;
49 int cxSource;
50 int cySource;
51 } GLOBAL_DATA, *PGLOBAL_DATA;
52
53 static VOID
54 UpdateDisplay(IN HWND hwndDlg, PGLOBAL_DATA pGlobalData, IN BOOL bUpdateThumb)
55 {
56 TCHAR Buffer[64];
57 TCHAR Pixel[64];
58 DWORD index;
59
60 LoadString(hApplet, IDS_PIXEL, Pixel, sizeof(Pixel) / sizeof(TCHAR));
61 _stprintf(Buffer, Pixel, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth, pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight, Pixel);
62 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT, WM_SETTEXT, 0, (LPARAM)Buffer);
63
64 for (index = 0; index < pGlobalData->CurrentDisplayDevice->ResolutionsCount; index++)
65 {
66
67 if (pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth &&
68 pGlobalData->CurrentDisplayDevice->Resolutions[index].dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight)
69 {
70 if (bUpdateThumb)
71 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETPOS, TRUE, index);
72 break;
73 }
74 }
75 if (LoadString(hApplet, (2900 + pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
76 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)Buffer);
77 }
78
79 static PSETTINGS_ENTRY
80 GetPossibleSettings(IN LPTSTR DeviceName, OUT DWORD* pSettingsCount, OUT PSETTINGS_ENTRY* CurrentSettings)
81 {
82 DEVMODE devmode;
83 DWORD NbSettings = 0;
84 DWORD iMode = 0;
85 DWORD dwFlags = 0;
86 PSETTINGS_ENTRY Settings = NULL;
87 HDC hDC;
88 PSETTINGS_ENTRY Current;
89 DWORD bpp, xres, yres, checkbpp;
90
91 /* Get current settings */
92 *CurrentSettings = NULL;
93 hDC = CreateIC(NULL, DeviceName, NULL, NULL);
94 bpp = GetDeviceCaps(hDC, PLANES);
95 bpp *= GetDeviceCaps(hDC, BITSPIXEL);
96 xres = GetDeviceCaps(hDC, HORZRES);
97 yres = GetDeviceCaps(hDC, VERTRES);
98 DeleteDC(hDC);
99
100 /* List all settings */
101 devmode.dmSize = (WORD)sizeof(DEVMODE);
102 devmode.dmDriverExtra = 0;
103 while (EnumDisplaySettingsEx(DeviceName, iMode, &devmode, dwFlags))
104 {
105 if (devmode.dmBitsPerPel==8 || devmode.dmBitsPerPel==16 || devmode.dmBitsPerPel==24 || devmode.dmBitsPerPel==32) checkbpp=1;
106 else checkbpp=0;
107
108 if (devmode.dmPelsWidth < 640 ||
109 devmode.dmPelsHeight < 480 || checkbpp == 0)
110 {
111 iMode++;
112 continue;
113 }
114
115 Current = HeapAlloc(GetProcessHeap(), 0, sizeof(SETTINGS_ENTRY));
116 if (Current != NULL)
117 {
118 /* Sort resolutions by increasing height, and BPP */
119 PSETTINGS_ENTRY Previous = NULL;
120 PSETTINGS_ENTRY Next = Settings;
121 Current->dmPelsWidth = devmode.dmPelsWidth;
122 Current->dmPelsHeight = devmode.dmPelsHeight;
123 Current->dmBitsPerPel = devmode.dmBitsPerPel;
124 while (Next != NULL && (
125 Next->dmPelsHeight < Current->dmPelsHeight ||
126 (Next->dmPelsHeight == Current->dmPelsHeight && Next->dmBitsPerPel < Current->dmBitsPerPel) ||
127 (Next->dmPelsHeight == Current->dmPelsHeight &&
128 Next->dmBitsPerPel == Current->dmBitsPerPel &&
129 Next->dmPelsWidth < Current->dmPelsWidth)))
130 {
131 Previous = Next;
132 Next = Next->Flink;
133 }
134 Current->Blink = Previous;
135 Current->Flink = Next;
136 if (Previous == NULL)
137 Settings = Current;
138 else
139 Previous->Flink = Current;
140 if (Next != NULL)
141 Next->Blink = Current;
142 if (devmode.dmPelsWidth == xres && devmode.dmPelsHeight == yres && devmode.dmBitsPerPel == bpp)
143 {
144 *CurrentSettings = Current;
145 }
146 NbSettings++;
147 }
148 iMode++;
149 }
150
151 *pSettingsCount = NbSettings;
152 return Settings;
153 }
154
155 static BOOL
156 AddDisplayDevice(IN PGLOBAL_DATA pGlobalData, IN LPTSTR Description, IN LPTSTR DeviceName)
157 {
158 PDISPLAY_DEVICE_ENTRY newEntry = NULL;
159 LPTSTR description = NULL;
160 LPTSTR name = NULL;
161 DWORD descriptionSize;
162 DWORD nameSize;
163 PSETTINGS_ENTRY Current;
164 DWORD ResolutionsCount = 1;
165 DWORD i;
166
167 newEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(DISPLAY_DEVICE_ENTRY));
168 memset(newEntry, 0, sizeof(DISPLAY_DEVICE_ENTRY));
169 if (!newEntry) goto ByeBye;
170
171 newEntry->Settings = GetPossibleSettings(DeviceName, &newEntry->SettingsCount, &newEntry->CurrentSettings);
172 if (!newEntry->Settings) goto ByeBye;
173
174 newEntry->InitialSettings.dmPelsWidth = newEntry->CurrentSettings->dmPelsWidth;
175 newEntry->InitialSettings.dmPelsHeight = newEntry->CurrentSettings->dmPelsHeight;
176 newEntry->InitialSettings.dmBitsPerPel = newEntry->CurrentSettings->dmBitsPerPel;
177
178 /* Count different resolutions */
179 for (Current = newEntry->Settings; Current != NULL; Current = Current->Flink)
180 if (Current->Flink != NULL &&
181 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) || (Current->dmPelsHeight != Current->Flink->dmPelsHeight)))
182 ResolutionsCount++;
183 newEntry->Resolutions = HeapAlloc(GetProcessHeap(), 0, ResolutionsCount * sizeof(RESOLUTION_INFO));
184 if (!newEntry->Resolutions) goto ByeBye;
185 newEntry->ResolutionsCount = ResolutionsCount;
186 /* Fill resolutions infos */
187 for (Current = newEntry->Settings, i = 0; Current != NULL; Current = Current->Flink)
188 if (Current->Flink == NULL || (Current->Flink != NULL &&
189 ((Current->dmPelsWidth != Current->Flink->dmPelsWidth) || (Current->dmPelsHeight != Current->Flink->dmPelsHeight))))
190 {
191 newEntry->Resolutions[i].dmPelsWidth = Current->dmPelsWidth;
192 newEntry->Resolutions[i].dmPelsHeight = Current->dmPelsHeight;
193 i++;
194 }
195
196 descriptionSize = (_tcslen(Description) + 1) * sizeof(TCHAR);
197 description = HeapAlloc(GetProcessHeap(), 0, descriptionSize);
198 if (!description) goto ByeBye;
199
200 nameSize = (_tcslen(DeviceName) + 1) * sizeof(TCHAR);
201 name = HeapAlloc(GetProcessHeap(), 0, nameSize);
202 if (!name) goto ByeBye;
203
204 memcpy(description, Description, descriptionSize);
205 memcpy(name, DeviceName, nameSize);
206 newEntry->DeviceDescription = description;
207 newEntry->DeviceName = name;
208 newEntry->Flink = pGlobalData->DisplayDeviceList;
209 pGlobalData->DisplayDeviceList = newEntry;
210 return TRUE;
211
212 ByeBye:
213 if (newEntry != NULL)
214 {
215 if (newEntry->Settings != NULL)
216 {
217 Current = newEntry->Settings;
218 while (Current != NULL)
219 {
220 PSETTINGS_ENTRY Next = Current->Flink;
221 HeapFree(GetProcessHeap(), 0, Current);
222 Current = Next;
223 }
224 }
225 if (newEntry->Resolutions != NULL)
226 HeapFree(GetProcessHeap(), 0, newEntry->Resolutions);
227 HeapFree(GetProcessHeap(), 0, newEntry);
228 }
229 if (description != NULL)
230 HeapFree(GetProcessHeap(), 0, description);
231 if (name != NULL)
232 HeapFree(GetProcessHeap(), 0, name);
233 return FALSE;
234 }
235
236 static VOID
237 OnDisplayDeviceChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN PDISPLAY_DEVICE_ENTRY pDeviceEntry)
238 {
239 PSETTINGS_ENTRY Current;
240 DWORD index;
241
242 pGlobalData->CurrentDisplayDevice = pDeviceEntry; /* Update global variable */
243
244 /* Fill color depths combo box */
245 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_RESETCONTENT, 0, 0);
246 for (Current = pDeviceEntry->Settings; Current != NULL; Current = Current->Flink)
247 {
248 TCHAR Buffer[64];
249 if (LoadString(hApplet, (2900 + Current->dmBitsPerPel), Buffer, sizeof(Buffer) / sizeof(TCHAR)))
250 {
251 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
252 if (index == (DWORD)CB_ERR)
253 {
254 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_ADDSTRING, 0, (LPARAM)Buffer);
255 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_SETITEMDATA, index, Current->dmBitsPerPel);
256 }
257 }
258 }
259
260 /* Fill resolutions slider */
261 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_CLEARTICS, TRUE, 0);
262 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_SETRANGE, TRUE, MAKELONG(0, pDeviceEntry->ResolutionsCount - 1));
263
264 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
265 }
266
267 static VOID
268 OnInitDialog(IN HWND hwndDlg)
269 {
270 DWORD Result = 0;
271 DWORD iDevNum = 0;
272 DISPLAY_DEVICE displayDevice;
273 BITMAP bitmap;
274 PGLOBAL_DATA pGlobalData;
275
276 pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA));
277 if (pGlobalData == NULL)
278 return;
279
280 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
281
282 /* Get video cards list */
283 displayDevice.cb = (DWORD)sizeof(DISPLAY_DEVICE);
284 while (EnumDisplayDevices(NULL, iDevNum, &displayDevice, 0))
285 {
286 if ((displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0)
287 {
288 if (AddDisplayDevice(pGlobalData, displayDevice.DeviceString, displayDevice.DeviceName))
289 Result++;
290 }
291 iDevNum++;
292 }
293 if (Result == 0)
294 {
295 /* No adapter found */
296 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_BPP), FALSE);
297 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION), FALSE);
298 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_RESOLUTION_TEXT), FALSE);
299 EnableWindow(GetDlgItem(hwndDlg, IDC_SETTINGS_ADVANCED), FALSE);
300 }
301 else if (Result == 1)
302 {
303 /* Single video adapter */
304 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
305 OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
306 }
307 else
308 {
309 /* FIXME: multi video adapter */
310 /* FIXME: choose selected adapter being the primary one */
311 }
312
313 pGlobalData->hBitmap = LoadImage(hApplet, MAKEINTRESOURCE(IDC_MONITOR), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
314 if (pGlobalData->hBitmap != NULL)
315 {
316 GetObject(pGlobalData->hBitmap, sizeof(BITMAP), &bitmap);
317
318 pGlobalData->cxSource = bitmap.bmWidth;
319 pGlobalData->cySource = bitmap.bmHeight;
320 }
321 }
322
323 static VOID
324 OnBPPChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData)
325 {
326 /* if new BPP is not compatible with resolution:
327 * 1) try to find the nearest smaller matching resolution
328 * 2) otherwise, get the nearest bigger resolution
329 */
330 PSETTINGS_ENTRY Current;
331 DWORD dmNewBitsPerPel;
332 DWORD index;
333 TCHAR Buffer[64];
334
335 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, WM_GETTEXT, (WPARAM)(sizeof(Buffer) / sizeof(TCHAR)), (LPARAM)Buffer);
336 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
337 dmNewBitsPerPel = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
338
339 /* find if new parameters are valid */
340 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
341 if (dmNewBitsPerPel == Current->dmBitsPerPel)
342 {
343 /* no change */
344 return;
345 }
346
347 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
348
349 if (dmNewBitsPerPel < Current->dmBitsPerPel)
350 {
351 Current = Current->Blink;
352 while (Current != NULL)
353 {
354 if (Current->dmBitsPerPel == dmNewBitsPerPel
355 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
356 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
357 {
358 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
359 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
360 return;
361 }
362 Current = Current->Blink;
363 }
364 }
365 else
366 {
367 Current = Current->Flink;
368 while (Current != NULL)
369 {
370 if (Current->dmBitsPerPel == dmNewBitsPerPel
371 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
372 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
373 {
374 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
375 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
376 return;
377 }
378 Current = Current->Flink;
379 }
380 }
381
382 /* search smaller resolution compatible with current color depth */
383 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
384 while (Current != NULL)
385 {
386 if (Current->dmBitsPerPel == dmNewBitsPerPel)
387 {
388 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
389 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
390 return;
391 }
392 Current = Current->Blink;
393 }
394
395 /* search bigger resolution compatible with current color depth */
396 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
397 while (Current != NULL)
398 {
399 if (Current->dmBitsPerPel == dmNewBitsPerPel)
400 {
401 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
402 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
403 return;
404 }
405 Current = Current->Flink;
406 }
407
408 /* we shouldn't go there */
409 }
410
411 static VOID
412 OnResolutionChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN DWORD NewPosition,
413 IN BOOL bUpdateThumb)
414 {
415 /* if new resolution is not compatible with color depth:
416 * 1) try to find the nearest bigger matching color depth
417 * 2) otherwise, get the nearest smaller color depth
418 */
419 PSETTINGS_ENTRY Current;
420 DWORD dmNewPelsHeight = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
421 DWORD dmNewPelsWidth = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
422
423 /* find if new parameters are valid */
424 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
425 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
426 {
427 /* no change */
428 return;
429 }
430
431 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
432
433 if (dmNewPelsHeight < Current->dmPelsHeight)
434 {
435 Current = Current->Blink;
436 while (Current != NULL)
437 {
438 if (Current->dmPelsHeight == dmNewPelsHeight
439 && Current->dmPelsWidth == dmNewPelsWidth
440 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
441 {
442 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
443 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
444 return;
445 }
446 Current = Current->Blink;
447 }
448 }
449 else
450 {
451 Current = Current->Flink;
452 while (Current != NULL)
453 {
454 if (Current->dmPelsHeight == dmNewPelsHeight
455 && Current->dmPelsWidth == dmNewPelsWidth
456 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
457 {
458 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
459 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
460 return;
461 }
462 Current = Current->Flink;
463 }
464 }
465
466 /* search bigger color depth compatible with current resolution */
467 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
468 while (Current != NULL)
469 {
470 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
471 {
472 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
473 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
474 return;
475 }
476 Current = Current->Flink;
477 }
478
479 /* search smaller color depth compatible with current resolution */
480 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
481 while (Current != NULL)
482 {
483 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
484 {
485 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
486 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
487 return;
488 }
489 Current = Current->Blink;
490 }
491
492 /* we shouldn't go there */
493 }
494
495 static VOID
496 OnAdvancedButton()
497 {
498 MessageBox(NULL, TEXT("That button doesn't do anything yet"), TEXT("Whoops"), MB_OK);
499 }
500
501 /* Property page dialog callback */
502 INT_PTR CALLBACK
503 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
504 {
505 PGLOBAL_DATA pGlobalData;
506
507 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
508
509 switch(uMsg)
510 {
511 case WM_INITDIALOG:
512 OnInitDialog(hwndDlg);
513 break;
514 case WM_COMMAND:
515 {
516 DWORD controlId = LOWORD(wParam);
517 DWORD command = HIWORD(wParam);
518
519 if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
520 OnAdvancedButton();
521 else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
522 OnBPPChanged(hwndDlg, pGlobalData);
523 break;
524 }
525 case WM_HSCROLL:
526 {
527 switch (LOWORD(wParam))
528 {
529 case TB_LINEUP:
530 case TB_LINEDOWN:
531 case TB_PAGEUP:
532 case TB_PAGEDOWN:
533 case TB_TOP:
534 case TB_BOTTOM:
535 case TB_ENDTRACK:
536 {
537 DWORD newPosition = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
538 OnResolutionChanged(hwndDlg, pGlobalData, newPosition, TRUE);
539 break;
540 }
541
542 case TB_THUMBTRACK:
543 OnResolutionChanged(hwndDlg, pGlobalData, HIWORD(wParam), FALSE);
544 break;
545 }
546 break;
547 }
548 case WM_NOTIFY:
549 {
550 LPNMHDR lpnm = (LPNMHDR)lParam;
551 if (lpnm->code == (UINT)PSN_APPLY)
552 {
553 if (pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth
554 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight
555 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
556 {
557 /* FIXME: Need to test changes */
558 /* Apply new settings */
559 LONG rc;
560 DEVMODE devmode;
561 RtlZeroMemory(&devmode, sizeof(DEVMODE));
562 devmode.dmSize = (WORD)sizeof(DEVMODE);
563 devmode.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
564 devmode.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
565 devmode.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
566 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
567 rc = ChangeDisplaySettingsEx(
568 pGlobalData->CurrentDisplayDevice->DeviceName,
569 &devmode,
570 NULL,
571 CDS_UPDATEREGISTRY,
572 NULL);
573 switch (rc)
574 {
575 case DISP_CHANGE_SUCCESSFUL:
576 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
577 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
578 pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
579 break;
580 case DISP_CHANGE_FAILED:
581 MessageBox(NULL, TEXT("Failed to apply new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
582 break;
583 case DISP_CHANGE_RESTART:
584 MessageBox(NULL, TEXT("You need to restart your computer to apply changes."), TEXT("Display settings"), MB_OK | MB_ICONINFORMATION);
585 break;
586 default:
587 MessageBox(NULL, TEXT("Unknown error when applying new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
588 break;
589 }
590 }
591 }
592 break;
593 }
594
595 case WM_PAINT:
596 {
597 PAINTSTRUCT ps;
598 HDC hdc, hdcMem;
599
600 hdc = BeginPaint(hwndDlg, &ps);
601
602 hdcMem = CreateCompatibleDC(hdc);
603 SelectObject(hdcMem, pGlobalData->hBitmap);
604
605 TransparentBlt(hdc, 98, 0,
606 pGlobalData->cxSource,
607 pGlobalData->cySource, hdcMem, 0, 0,
608 pGlobalData->cxSource,
609 pGlobalData->cySource, 0xFF80FF);
610
611 DeleteDC(hdcMem);
612 EndPaint(hwndDlg, &ps);
613
614 break;
615 }
616
617 case WM_DESTROY:
618 {
619 PDISPLAY_DEVICE_ENTRY Current = pGlobalData->DisplayDeviceList;
620 while (Current != NULL)
621 {
622 PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
623 PSETTINGS_ENTRY CurrentSettings = Current->Settings;
624 while (CurrentSettings != NULL)
625 {
626 PSETTINGS_ENTRY NextSettings = CurrentSettings->Flink;
627 HeapFree(GetProcessHeap(), 0, CurrentSettings);
628 CurrentSettings = NextSettings;
629 }
630 HeapFree(GetProcessHeap(), 0, Current);
631 Current = Next;
632 }
633
634 DeleteObject(pGlobalData->hBitmap);
635
636 HeapFree(GetProcessHeap(), 0, pGlobalData);
637 }
638 }
639 return FALSE;
640 }