6 static HINSTANCE hInstance
;
9 typedef INT_PTR (WINAPI
*PDEVICEPROPERTIES
)(HWND
,LPCWSTR
,LPCWSTR
,BOOL
);
10 #define FUNC_DEVICEPROPERTIES "DevicePropertiesW"
12 typedef INT_PTR (WINAPI
*PDEVICEPROPERTIES
)(HWND
,LPCSTR
,LPCSTR
,BOOL
);
13 #define FUNC_DEVICEPROPERTIES "DevicePropertiesA"
17 GetMonitorDevInstID(LPCTSTR lpDeviceID
)
19 /* FIXME: Implement, allocate returned string with LocalAlloc! */
24 ShowMonitorProperties(PDESKMONITOR This
)
27 PDEVICEPROPERTIES pDeviceProperties
;
30 if (This
->SelMonitor
!= NULL
)
32 lpDevInstID
= GetMonitorDevInstID(This
->SelMonitor
->dd
.DeviceID
);
33 if (lpDevInstID
!= NULL
)
35 hDevMgr
= LoadLibrary(TEXT("devmgr.dll"));
38 pDeviceProperties
= (PDEVICEPROPERTIES
)GetProcAddress(hDevMgr
,
39 FUNC_DEVICEPROPERTIES
);
40 if (pDeviceProperties
!= NULL
)
42 pDeviceProperties(This
->hwndDlg
,
44 This
->SelMonitor
->dd
.DeviceID
,
51 LocalFree((HLOCAL
)lpDevInstID
);
57 UpdateMonitorSelection(PDESKMONITOR This
)
61 if (This
->dwMonitorCount
> 1)
63 This
->SelMonitor
= NULL
;
65 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
72 This
->SelMonitor
= (PDESKMONINFO
)SendDlgItemMessage(This
->hwndDlg
,
80 This
->SelMonitor
= This
->Monitors
;
82 EnableWindow(GetDlgItem(This
->hwndDlg
,
83 IDC_MONITORPROPERTIES
),
84 This
->SelMonitor
!= NULL
);
88 UpdatePruningControls(PDESKMONITOR This
)
90 EnableWindow(GetDlgItem(This
->hwndDlg
,
92 This
->bModesPruned
&& !This
->bKeyIsReadOnly
);
93 CheckDlgButton(This
->hwndDlg
,
95 (This
->bModesPruned
&& This
->bPruningOn
) ? BST_CHECKED
: BST_UNCHECKED
);
99 GetPruningSettings(PDESKMONITOR This
)
101 BOOL bModesPruned
= FALSE
, bKeyIsReadOnly
= FALSE
, bPruningOn
= FALSE
;
103 if (This
->DeskExtInterface
!= NULL
)
105 This
->DeskExtInterface
->GetPruningMode(This
->DeskExtInterface
->Context
,
111 /* Check the boolean values against zero before assigning it to the bitfields! */
112 This
->bModesPruned
= (bModesPruned
!= FALSE
);
113 This
->bKeyIsReadOnly
= (bKeyIsReadOnly
!= FALSE
);
114 This
->bPruningOn
= (bPruningOn
!= FALSE
);
116 UpdatePruningControls(This
);
120 UpdateRefreshFrequencyList(PDESKMONITOR This
)
122 PDEVMODEW lpCurrentMode
, lpMode
;
126 BOOL bHasDef
= FALSE
;
129 /* Fill the refresh rate combo box */
130 SendDlgItemMessage(This
->hwndDlg
,
136 lpCurrentMode
= This
->DeskExtInterface
->GetCurrentMode(This
->DeskExtInterface
->Context
);
141 lpMode
= This
->DeskExtInterface
->EnumAllModes(This
->DeskExtInterface
->Context
,
143 if (lpMode
!= NULL
&&
144 lpMode
->dmBitsPerPel
== lpCurrentMode
->dmBitsPerPel
&&
145 lpMode
->dmPelsWidth
== lpCurrentMode
->dmPelsWidth
&&
146 lpMode
->dmPelsHeight
== lpCurrentMode
->dmPelsHeight
)
148 /* We're only interested in refresh rates for the current resolution and color depth */
150 if (lpMode
->dmDisplayFrequency
<= 1)
152 /* Default hardware frequency */
158 if (!LoadString(hInstance
,
161 sizeof(szBuffer
) / sizeof(szBuffer
[0])))
163 szBuffer
[0] = TEXT('\0');
170 if (!LoadString(hInstance
,
173 sizeof(szFmt
) / sizeof(szFmt
[0])))
175 szFmt
[0] = TEXT('\0');
179 sizeof(szBuffer
) / sizeof(szBuffer
[0]),
181 lpMode
->dmDisplayFrequency
);
184 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
193 SendDlgItemMessage(This
->hwndDlg
,
199 if (lpMode
->dmDisplayFrequency
== lpCurrentMode
->dmDisplayFrequency
)
201 SendDlgItemMessage(This
->hwndDlg
,
210 } while (lpMode
!= NULL
);
212 EnableWindow(GetDlgItem(This
->hwndDlg
,
213 IDS_MONITORSETTINGSGROUP
),
215 EnableWindow(GetDlgItem(This
->hwndDlg
,
216 IDS_REFRESHRATELABEL
),
218 EnableWindow(GetDlgItem(This
->hwndDlg
,
222 GetPruningSettings(This
);
226 InitMonitorDialog(PDESKMONITOR This
)
228 PDESKMONINFO pmi
, pminext
, *pmilink
;
234 /* Free all allocated monitors */
235 pmi
= This
->Monitors
;
236 This
->Monitors
= NULL
;
240 LocalFree((HLOCAL
)pmi
);
244 This
->SelMonitor
= NULL
;
245 This
->dwMonitorCount
= 0;
247 if (This
->lpDisplayDevice
!= NULL
)
248 LocalFree((HLOCAL
)This
->lpDisplayDevice
);
250 This
->lpDisplayDevice
= QueryDeskCplString(This
->pdtobj
,
251 RegisterClipboardFormat(DESK_EXT_DISPLAYDEVICE
));
253 if (This
->DeskExtInterface
!= NULL
)
255 if (This
->lpDisplayDevice
!= NULL
)
257 /* Enumerate all monitors */
259 pmilink
= &This
->Monitors
;
264 bRet
= EnumDisplayDevices(This
->lpDisplayDevice
,
270 pmi
= LocalAlloc(LMEM_FIXED
,
279 pmilink
= &pmi
->Next
;
281 This
->dwMonitorCount
++;
287 This
->lpDevModeOnInit
= This
->DeskExtInterface
->GetCurrentMode(This
->DeskExtInterface
->Context
);
290 This
->lpDevModeOnInit
= NULL
;
292 This
->lpSelDevMode
= This
->lpDevModeOnInit
;
294 /* Setup the UI depending on how many monitors are attached */
295 if (This
->dwMonitorCount
== 0)
297 LPTSTR lpMonitorName
;
299 /* This is a fallback, let's hope that desk.cpl can provide us with a monitor name */
300 lpMonitorName
= QueryDeskCplString(This
->pdtobj
,
301 RegisterClipboardFormat(DESK_EXT_MONITORNAME
));
303 SetDlgItemText(This
->hwndDlg
,
307 if (lpMonitorName
!= NULL
)
308 LocalFree((HLOCAL
)lpMonitorName
);
310 else if (This
->dwMonitorCount
== 1)
312 This
->SelMonitor
= This
->Monitors
;
313 SetDlgItemText(This
->hwndDlg
,
315 This
->Monitors
->dd
.DeviceString
);
319 SendDlgItemMessage(This
->hwndDlg
,
325 pmi
= This
->Monitors
;
328 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
332 (LPARAM
)pmi
->dd
.DeviceString
);
335 SendDlgItemMessage(This
->hwndDlg
,
341 if (This
->SelMonitor
== NULL
)
343 SendDlgItemMessage(This
->hwndDlg
,
349 This
->SelMonitor
= pmi
;
357 /* Show/Hide controls */
358 ShowWindow(GetDlgItem(This
->hwndDlg
,
360 (This
->dwMonitorCount
<= 1 ? SW_SHOW
: SW_HIDE
));
361 ShowWindow(GetDlgItem(This
->hwndDlg
,
363 (This
->dwMonitorCount
> 1 ? SW_SHOW
: SW_HIDE
));
365 UpdateRefreshFrequencyList(This
);
366 UpdateMonitorSelection(This
);
370 UpdatePruningSelection(PDESKMONITOR This
)
374 if (This
->DeskExtInterface
!= NULL
&& This
->bModesPruned
&& !This
->bKeyIsReadOnly
)
376 bPruningOn
= IsDlgButtonChecked(This
->hwndDlg
,
377 IDC_PRUNINGCHECK
) != BST_UNCHECKED
;
379 if (bPruningOn
!= This
->bPruningOn
)
381 /* Tell desk.cpl to turn on/off pruning mode */
382 This
->bPruningOn
= bPruningOn
;
383 This
->DeskExtInterface
->SetPruningMode(This
->DeskExtInterface
->Context
,
386 /* Fill the refresh rate combobox again, we now receive a filtered
387 or unfiltered device mode list from desk.cpl (depending on whether
388 pruning is active or not) */
389 UpdateRefreshFrequencyList(This
);
391 (void)PropSheet_Changed(GetParent(This
->hwndDlg
),
398 UpdateRefreshRateSelection(PDESKMONITOR This
)
400 PDEVMODEW lpCurrentDevMode
;
403 if (This
->DeskExtInterface
!= NULL
)
405 i
= (INT
)SendDlgItemMessage(This
->hwndDlg
,
412 lpCurrentDevMode
= This
->lpSelDevMode
;
413 This
->lpSelDevMode
= (PDEVMODEW
)SendDlgItemMessage(This
->hwndDlg
,
419 if (This
->lpSelDevMode
!= NULL
&& This
->lpSelDevMode
!= lpCurrentDevMode
)
421 This
->DeskExtInterface
->SetCurrentMode(This
->DeskExtInterface
->Context
,
424 UpdateRefreshFrequencyList(This
);
426 (void)PropSheet_Changed(GetParent(This
->hwndDlg
),
434 ApplyMonitorChanges(PDESKMONITOR This
)
438 if (This
->DeskExtInterface
!= NULL
)
440 /* Change the display settings through desk.cpl */
441 lChangeRet
= DeskCplExtDisplaySaveSettings(This
->DeskExtInterface
,
443 if (lChangeRet
== DISP_CHANGE_SUCCESSFUL
)
445 /* Save the new mode */
446 This
->lpDevModeOnInit
= This
->DeskExtInterface
->GetCurrentMode(This
->DeskExtInterface
->Context
);
447 This
->lpSelDevMode
= This
->lpDevModeOnInit
;
448 return PSNRET_NOERROR
;
450 else if (lChangeRet
== DISP_CHANGE_RESTART
)
452 /* Notify desk.cpl that the user needs to reboot */
453 PropSheet_RestartWindows(GetParent(This
->hwndDlg
));
454 return PSNRET_NOERROR
;
458 InitMonitorDialog(This
);
460 return PSNRET_INVALID_NOCHANGEPAGE
;
464 ResetMonitorChanges(PDESKMONITOR This
)
466 if (This
->DeskExtInterface
!= NULL
&& This
->lpDevModeOnInit
!= NULL
)
468 This
->DeskExtInterface
->SetCurrentMode(This
->DeskExtInterface
->Context
,
469 This
->lpDevModeOnInit
);
473 static INT_PTR CALLBACK
474 MonitorDlgProc(HWND hwndDlg
,
482 if (uMsg
!= WM_INITDIALOG
)
484 This
= (PDESKMONITOR
)GetWindowLongPtr(hwndDlg
,
491 This
= (PDESKMONITOR
)((LPCPROPSHEETPAGE
)lParam
)->lParam
;
492 This
->hwndDlg
= hwndDlg
;
493 SetWindowLongPtr(hwndDlg
,
497 InitMonitorDialog(This
);
502 switch (LOWORD(wParam
))
504 case IDC_MONITORPROPERTIES
:
505 ShowMonitorProperties(This
);
508 case IDC_MONITORLIST
:
509 if (HIWORD(wParam
) == LBN_SELCHANGE
)
510 UpdateMonitorSelection(This
);
513 case IDC_PRUNINGCHECK
:
514 if (HIWORD(wParam
) == BN_CLICKED
)
515 UpdatePruningSelection(This
);
518 case IDC_REFRESHRATE
:
519 if (HIWORD(wParam
) == CBN_SELCHANGE
)
520 UpdateRefreshRateSelection(This
);
527 NMHDR
*nmh
= (NMHDR
*)lParam
;
533 SetWindowLongPtr(hwndDlg
,
535 ApplyMonitorChanges(This
));
540 ResetMonitorChanges(This
);
544 UpdateRefreshFrequencyList(This
);
555 IDeskMonitor_Destroy(PDESKMONITOR This
)
557 PDESKMONINFO pmi
, pminext
;
559 if (This
->pdtobj
!= NULL
)
561 IDataObject_Release(This
->pdtobj
);
565 if (This
->DeskExtInterface
!= NULL
)
567 LocalFree((HLOCAL
)This
->DeskExtInterface
);
568 This
->DeskExtInterface
= NULL
;
571 if (This
->lpDisplayDevice
!= NULL
)
573 LocalFree((HLOCAL
)This
->lpDisplayDevice
);
574 This
->lpDisplayDevice
= NULL
;
577 /* Free all monitors */
578 pmi
= This
->Monitors
;
579 This
->Monitors
= NULL
;
583 LocalFree((HLOCAL
)pmi
);
589 IDeskMonitor_AddRef(PDESKMONITOR This
)
593 ret
= InterlockedIncrement((PLONG
)&This
->ref
);
595 InterlockedIncrement(&dll_refs
);
601 IDeskMonitor_Release(PDESKMONITOR This
)
605 ret
= InterlockedDecrement((PLONG
)&This
->ref
);
608 IDeskMonitor_Destroy(This
);
609 InterlockedDecrement(&dll_refs
);
611 HeapFree(GetProcessHeap(),
619 HRESULT STDMETHODCALLTYPE
620 IDeskMonitor_QueryInterface(PDESKMONITOR This
,
627 &IID_IShellPropSheetExt
) ||
631 *pvObject
= impl_to_interface(This
, IShellPropSheetExt
);
633 else if (IsEqualIID(iid
,
636 *pvObject
= impl_to_interface(This
, IShellExtInit
);
638 else if (IsEqualIID(iid
,
641 *pvObject
= impl_to_interface(This
, IClassFactory
);
645 DPRINT1("IDeskMonitor::QueryInterface(%p,%p): E_NOINTERFACE\n", iid
, pvObject
);
646 return E_NOINTERFACE
;
649 IDeskMonitor_AddRef(This
);
654 IDeskMonitor_Initialize(PDESKMONITOR This
,
655 LPCITEMIDLIST pidlFolder
,
659 DPRINT1("IDeskMonitor::Initialize(%p,%p,%p)\n", pidlFolder
, pdtobj
, hkeyProgID
);
663 IDataObject_AddRef(pdtobj
);
664 This
->pdtobj
= pdtobj
;
666 /* Get a copy of the desk.cpl extension interface */
667 This
->DeskExtInterface
= QueryDeskCplExtInterface(This
->pdtobj
);
668 if (This
->DeskExtInterface
!= NULL
)
676 IDeskMonitor_AddPages(PDESKMONITOR This
,
677 LPFNADDPROPSHEETPAGE pfnAddPage
,
683 DPRINT1("IDeskMonitor::AddPages(%p,%p)\n", pfnAddPage
, lParam
);
685 psp
.dwSize
= sizeof(psp
);
686 psp
.dwFlags
= PSP_DEFAULT
;
687 psp
.hInstance
= hInstance
;
688 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_MONITOR
);
689 psp
.pfnDlgProc
= MonitorDlgProc
;
690 psp
.lParam
= (LPARAM
)This
;
692 hpsp
= CreatePropertySheetPage(&psp
);
693 if (hpsp
!= NULL
&& pfnAddPage(hpsp
, lParam
))
700 IDeskMonitor_ReplacePage(PDESKMONITOR This
,
702 LPFNADDPROPSHEETPAGE pfnReplacePage
,
705 DPRINT1("IDeskMonitor::ReplacePage(%u,%p,%p)\n", uPageID
, pfnReplacePage
, lParam
);
710 IDeskMonitor_Constructor(REFIID riid
,
714 HRESULT hRet
= E_OUTOFMEMORY
;
716 DPRINT1("IDeskMonitor::Constructor(%p,%p)\n", riid
, ppv
);
718 This
= HeapAlloc(GetProcessHeap(),
726 IDeskMonitor_InitIface(This
);
728 hRet
= IDeskMonitor_QueryInterface(This
,
731 if (!SUCCEEDED(hRet
))
732 IDeskMonitor_Release(This
);
739 DllMain(HINSTANCE hinstDLL
,
745 case DLL_PROCESS_ATTACH
:
746 hInstance
= hinstDLL
;
747 DisableThreadLibraryCalls(hInstance
);