10 static HINSTANCE hInstance
;
13 typedef INT_PTR (WINAPI
*PDEVICEPROPERTIES
)(HWND
,LPCWSTR
,LPCWSTR
,BOOL
);
14 #define FUNC_DEVICEPROPERTIES "DevicePropertiesW"
16 typedef INT_PTR (WINAPI
*PDEVICEPROPERTIES
)(HWND
,LPCSTR
,LPCSTR
,BOOL
);
17 #define FUNC_DEVICEPROPERTIES "DevicePropertiesA"
21 GetMonitorDevInstID(LPCTSTR lpDeviceID
)
23 /* FIXME: Implement, allocate returned string with LocalAlloc! */
28 ShowMonitorProperties(PDESKMONITOR This
)
31 PDEVICEPROPERTIES pDeviceProperties
;
34 if (This
->SelMonitor
!= NULL
)
36 lpDevInstID
= GetMonitorDevInstID(This
->SelMonitor
->dd
.DeviceID
);
37 if (lpDevInstID
!= NULL
)
39 hDevMgr
= LoadLibrary(TEXT("devmgr.dll"));
42 pDeviceProperties
= (PDEVICEPROPERTIES
)GetProcAddress(hDevMgr
,
43 FUNC_DEVICEPROPERTIES
);
44 if (pDeviceProperties
!= NULL
)
46 pDeviceProperties(This
->hwndDlg
,
48 This
->SelMonitor
->dd
.DeviceID
,
55 LocalFree((HLOCAL
)lpDevInstID
);
61 UpdateMonitorSelection(PDESKMONITOR This
)
65 if (This
->dwMonitorCount
> 1)
67 This
->SelMonitor
= NULL
;
69 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
76 This
->SelMonitor
= (PDESKMONINFO
)SendDlgItemMessage(This
->hwndDlg
,
84 This
->SelMonitor
= This
->Monitors
;
86 EnableWindow(GetDlgItem(This
->hwndDlg
,
87 IDC_MONITORPROPERTIES
),
88 This
->SelMonitor
!= NULL
);
92 UpdatePruningControls(PDESKMONITOR This
)
94 EnableWindow(GetDlgItem(This
->hwndDlg
,
96 This
->bModesPruned
&& !This
->bKeyIsReadOnly
);
97 CheckDlgButton(This
->hwndDlg
,
99 (This
->bModesPruned
&& This
->bPruningOn
) ? BST_CHECKED
: BST_UNCHECKED
);
103 GetPruningSettings(PDESKMONITOR This
)
105 BOOL bModesPruned
= FALSE
, bKeyIsReadOnly
= FALSE
, bPruningOn
= FALSE
;
107 if (This
->DeskExtInterface
!= NULL
)
109 This
->DeskExtInterface
->GetPruningMode(This
->DeskExtInterface
->Context
,
115 /* Check the boolean values against zero before assigning it to the bitfields! */
116 This
->bModesPruned
= (bModesPruned
!= FALSE
);
117 This
->bKeyIsReadOnly
= (bKeyIsReadOnly
!= FALSE
);
118 This
->bPruningOn
= (bPruningOn
!= FALSE
);
120 UpdatePruningControls(This
);
124 UpdateRefreshFrequencyList(PDESKMONITOR This
)
126 PDEVMODEW lpCurrentMode
, lpMode
;
130 BOOL bHasDef
= FALSE
;
133 /* Fill the refresh rate combo box */
134 SendDlgItemMessage(This
->hwndDlg
,
140 lpCurrentMode
= This
->DeskExtInterface
->GetCurrentMode(This
->DeskExtInterface
->Context
);
145 lpMode
= This
->DeskExtInterface
->EnumAllModes(This
->DeskExtInterface
->Context
,
147 if (lpMode
!= NULL
&&
148 lpMode
->dmBitsPerPel
== lpCurrentMode
->dmBitsPerPel
&&
149 lpMode
->dmPelsWidth
== lpCurrentMode
->dmPelsWidth
&&
150 lpMode
->dmPelsHeight
== lpCurrentMode
->dmPelsHeight
)
152 /* We're only interested in refresh rates for the current resolution and color depth */
154 if (lpMode
->dmDisplayFrequency
<= 1)
156 /* Default hardware frequency */
162 if (!LoadString(hInstance
,
165 sizeof(szBuffer
) / sizeof(szBuffer
[0])))
167 szBuffer
[0] = TEXT('\0');
174 if (!LoadString(hInstance
,
177 sizeof(szFmt
) / sizeof(szFmt
[0])))
179 szFmt
[0] = TEXT('\0');
183 sizeof(szBuffer
) / sizeof(szBuffer
[0]),
185 lpMode
->dmDisplayFrequency
);
188 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
197 SendDlgItemMessage(This
->hwndDlg
,
203 if (lpMode
->dmDisplayFrequency
== lpCurrentMode
->dmDisplayFrequency
)
205 SendDlgItemMessage(This
->hwndDlg
,
214 } while (lpMode
!= NULL
);
216 EnableWindow(GetDlgItem(This
->hwndDlg
,
217 IDS_MONITORSETTINGSGROUP
),
219 EnableWindow(GetDlgItem(This
->hwndDlg
,
220 IDS_REFRESHRATELABEL
),
222 EnableWindow(GetDlgItem(This
->hwndDlg
,
226 GetPruningSettings(This
);
230 InitMonitorDialog(PDESKMONITOR This
)
232 PDESKMONINFO pmi
, pminext
, *pmilink
;
238 /* Free all allocated monitors */
239 pmi
= This
->Monitors
;
240 This
->Monitors
= NULL
;
244 LocalFree((HLOCAL
)pmi
);
248 This
->SelMonitor
= NULL
;
249 This
->dwMonitorCount
= 0;
251 if (This
->lpDisplayDevice
!= NULL
)
252 LocalFree((HLOCAL
)This
->lpDisplayDevice
);
254 This
->lpDisplayDevice
= QueryDeskCplString(This
->pdtobj
,
255 RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE
));
257 if (This
->DeskExtInterface
!= NULL
)
259 if (This
->lpDisplayDevice
!= NULL
)
261 /* Enumerate all monitors */
263 pmilink
= &This
->Monitors
;
268 bRet
= EnumDisplayDevices(This
->lpDisplayDevice
,
274 pmi
= LocalAlloc(LMEM_FIXED
,
283 pmilink
= &pmi
->Next
;
285 This
->dwMonitorCount
++;
291 This
->lpDevModeOnInit
= This
->DeskExtInterface
->GetCurrentMode(This
->DeskExtInterface
->Context
);
294 This
->lpDevModeOnInit
= NULL
;
296 This
->lpSelDevMode
= This
->lpDevModeOnInit
;
298 /* Setup the UI depending on how many monitors are attached */
299 if (This
->dwMonitorCount
== 0)
301 LPTSTR lpMonitorName
;
303 /* This is a fallback, let's hope that desk.cpl can provide us with a monitor name */
304 lpMonitorName
= QueryDeskCplString(This
->pdtobj
,
305 RegisterClipboardFormat(DESK_EXT_MONITORNAME
));
307 SetDlgItemText(This
->hwndDlg
,
311 if (lpMonitorName
!= NULL
)
312 LocalFree((HLOCAL
)lpMonitorName
);
314 else if (This
->dwMonitorCount
== 1)
316 This
->SelMonitor
= This
->Monitors
;
317 SetDlgItemText(This
->hwndDlg
,
319 This
->Monitors
->dd
.DeviceString
);
323 SendDlgItemMessage(This
->hwndDlg
,
329 pmi
= This
->Monitors
;
332 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
336 (LPARAM
)pmi
->dd
.DeviceString
);
339 SendDlgItemMessage(This
->hwndDlg
,
345 if (This
->SelMonitor
== NULL
)
347 SendDlgItemMessage(This
->hwndDlg
,
353 This
->SelMonitor
= pmi
;
361 /* Show/Hide controls */
362 ShowWindow(GetDlgItem(This
->hwndDlg
,
364 (This
->dwMonitorCount
<= 1 ? SW_SHOW
: SW_HIDE
));
365 ShowWindow(GetDlgItem(This
->hwndDlg
,
367 (This
->dwMonitorCount
> 1 ? SW_SHOW
: SW_HIDE
));
369 UpdateRefreshFrequencyList(This
);
370 UpdateMonitorSelection(This
);
374 UpdatePruningSelection(PDESKMONITOR This
)
378 if (This
->DeskExtInterface
!= NULL
&& This
->bModesPruned
&& !This
->bKeyIsReadOnly
)
380 bPruningOn
= IsDlgButtonChecked(This
->hwndDlg
,
381 IDC_PRUNINGCHECK
) != BST_UNCHECKED
;
383 if (bPruningOn
!= This
->bPruningOn
)
385 /* Tell desk.cpl to turn on/off pruning mode */
386 This
->bPruningOn
= bPruningOn
;
387 This
->DeskExtInterface
->SetPruningMode(This
->DeskExtInterface
->Context
,
390 /* Fill the refresh rate combobox again, we now receive a filtered
391 or unfiltered device mode list from desk.cpl (depending on whether
392 pruning is active or not) */
393 UpdateRefreshFrequencyList(This
);
395 (void)PropSheet_Changed(GetParent(This
->hwndDlg
),
402 UpdateRefreshRateSelection(PDESKMONITOR This
)
404 PDEVMODEW lpCurrentDevMode
;
407 if (This
->DeskExtInterface
!= NULL
)
409 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
416 lpCurrentDevMode
= This
->lpSelDevMode
;
417 This
->lpSelDevMode
= (PDEVMODEW
)SendDlgItemMessage(This
->hwndDlg
,
423 if (This
->lpSelDevMode
!= NULL
&& This
->lpSelDevMode
!= lpCurrentDevMode
)
425 This
->DeskExtInterface
->SetCurrentMode(This
->DeskExtInterface
->Context
,
428 UpdateRefreshFrequencyList(This
);
430 (void)PropSheet_Changed(GetParent(This
->hwndDlg
),
438 ApplyMonitorChanges(PDESKMONITOR This
)
442 if (This
->DeskExtInterface
!= NULL
)
444 /* Change the display settings through desk.cpl */
445 lChangeRet
= DeskCplExtDisplaySaveSettings(This
->DeskExtInterface
,
447 if (lChangeRet
== DISP_CHANGE_SUCCESSFUL
)
449 /* Save the new mode */
450 This
->lpDevModeOnInit
= This
->DeskExtInterface
->GetCurrentMode(This
->DeskExtInterface
->Context
);
451 This
->lpSelDevMode
= This
->lpDevModeOnInit
;
452 return PSNRET_NOERROR
;
454 else if (lChangeRet
== DISP_CHANGE_RESTART
)
456 /* Notify desk.cpl that the user needs to reboot */
457 PropSheet_RestartWindows(GetParent(This
->hwndDlg
));
458 return PSNRET_NOERROR
;
462 InitMonitorDialog(This
);
464 return PSNRET_INVALID_NOCHANGEPAGE
;
468 ResetMonitorChanges(PDESKMONITOR This
)
470 if (This
->DeskExtInterface
!= NULL
&& This
->lpDevModeOnInit
!= NULL
)
472 This
->DeskExtInterface
->SetCurrentMode(This
->DeskExtInterface
->Context
,
473 This
->lpDevModeOnInit
);
477 static INT_PTR CALLBACK
478 MonitorDlgProc(HWND hwndDlg
,
486 if (uMsg
!= WM_INITDIALOG
)
488 This
= (PDESKMONITOR
)GetWindowLongPtr(hwndDlg
,
495 This
= (PDESKMONITOR
)((LPCPROPSHEETPAGE
)lParam
)->lParam
;
496 This
->hwndDlg
= hwndDlg
;
497 SetWindowLongPtr(hwndDlg
,
501 InitMonitorDialog(This
);
506 switch (LOWORD(wParam
))
508 case IDC_MONITORPROPERTIES
:
509 ShowMonitorProperties(This
);
512 case IDC_MONITORLIST
:
513 if (HIWORD(wParam
) == LBN_SELCHANGE
)
514 UpdateMonitorSelection(This
);
517 case IDC_PRUNINGCHECK
:
518 if (HIWORD(wParam
) == BN_CLICKED
)
519 UpdatePruningSelection(This
);
522 case IDC_REFRESHRATE
:
523 if (HIWORD(wParam
) == CBN_SELCHANGE
)
524 UpdateRefreshRateSelection(This
);
531 NMHDR
*nmh
= (NMHDR
*)lParam
;
537 SetWindowLongPtr(hwndDlg
,
539 ApplyMonitorChanges(This
));
544 ResetMonitorChanges(This
);
548 UpdateRefreshFrequencyList(This
);
559 IDeskMonitor_Destroy(PDESKMONITOR This
)
561 PDESKMONINFO pmi
, pminext
;
563 if (This
->pdtobj
!= NULL
)
565 IDataObject_Release(This
->pdtobj
);
569 if (This
->DeskExtInterface
!= NULL
)
571 LocalFree((HLOCAL
)This
->DeskExtInterface
);
572 This
->DeskExtInterface
= NULL
;
575 if (This
->lpDisplayDevice
!= NULL
)
577 LocalFree((HLOCAL
)This
->lpDisplayDevice
);
578 This
->lpDisplayDevice
= NULL
;
581 /* Free all monitors */
582 pmi
= This
->Monitors
;
583 This
->Monitors
= NULL
;
587 LocalFree((HLOCAL
)pmi
);
593 IDeskMonitor_AddRef(PDESKMONITOR This
)
597 ret
= InterlockedIncrement((PLONG
)&This
->ref
);
599 InterlockedIncrement(&dll_refs
);
605 IDeskMonitor_Release(PDESKMONITOR This
)
609 ret
= InterlockedDecrement((PLONG
)&This
->ref
);
612 IDeskMonitor_Destroy(This
);
613 InterlockedDecrement(&dll_refs
);
615 HeapFree(GetProcessHeap(),
623 HRESULT STDMETHODCALLTYPE
624 IDeskMonitor_QueryInterface(PDESKMONITOR This
,
631 &IID_IShellPropSheetExt
) ||
635 *pvObject
= impl_to_interface(This
, IShellPropSheetExt
);
637 else if (IsEqualIID(iid
,
640 *pvObject
= impl_to_interface(This
, IShellExtInit
);
642 else if (IsEqualIID(iid
,
645 *pvObject
= impl_to_interface(This
, IClassFactory
);
649 DPRINT1("IDeskMonitor::QueryInterface(%p,%p): E_NOINTERFACE\n", iid
, pvObject
);
650 return E_NOINTERFACE
;
653 IDeskMonitor_AddRef(This
);
658 IDeskMonitor_Initialize(PDESKMONITOR This
,
659 LPCITEMIDLIST pidlFolder
,
663 DPRINT1("IDeskMonitor::Initialize(%p,%p,%p)\n", pidlFolder
, pdtobj
, hkeyProgID
);
667 IDataObject_AddRef(pdtobj
);
668 This
->pdtobj
= pdtobj
;
670 /* Get a copy of the desk.cpl extension interface */
671 This
->DeskExtInterface
= QueryDeskCplExtInterface(This
->pdtobj
);
672 if (This
->DeskExtInterface
!= NULL
)
680 IDeskMonitor_AddPages(PDESKMONITOR This
,
681 LPFNADDPROPSHEETPAGE pfnAddPage
,
687 DPRINT1("IDeskMonitor::AddPages(%p,%p)\n", pfnAddPage
, lParam
);
689 psp
.dwSize
= sizeof(psp
);
690 psp
.dwFlags
= PSP_DEFAULT
;
691 psp
.hInstance
= hInstance
;
692 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_MONITOR
);
693 psp
.pfnDlgProc
= MonitorDlgProc
;
694 psp
.lParam
= (LPARAM
)This
;
696 hpsp
= CreatePropertySheetPage(&psp
);
697 if (hpsp
!= NULL
&& pfnAddPage(hpsp
, lParam
))
704 IDeskMonitor_ReplacePage(PDESKMONITOR This
,
706 LPFNADDPROPSHEETPAGE pfnReplacePage
,
709 DPRINT1("IDeskMonitor::ReplacePage(%u,%p,%p)\n", uPageID
, pfnReplacePage
, lParam
);
714 IDeskMonitor_Constructor(REFIID riid
,
718 HRESULT hRet
= E_OUTOFMEMORY
;
720 DPRINT1("IDeskMonitor::Constructor(%p,%p)\n", riid
, ppv
);
722 This
= HeapAlloc(GetProcessHeap(),
730 IDeskMonitor_InitIface(This
);
732 hRet
= IDeskMonitor_QueryInterface(This
,
735 if (!SUCCEEDED(hRet
))
736 IDeskMonitor_Release(This
);
743 DllMain(HINSTANCE hinstDLL
,
749 case DLL_PROCESS_ATTACH
:
750 hInstance
= hinstDLL
;
751 DisableThreadLibraryCalls(hInstance
);