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