use w3seek's control for single monitors displays
[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 MONSL_MONINFO monitors;
318
319 /* Single video adapter */
320 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_DEVICE, WM_SETTEXT, 0, (LPARAM)pGlobalData->DisplayDeviceList->DeviceDescription);
321 OnDisplayDeviceChanged(hwndDlg, pGlobalData, pGlobalData->DisplayDeviceList);
322
323 monitors.Position.x = monitors.Position.y = 0;
324 monitors.Size.cx = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
325 monitors.Size.cy = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
326 monitors.Flags = 0;
327 SendDlgItemMessage(hwndDlg,
328 IDC_SETTINGS_MONSEL,
329 MSLM_SETMONITORSINFO,
330 1,
331 (LPARAM)&monitors);
332 }
333 else
334 {
335 /* FIXME: multi video adapter */
336 /* FIXME: choose selected adapter being the primary one */
337 }
338
339 pGlobalData->hBitmap = LoadImage(hApplet, MAKEINTRESOURCE(IDC_MONITOR), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
340 if (pGlobalData->hBitmap != NULL)
341 {
342 GetObject(pGlobalData->hBitmap, sizeof(BITMAP), &bitmap);
343
344 pGlobalData->cxSource = bitmap.bmWidth;
345 pGlobalData->cySource = bitmap.bmHeight;
346 }
347 }
348
349 static VOID
350 OnBPPChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData)
351 {
352 /* if new BPP is not compatible with resolution:
353 * 1) try to find the nearest smaller matching resolution
354 * 2) otherwise, get the nearest bigger resolution
355 */
356 PSETTINGS_ENTRY Current;
357 DWORD dmNewBitsPerPel;
358 DWORD index;
359 TCHAR Buffer[64];
360
361 SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, WM_GETTEXT, (WPARAM)(sizeof(Buffer) / sizeof(TCHAR)), (LPARAM)Buffer);
362 index = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)Buffer);
363 dmNewBitsPerPel = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_BPP, CB_GETITEMDATA, index, 0);
364
365 /* find if new parameters are valid */
366 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
367 if (dmNewBitsPerPel == Current->dmBitsPerPel)
368 {
369 /* no change */
370 return;
371 }
372
373 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
374
375 if (dmNewBitsPerPel < Current->dmBitsPerPel)
376 {
377 Current = Current->Blink;
378 while (Current != NULL)
379 {
380 if (Current->dmBitsPerPel == dmNewBitsPerPel
381 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
382 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
383 {
384 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
385 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
386 return;
387 }
388 Current = Current->Blink;
389 }
390 }
391 else
392 {
393 Current = Current->Flink;
394 while (Current != NULL)
395 {
396 if (Current->dmBitsPerPel == dmNewBitsPerPel
397 && Current->dmPelsHeight == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight
398 && Current->dmPelsWidth == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth)
399 {
400 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
401 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
402 return;
403 }
404 Current = Current->Flink;
405 }
406 }
407
408 /* search smaller resolution compatible with current color depth */
409 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
410 while (Current != NULL)
411 {
412 if (Current->dmBitsPerPel == dmNewBitsPerPel)
413 {
414 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
415 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
416 return;
417 }
418 Current = Current->Blink;
419 }
420
421 /* search bigger resolution compatible with current color depth */
422 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
423 while (Current != NULL)
424 {
425 if (Current->dmBitsPerPel == dmNewBitsPerPel)
426 {
427 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
428 UpdateDisplay(hwndDlg, pGlobalData, TRUE);
429 return;
430 }
431 Current = Current->Flink;
432 }
433
434 /* we shouldn't go there */
435 }
436
437 static VOID
438 OnResolutionChanged(IN HWND hwndDlg, IN PGLOBAL_DATA pGlobalData, IN DWORD NewPosition,
439 IN BOOL bUpdateThumb)
440 {
441 /* if new resolution is not compatible with color depth:
442 * 1) try to find the nearest bigger matching color depth
443 * 2) otherwise, get the nearest smaller color depth
444 */
445 PSETTINGS_ENTRY Current;
446 DWORD dmNewPelsHeight = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsHeight;
447 DWORD dmNewPelsWidth = pGlobalData->CurrentDisplayDevice->Resolutions[NewPosition].dmPelsWidth;
448
449 /* find if new parameters are valid */
450 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings;
451 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
452 {
453 /* no change */
454 return;
455 }
456
457 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
458
459 if (dmNewPelsHeight < Current->dmPelsHeight)
460 {
461 Current = Current->Blink;
462 while (Current != NULL)
463 {
464 if (Current->dmPelsHeight == dmNewPelsHeight
465 && Current->dmPelsWidth == dmNewPelsWidth
466 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
467 {
468 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
469 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
470 return;
471 }
472 Current = Current->Blink;
473 }
474 }
475 else
476 {
477 Current = Current->Flink;
478 while (Current != NULL)
479 {
480 if (Current->dmPelsHeight == dmNewPelsHeight
481 && Current->dmPelsWidth == dmNewPelsWidth
482 && Current->dmBitsPerPel == pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel)
483 {
484 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
485 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
486 return;
487 }
488 Current = Current->Flink;
489 }
490 }
491
492 /* search bigger color depth compatible with current resolution */
493 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Flink;
494 while (Current != NULL)
495 {
496 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
497 {
498 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
499 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
500 return;
501 }
502 Current = Current->Flink;
503 }
504
505 /* search smaller color depth compatible with current resolution */
506 Current = pGlobalData->CurrentDisplayDevice->CurrentSettings->Blink;
507 while (Current != NULL)
508 {
509 if (dmNewPelsHeight == Current->dmPelsHeight && dmNewPelsWidth == Current->dmPelsWidth)
510 {
511 pGlobalData->CurrentDisplayDevice->CurrentSettings = Current;
512 UpdateDisplay(hwndDlg, pGlobalData, bUpdateThumb);
513 return;
514 }
515 Current = Current->Blink;
516 }
517
518 /* we shouldn't go there */
519 }
520
521 /* Property sheet page callback */
522 UINT CALLBACK
523 SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
524 {
525 UINT Ret = 0;
526
527 switch (uMsg)
528 {
529 case PSPCB_CREATE:
530 Ret = RegisterMonitorSelectionControl(hApplet);
531 break;
532
533 case PSPCB_RELEASE:
534 UnregisterMonitorSelectionControl(hApplet);
535 break;
536 }
537
538 return Ret;
539 }
540
541 /* Property page dialog callback */
542 INT_PTR CALLBACK
543 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
544 {
545 PGLOBAL_DATA pGlobalData;
546
547 pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
548
549 switch(uMsg)
550 {
551 case WM_INITDIALOG:
552 OnInitDialog(hwndDlg);
553 break;
554 case WM_COMMAND:
555 {
556 DWORD controlId = LOWORD(wParam);
557 DWORD command = HIWORD(wParam);
558
559 if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
560 DisplayAdvancedSettings(hwndDlg, pGlobalData->CurrentDisplayDevice);
561 else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
562 OnBPPChanged(hwndDlg, pGlobalData);
563 break;
564 }
565 case WM_HSCROLL:
566 {
567 switch (LOWORD(wParam))
568 {
569 case TB_LINEUP:
570 case TB_LINEDOWN:
571 case TB_PAGEUP:
572 case TB_PAGEDOWN:
573 case TB_TOP:
574 case TB_BOTTOM:
575 case TB_ENDTRACK:
576 {
577 DWORD newPosition = (DWORD) SendDlgItemMessage(hwndDlg, IDC_SETTINGS_RESOLUTION, TBM_GETPOS, 0, 0);
578 OnResolutionChanged(hwndDlg, pGlobalData, newPosition, TRUE);
579 break;
580 }
581
582 case TB_THUMBTRACK:
583 OnResolutionChanged(hwndDlg, pGlobalData, HIWORD(wParam), FALSE);
584 break;
585 }
586 break;
587 }
588 case WM_NOTIFY:
589 {
590 LPNMHDR lpnm = (LPNMHDR)lParam;
591 if (lpnm->code == (UINT)PSN_APPLY)
592 {
593 if (pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth
594 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight != pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight
595 || pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel != pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel)
596 {
597 /* FIXME: Need to test changes */
598 /* Apply new settings */
599 LONG rc;
600 DEVMODE devmode;
601 RtlZeroMemory(&devmode, sizeof(DEVMODE));
602 devmode.dmSize = (WORD)sizeof(DEVMODE);
603 devmode.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
604 devmode.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
605 devmode.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
606 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
607 rc = ChangeDisplaySettingsEx(
608 pGlobalData->CurrentDisplayDevice->DeviceName,
609 &devmode,
610 NULL,
611 CDS_UPDATEREGISTRY,
612 NULL);
613 switch (rc)
614 {
615 case DISP_CHANGE_SUCCESSFUL:
616 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
617 pGlobalData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
618 pGlobalData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pGlobalData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
619 break;
620 case DISP_CHANGE_FAILED:
621 MessageBox(NULL, TEXT("Failed to apply new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
622 break;
623 case DISP_CHANGE_RESTART:
624 MessageBox(NULL, TEXT("You need to restart your computer to apply changes."), TEXT("Display settings"), MB_OK | MB_ICONINFORMATION);
625 break;
626 default:
627 MessageBox(NULL, TEXT("Unknown error when applying new settings..."), TEXT("Display settings"), MB_OK | MB_ICONSTOP);
628 break;
629 }
630 }
631 }
632 break;
633 }
634
635 case WM_PAINT:
636 {
637 PAINTSTRUCT ps;
638 HDC hdc, hdcMem;
639
640 hdc = BeginPaint(hwndDlg, &ps);
641
642 hdcMem = CreateCompatibleDC(hdc);
643 SelectObject(hdcMem, pGlobalData->hBitmap);
644 /*
645 TransparentBlt(hdc, 98, 0,
646 pGlobalData->cxSource,
647 pGlobalData->cySource, hdcMem, 0, 0,
648 pGlobalData->cxSource,
649 pGlobalData->cySource, 0xFF80FF);
650 */
651 DeleteDC(hdcMem);
652 EndPaint(hwndDlg, &ps);
653
654 break;
655 }
656
657 case WM_DESTROY:
658 {
659 PDISPLAY_DEVICE_ENTRY Current = pGlobalData->DisplayDeviceList;
660 while (Current != NULL)
661 {
662 PDISPLAY_DEVICE_ENTRY Next = Current->Flink;
663 PSETTINGS_ENTRY CurrentSettings = Current->Settings;
664 while (CurrentSettings != NULL)
665 {
666 PSETTINGS_ENTRY NextSettings = CurrentSettings->Flink;
667 HeapFree(GetProcessHeap(), 0, CurrentSettings);
668 CurrentSettings = NextSettings;
669 }
670 HeapFree(GetProcessHeap(), 0, Current);
671 Current = Next;
672 }
673
674 DeleteObject(pGlobalData->hBitmap);
675
676 HeapFree(GetProcessHeap(), 0, pGlobalData);
677 }
678 }
679 return FALSE;
680 }