Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

928 lines
26 KiB

  1. /******************************************************************************
  2. Source File: deskmon.cpp
  3. Main code for the advanced desktop Monitor page
  4. Copyright (c) 1997-1998 by Microsoft Corporation
  5. Change History:
  6. 12-16-97 AndreVa - Created It
  7. ******************************************************************************/
  8. #include "deskmon.h"
  9. #define DECL_CRTFREE
  10. #include <crtfree.h>
  11. //
  12. // The function DeviceProperties() is implemented in DevMgr.dll; Since we don't have a devmgr.h, we
  13. // explicitly declare it here.
  14. //
  15. typedef int (WINAPI *DEVPROPERTIES)(
  16. HWND hwndParent,
  17. LPCTSTR MachineName,
  18. LPCTSTR DeviceID,
  19. BOOL ShowDeviceTree
  20. );
  21. // OLE-Registry magic number
  22. // 42071713-76d4-11d1-8b24-00a0c9068ff3
  23. //
  24. GUID g_CLSID_CplExt = { 0x42071713, 0x76d4, 0x11d1,
  25. { 0x8b, 0x24, 0x00, 0xa0, 0xc9, 0x06, 0x8f, 0xf3}
  26. };
  27. DESK_EXTENSION_INTERFACE DeskInterface;
  28. static const DWORD sc_MonitorHelpIds[] =
  29. {
  30. IDC_MONITOR_GRP, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_TYPE,
  31. IDI_MONITOR, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_TYPE,
  32. IDC_MONITORDESC, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_TYPE,
  33. IDC_MONITORS_LIST, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_MONITORTYPE_LISTBOX,
  34. IDC_PROPERTIES, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_PROPERTIES,
  35. IDC_MONSET_GRP, IDH_NOHELP,
  36. IDC_MONSET_FREQSTR, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_REFRESH,
  37. IDC_MONSET_FREQ, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_REFRESH,
  38. IDC_MONSET_PRUNNING_MODE, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_HIDEMODE_CHECKBOX,
  39. IDC_MONSET_PRUNNING_MODE_DESC, IDH_DISPLAY_SETTINGS_ADVANCED_MONITOR_HIDEMODE_CHECKBOX,
  40. 0, 0
  41. };
  42. ///////////////////////////////////////////////////////////////////////////////
  43. //
  44. // Messagebox wrapper
  45. //
  46. ///////////////////////////////////////////////////////////////////////////////
  47. int
  48. FmtMessageBox(
  49. HWND hwnd,
  50. UINT fuStyle,
  51. DWORD dwTitleID,
  52. DWORD dwTextID)
  53. {
  54. TCHAR Title[256];
  55. TCHAR Text[1700];
  56. LoadString(g_hInst, dwTextID, Text, ARRAYSIZE(Text));
  57. LoadString(g_hInst, dwTitleID, Title, ARRAYSIZE(Title));
  58. return (MessageBox(hwnd, Text, Title, fuStyle));
  59. }
  60. // Constructors / destructor
  61. CMonitorPage::CMonitorPage(HWND hDlg)
  62. : m_hDlg(hDlg)
  63. , m_lpdmPrevious(NULL)
  64. , m_bCanBePruned(FALSE)
  65. , m_bIsPruningReadOnly(TRUE)
  66. , m_bIsPruningOn(FALSE)
  67. , m_cMonitors(0)
  68. , m_hMonitorsList(NULL)
  69. , m_lpdmOnCancel(NULL)
  70. , m_bOnCancelIsPruningOn(FALSE)
  71. {
  72. // preconditions
  73. //ASSERT(NULL != hDlg);
  74. }
  75. CMonitorPage::~CMonitorPage()
  76. {
  77. }
  78. void CMonitorPage::OnApply()
  79. {
  80. long lRet = PSNRET_INVALID_NOCHANGEPAGE;
  81. HINSTANCE hInst;
  82. LPDISPLAY_SAVE_SETTINGS lpfnDisplaySaveSettings = NULL;
  83. hInst = LoadLibrary(TEXT("desk.cpl"));
  84. if (hInst)
  85. {
  86. lpfnDisplaySaveSettings = (LPDISPLAY_SAVE_SETTINGS)
  87. GetProcAddress(hInst, "DisplaySaveSettings");
  88. if (lpfnDisplaySaveSettings)
  89. {
  90. long lSave = lpfnDisplaySaveSettings(DeskInterface.pContext, m_hDlg);
  91. LPDEVMODEW lpdmCurrent = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext);
  92. if (lSave == DISP_CHANGE_SUCCESSFUL)
  93. {
  94. //
  95. // Save the current mode - to restore it in case the user cancels the p. sheet
  96. //
  97. m_lpdmOnCancel = m_lpdmPrevious = lpdmCurrent;
  98. m_bOnCancelIsPruningOn = m_bIsPruningOn;
  99. lRet = PSNRET_NOERROR;
  100. }
  101. else if (lSave == DISP_CHANGE_RESTART)
  102. {
  103. //
  104. // User wants to reboot system.
  105. //
  106. PropSheet_RestartWindows(GetParent(m_hDlg));
  107. lRet = PSNRET_NOERROR;
  108. }
  109. else
  110. {
  111. //
  112. // Keep the apply button active
  113. //
  114. lRet = PSNRET_INVALID_NOCHANGEPAGE;
  115. RefreshFrequenciesList();
  116. BOOL bCanBePruned, bIsPruningReadOnly, bIsPruningOn;
  117. DeskInterface.lpfnGetPruningMode(DeskInterface.pContext,
  118. &bCanBePruned,
  119. &bIsPruningReadOnly,
  120. &bIsPruningOn);
  121. if(m_bIsPruningOn != bIsPruningOn)
  122. InitPruningMode();
  123. }
  124. }
  125. FreeLibrary(hInst);
  126. }
  127. SetWindowLongPtr(m_hDlg, DWLP_MSGRESULT, lRet);
  128. }
  129. void CMonitorPage::OnCancel()
  130. {
  131. if (m_bCanBePruned && !m_bIsPruningReadOnly &&
  132. ((m_bOnCancelIsPruningOn != 0) != (m_bIsPruningOn != 0)))
  133. DeskInterface.lpfnSetPruningMode(DeskInterface.pContext, m_bOnCancelIsPruningOn);
  134. DeskInterface.lpfnSetSelectedMode(DeskInterface.pContext, m_lpdmOnCancel);
  135. };
  136. void CMonitorPage::OnInitDialog()
  137. {
  138. m_hMonitorsList = GetDlgItem(m_hDlg, IDC_MONITORS_LIST);
  139. HWND hSingleMonitor = GetDlgItem(m_hDlg, IDC_MONITORDESC);
  140. //ASSERT((NULL != m_hMonitorsList) && (NULL != hSingleMonitor));
  141. ListBox_ResetContent(m_hMonitorsList);
  142. //
  143. // Get the CPL extension interfaces from IDataObject.
  144. //
  145. STGMEDIUM stgmExt;
  146. FORMATETC fmteExt = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_INTERFACE),
  147. (DVTARGETDEVICE FAR *) NULL,
  148. DVASPECT_CONTENT,
  149. -1,
  150. TYMED_HGLOBAL};
  151. HRESULT hres = g_lpdoTarget->GetData(&fmteExt, &stgmExt);
  152. if (SUCCEEDED(hres) && stgmExt.hGlobal)
  153. {
  154. //
  155. // The storage now contains Display device path (\\.\DisplayX) in UNICODE.
  156. //
  157. PDESK_EXTENSION_INTERFACE pInterface =
  158. (PDESK_EXTENSION_INTERFACE) GlobalLock(stgmExt.hGlobal);
  159. RtlCopyMemory(&DeskInterface,
  160. pInterface,
  161. min(pInterface->cbSize,
  162. sizeof(DESK_EXTENSION_INTERFACE)));
  163. GlobalUnlock(stgmExt.hGlobal);
  164. ReleaseStgMedium(&stgmExt);
  165. }
  166. //
  167. // Get the adapter devnode.
  168. // The adapter is the parent of all monitors in the device tree.
  169. //
  170. DEVINST devInstAdapter;
  171. BOOL bDevInstAdapter = FALSE;
  172. STGMEDIUM stgmAdpId;
  173. FORMATETC fmteAdpId = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_DISPLAY_ID),
  174. (DVTARGETDEVICE FAR *) NULL,
  175. DVASPECT_CONTENT,
  176. -1,
  177. TYMED_HGLOBAL};
  178. hres = g_lpdoTarget->GetData(&fmteAdpId, &stgmAdpId);
  179. if(SUCCEEDED(hres) && stgmAdpId.hGlobal)
  180. {
  181. LPWSTR pwDeviceID = (LPWSTR) GlobalLock(stgmAdpId.hGlobal);
  182. #ifdef UNICODE
  183. bDevInstAdapter = (CM_Locate_DevNodeW(&devInstAdapter, pwDeviceID, 0) == CR_SUCCESS);
  184. #else // UNICODE
  185. CHAR szBuffer[MAX_PATH];
  186. bDevInstAdapter = (BOOL)WideCharToMultiByte(CP_ACP, 0, pwDeviceID, lstrlenW(pwDeviceID) + 1,
  187. szBuffer, MAX_PATH, NULL, NULL);
  188. if(bDevInstAdapter)
  189. {
  190. bDevInstAdapter = (CM_Locate_DevNodeA(&devInstAdapter, szBuffer, 0) == CR_SUCCESS);
  191. }
  192. #endif // UNICODE
  193. GlobalUnlock(stgmAdpId.hGlobal);
  194. ReleaseStgMedium(&stgmAdpId);
  195. }
  196. //
  197. // Get the adapter device and enum all monitors
  198. //
  199. STGMEDIUM stgmAdpDev;
  200. FORMATETC fmteAdpDev = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_DISPLAY_DEVICE),
  201. (DVTARGETDEVICE FAR *) NULL,
  202. DVASPECT_CONTENT,
  203. -1,
  204. TYMED_HGLOBAL};
  205. hres = g_lpdoTarget->GetData(&fmteAdpDev, &stgmAdpDev);
  206. if (SUCCEEDED(hres) && stgmAdpDev.hGlobal)
  207. {
  208. LPWSTR pwDisplayDevice = (LPWSTR)GlobalLock(stgmAdpDev.hGlobal);
  209. LPTSTR pBuffer = NULL;
  210. #ifdef UNICODE
  211. pBuffer = pwDisplayDevice;
  212. #else // UNICODE
  213. CHAR szBuffer[MAX_PATH];
  214. if(WideCharToMultiByte(CP_ACP, 0, pwDisplayDevice, lstrlenW(pwDisplayDevice) + 1,
  215. szBuffer, MAX_PATH, NULL, NULL))
  216. pBuffer = szBuffer;
  217. #endif // UNICODE
  218. if(NULL != pBuffer)
  219. {
  220. DISPLAY_DEVICE ddMon;
  221. BOOL bSuccess = FALSE;
  222. int cMonitors = 0;
  223. do
  224. {
  225. ZeroMemory(&ddMon, sizeof(ddMon));
  226. ddMon.cb = sizeof(DISPLAY_DEVICE);
  227. bSuccess = EnumDisplayDevices(pBuffer, cMonitors, &ddMon, 0);
  228. if (bSuccess)
  229. {
  230. ++cMonitors;
  231. if (ddMon.StateFlags & DISPLAY_DEVICE_ATTACHED)
  232. {
  233. if(0 == m_cMonitors)
  234. SendDlgItemMessage(m_hDlg, IDC_MONITORDESC, WM_SETTEXT, 0, (LPARAM)ddMon.DeviceString);
  235. int nNewItem = ListBox_AddString(m_hMonitorsList, (LPTSTR)ddMon.DeviceString);
  236. if(nNewItem >= 0)
  237. {
  238. ++m_cMonitors;
  239. ListBox_SetItemData(m_hMonitorsList, nNewItem, NULL);
  240. if(bDevInstAdapter)
  241. SaveMonitorInstancePath(devInstAdapter, ddMon.DeviceID, nNewItem);
  242. }
  243. }
  244. }
  245. }
  246. while (bSuccess);
  247. }
  248. GlobalUnlock(stgmAdpDev.hGlobal);
  249. ReleaseStgMedium(&stgmAdpDev);
  250. }
  251. if(m_cMonitors <= 0)
  252. {
  253. TCHAR szDefaultMonitor[MAX_PATH];
  254. LoadString(g_hInst, IDS_DEFAULT_MONITOR, szDefaultMonitor, ARRAYSIZE(szDefaultMonitor));
  255. SendDlgItemMessage(m_hDlg, IDC_MONITORDESC, WM_SETTEXT, 0, (LPARAM)szDefaultMonitor);
  256. EnableWindow(GetDlgItem(m_hDlg, IDC_PROPERTIES), FALSE);
  257. }
  258. else if(m_cMonitors == 1)
  259. {
  260. BOOL bEnable = ((ListBox_GetCount(m_hMonitorsList) >= 1) &&
  261. (NULL != (LPTSTR)ListBox_GetItemData(m_hMonitorsList, 0)));
  262. EnableWindow(GetDlgItem(m_hDlg, IDC_PROPERTIES), bEnable);
  263. }
  264. else
  265. {
  266. ListBox_SetCurSel(m_hMonitorsList, 0);
  267. OnSelMonitorChanged();
  268. }
  269. ShowWindow(((m_cMonitors <= 1) ? m_hMonitorsList : hSingleMonitor), SW_HIDE);
  270. //
  271. // Init the pruning mode check box
  272. //
  273. InitPruningMode();
  274. m_bOnCancelIsPruningOn = m_bIsPruningOn;
  275. //
  276. // Save the current mode - in case the user cancels the p. sheet
  277. //
  278. m_lpdmOnCancel = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext);
  279. }
  280. void CMonitorPage::OnDestroy()
  281. {
  282. //ASSERT(NULL != m_hMonitorsList);
  283. int cMonitors = ListBox_GetCount(m_hMonitorsList);
  284. for(int nMonitor = 0; nMonitor < cMonitors; ++nMonitor)
  285. {
  286. LPTSTR pMonitorInstancePath = (LPTSTR)ListBox_GetItemData(m_hMonitorsList, nMonitor);
  287. if(NULL != pMonitorInstancePath)
  288. LocalFree(pMonitorInstancePath);
  289. }
  290. }
  291. void CMonitorPage::SaveMonitorInstancePath(DEVINST devInstAdapter, LPCTSTR pMonitorID, int nNewItem)
  292. {
  293. //ASSERT(NULL != m_hMonitorsList);
  294. DEVINST devInstChild, devInstPrevChild;
  295. TCHAR szBuff[256]; // buffer used to concatenate: HARDWAREID, "\" and DRIVER
  296. // this is what EnumDisplayDevice returns in DeviceID in case of a monitor
  297. ULONG lenBuff; // size of the buffer, in bytes
  298. if (CM_Get_Child(&devInstChild, devInstAdapter, 0) != CR_SUCCESS)
  299. return;
  300. do
  301. {
  302. devInstPrevChild = devInstChild;
  303. //CM_DRP_HARDWAREID
  304. lenBuff = ARRAYSIZE(szBuff) - 2 ; // make sure we have place to append "\"
  305. if (CM_Get_DevNode_Registry_Property(devInstChild,
  306. CM_DRP_HARDWAREID,
  307. NULL,
  308. szBuff,
  309. &lenBuff,
  310. 0) != CR_SUCCESS)
  311. continue;
  312. // "\"
  313. lstrcat(szBuff, TEXT("\\"));
  314. //CM_DRP_DRIVER
  315. lenBuff = sizeof(szBuff) - lstrlen(szBuff) * sizeof(TCHAR);
  316. if (CM_Get_DevNode_Registry_Property(devInstChild,
  317. CM_DRP_DRIVER,
  318. NULL,
  319. szBuff + lstrlen(szBuff),
  320. &lenBuff,
  321. 0) != CR_SUCCESS)
  322. continue;
  323. if (lstrcmpi(szBuff, pMonitorID) == 0)
  324. {
  325. LPTSTR pMonitorInstancePath = (LPTSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(TCHAR));
  326. if((NULL != pMonitorInstancePath) &&
  327. (CM_Get_Device_ID(devInstChild, pMonitorInstancePath, MAX_PATH, 0) == CR_SUCCESS))
  328. ListBox_SetItemData(m_hMonitorsList, nNewItem, (LPARAM)pMonitorInstancePath);
  329. break;
  330. }
  331. }
  332. while(CM_Get_Sibling(&devInstChild, devInstPrevChild, 0) == CR_SUCCESS);
  333. }
  334. void CMonitorPage::OnSelMonitorChanged()
  335. {
  336. //ASSERT(NULL != m_hMonitorsList);
  337. //ASSERT(NULL != m_hDlg);
  338. //
  339. // Enable / Disable the Properties button
  340. //
  341. BOOL bEnable = FALSE;
  342. if(ListBox_GetCount(m_hMonitorsList) >= 1)
  343. {
  344. int nCurSel = ListBox_GetCurSel(m_hMonitorsList);
  345. if(nCurSel >= 0)
  346. bEnable = (NULL != (LPTSTR)ListBox_GetItemData(m_hMonitorsList, nCurSel));
  347. }
  348. EnableWindow(GetDlgItem(m_hDlg, IDC_PROPERTIES), bEnable);
  349. }
  350. void CMonitorPage::OnProperties()
  351. {
  352. int nSelMonitor;
  353. if(m_cMonitors <= 0)
  354. nSelMonitor = -1;
  355. else if(m_cMonitors == 1)
  356. nSelMonitor = ((ListBox_GetCount(m_hMonitorsList) >= 1) ? 0 : -1);
  357. else
  358. nSelMonitor = ListBox_GetCurSel(m_hMonitorsList);
  359. if(nSelMonitor < 0)
  360. return;
  361. //ASSERT(nSelMonitor < ListBox_GetCount(m_hMonitorsList));
  362. LPTSTR pMonitorInstancePath = (LPTSTR)ListBox_GetItemData(m_hMonitorsList, nSelMonitor);
  363. if(NULL != pMonitorInstancePath)
  364. {
  365. HINSTANCE hinstDevMgr = LoadLibrary(TEXT("DEVMGR.DLL"));
  366. if (hinstDevMgr)
  367. {
  368. DEVPROPERTIES pfnDevProp = NULL;
  369. #ifdef UNICODE
  370. pfnDevProp = (DEVPROPERTIES)GetProcAddress(hinstDevMgr, "DevicePropertiesW");
  371. #else // UNICODE
  372. pfnDevProp = (DEVPROPERTIES)GetProcAddress(hinstDevMgr, "DevicePropertiesA");
  373. #endif // UNICODE
  374. if (pfnDevProp)
  375. {
  376. //Display the property sheets for this device.
  377. (*pfnDevProp)(m_hDlg, NULL, pMonitorInstancePath, FALSE);
  378. }
  379. FreeLibrary(hinstDevMgr);
  380. }
  381. }
  382. }
  383. BOOL CMonitorPage::OnSetActive()
  384. {
  385. LPDEVMODEW lpdm;
  386. DWORD item;
  387. LPDEVMODEW lpdmCurrent, lpdmPrevious;
  388. LPDEVMODEW lpdmTmp;
  389. DWORD i = 0;
  390. TCHAR achFre[50];
  391. TCHAR achText[80];
  392. DWORD pos;
  393. HWND hFreq;
  394. InitPruningMode();
  395. //
  396. // Build the list of refresh rates for the currently selected mode.
  397. //
  398. lpdmCurrent = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext);
  399. hFreq = GetDlgItem(m_hDlg, IDC_MONSET_FREQ);
  400. if (lpdmCurrent == NULL)
  401. return -1;
  402. if (m_lpdmPrevious)
  403. {
  404. if (lpdmCurrent->dmBitsPerPel != m_lpdmPrevious->dmBitsPerPel ||
  405. lpdmCurrent->dmPelsWidth != m_lpdmPrevious->dmPelsWidth ||
  406. lpdmCurrent->dmPelsHeight != m_lpdmPrevious->dmPelsHeight)
  407. {
  408. ComboBox_ResetContent(hFreq);
  409. }
  410. }
  411. m_lpdmPrevious = lpdmCurrent;
  412. while (lpdm = DeskInterface.lpfnEnumAllModes(DeskInterface.pContext, i++)) {
  413. //
  414. // Only show refresh frequencies for current modes.
  415. //
  416. if ((lpdmCurrent->dmBitsPerPel != lpdm->dmBitsPerPel) ||
  417. (lpdmCurrent->dmPelsWidth != lpdm->dmPelsWidth) ||
  418. (lpdmCurrent->dmPelsHeight != lpdm->dmPelsHeight))
  419. continue;
  420. //
  421. // convert bit count to number of colors and make it a string
  422. //
  423. // WARNING should this be 0 ?
  424. if (lpdm->dmDisplayFrequency == 1) {
  425. LoadString(g_hInst, IDS_DEFFREQ, achText, ARRAYSIZE(achText));
  426. }
  427. else {
  428. DWORD idFreq = IDS_FREQ;
  429. if (lpdm->dmDisplayFrequency < 50)
  430. {
  431. idFreq = IDS_INTERLACED;
  432. }
  433. LoadString(g_hInst, idFreq, achFre, ARRAYSIZE(achFre));
  434. wsprintf(achText, TEXT("%d %s"), lpdm->dmDisplayFrequency, achFre);
  435. }
  436. //
  437. // Insert the string in the right place
  438. //
  439. pos = 0;
  440. while (lpdmTmp = (LPDEVMODEW) ComboBox_GetItemData(hFreq, pos)) {
  441. if ((ULONG_PTR)lpdmTmp != CB_ERR) {
  442. if (lpdmTmp->dmDisplayFrequency == lpdm->dmDisplayFrequency) {
  443. break;
  444. }
  445. if (lpdmTmp->dmDisplayFrequency < lpdm->dmDisplayFrequency) {
  446. pos++;
  447. continue;
  448. }
  449. }
  450. //
  451. // Insert it here
  452. //
  453. item = ComboBox_InsertString(hFreq, pos, achText);
  454. ComboBox_SetItemData(hFreq, item, lpdm);
  455. break;
  456. }
  457. }
  458. //
  459. // Finally, set the right selection
  460. //
  461. pos = 0;
  462. while (lpdmTmp = (LPDEVMODEW) ComboBox_GetItemData(hFreq, pos)) {
  463. if ((ULONG_PTR)lpdmTmp == CB_ERR) {
  464. FmtMessageBox(m_hDlg,
  465. MB_OK | MB_ICONINFORMATION,
  466. IDS_BAD_REFRESH,
  467. IDS_BAD_REFRESH);
  468. return -1;
  469. }
  470. if (lpdmTmp->dmDisplayFrequency == lpdmCurrent->dmDisplayFrequency) {
  471. ComboBox_SetCurSel(hFreq, pos);
  472. break;
  473. }
  474. pos++;
  475. }
  476. return 0;
  477. }
  478. void CMonitorPage::OnFrequencyChanged()
  479. {
  480. DWORD item;
  481. HWND hFreq;
  482. LPDEVMODEW lpdmSelected = NULL, lpdmCurrent = NULL;
  483. //
  484. // Save the mode back
  485. //
  486. hFreq = GetDlgItem(m_hDlg, IDC_MONSET_FREQ);
  487. item = ComboBox_GetCurSel(hFreq);
  488. if (item == LB_ERR)
  489. return;
  490. lpdmCurrent = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext);
  491. lpdmSelected = (LPDEVMODEW) ComboBox_GetItemData(hFreq, item);
  492. if (lpdmSelected && (lpdmSelected != lpdmCurrent))
  493. DeskInterface.lpfnSetSelectedMode(DeskInterface.pContext, lpdmSelected);
  494. }
  495. void CMonitorPage::OnPruningModeChanged()
  496. {
  497. if (m_bCanBePruned && !m_bIsPruningReadOnly)
  498. {
  499. BOOL bNewIsPruningOn = (BST_UNCHECKED != IsDlgButtonChecked(m_hDlg, IDC_MONSET_PRUNNING_MODE));
  500. if((m_bIsPruningOn != 0) != bNewIsPruningOn)
  501. {
  502. m_bIsPruningOn = bNewIsPruningOn;
  503. DeskInterface.lpfnSetPruningMode(DeskInterface.pContext, m_bIsPruningOn);
  504. RefreshFrequenciesList();
  505. }
  506. }
  507. }
  508. void CMonitorPage::InitPruningMode()
  509. {
  510. m_bCanBePruned = FALSE;
  511. m_bIsPruningReadOnly = TRUE;
  512. m_bIsPruningOn = FALSE;
  513. DeskInterface.lpfnGetPruningMode(DeskInterface.pContext,
  514. &m_bCanBePruned,
  515. &m_bIsPruningReadOnly,
  516. &m_bIsPruningOn);
  517. BOOL bEnable = (m_bCanBePruned && !m_bIsPruningReadOnly);
  518. EnableWindow(GetDlgItem(m_hDlg, IDC_MONSET_PRUNNING_MODE), bEnable);
  519. EnableWindow(GetDlgItem(m_hDlg, IDC_MONSET_PRUNNING_MODE_DESC), bEnable);
  520. BOOL bChecked = (m_bCanBePruned && m_bIsPruningOn);
  521. CheckDlgButton(m_hDlg, IDC_MONSET_PRUNNING_MODE, bChecked);
  522. }
  523. void CMonitorPage::RefreshFrequenciesList()
  524. {
  525. LPDEVMODEW lpdm;
  526. DWORD item;
  527. LPDEVMODEW lpdmCurrent, lpdmPrevious;
  528. LPDEVMODEW lpdmTmp;
  529. DWORD i = 0;
  530. TCHAR achFre[50];
  531. TCHAR achText[80];
  532. DWORD pos;
  533. HWND hFreq;
  534. HWND hwndCurr = GetFocus();
  535. //
  536. // Build the list of refresh rates for the currently selected mode.
  537. //
  538. lpdmCurrent = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext);
  539. if (lpdmCurrent == NULL)
  540. return;
  541. hFreq = GetDlgItem(m_hDlg, IDC_MONSET_FREQ);
  542. ComboBox_ResetContent(hFreq);
  543. while (lpdm = DeskInterface.lpfnEnumAllModes(DeskInterface.pContext, i++))
  544. {
  545. //
  546. // Only show refresh frequencies for current modes.
  547. //
  548. if ((lpdmCurrent->dmBitsPerPel != lpdm->dmBitsPerPel) ||
  549. (lpdmCurrent->dmPelsWidth != lpdm->dmPelsWidth) ||
  550. (lpdmCurrent->dmPelsHeight != lpdm->dmPelsHeight))
  551. continue;
  552. //
  553. // convert bit count to number of colors and make it a string
  554. //
  555. // WARNING should this be 0 ?
  556. if (lpdm->dmDisplayFrequency == 1)
  557. {
  558. LoadString(g_hInst, IDS_DEFFREQ, achText, ARRAYSIZE(achText));
  559. }
  560. else
  561. {
  562. DWORD idFreq = IDS_FREQ;
  563. if (lpdm->dmDisplayFrequency < 50)
  564. {
  565. idFreq = IDS_INTERLACED;
  566. }
  567. LoadString(g_hInst, idFreq, achFre, ARRAYSIZE(achFre));
  568. wsprintf(achText, TEXT("%d %s"), lpdm->dmDisplayFrequency, achFre);
  569. }
  570. //
  571. // Insert the string in the right place
  572. //
  573. pos = 0;
  574. while (lpdmTmp = (LPDEVMODEW) ComboBox_GetItemData(hFreq, pos))
  575. {
  576. if ((ULONG_PTR)lpdmTmp != CB_ERR)
  577. {
  578. if (lpdmTmp->dmDisplayFrequency == lpdm->dmDisplayFrequency)
  579. {
  580. break;
  581. }
  582. if (lpdmTmp->dmDisplayFrequency < lpdm->dmDisplayFrequency)
  583. {
  584. pos++;
  585. continue;
  586. }
  587. }
  588. //
  589. // Insert it here
  590. //
  591. item = ComboBox_InsertString(hFreq, pos, achText);
  592. ComboBox_SetItemData(hFreq, item, lpdm);
  593. break;
  594. }
  595. }
  596. //
  597. // Finally, set the right selection
  598. //
  599. pos = 0;
  600. while (lpdmTmp = (LPDEVMODEW) ComboBox_GetItemData(hFreq, pos))
  601. {
  602. if ((ULONG_PTR)lpdmTmp == CB_ERR)
  603. {
  604. FmtMessageBox(m_hDlg,
  605. MB_OK | MB_ICONINFORMATION,
  606. IDS_BAD_REFRESH,
  607. IDS_BAD_REFRESH);
  608. break;
  609. }
  610. if (lpdmTmp->dmDisplayFrequency == lpdmCurrent->dmDisplayFrequency)
  611. {
  612. ComboBox_SetCurSel(hFreq, pos);
  613. break;
  614. }
  615. pos++;
  616. }
  617. if (hwndCurr)
  618. SetFocus(hwndCurr);
  619. return;
  620. }
  621. #ifdef DBG
  622. void CMonitorPage::AssertValid() const
  623. {
  624. //ASSERT(m_hDlg != NULL);
  625. //ASSERT(!m_bIsPruningOn || m_bCanBePruned);
  626. }
  627. #endif
  628. //---------------------------------------------------------------------------
  629. //
  630. // PropertySheeDlgProc()
  631. //
  632. // The dialog procedure for the "Monitor" property sheet page.
  633. //
  634. //---------------------------------------------------------------------------
  635. INT_PTR
  636. CALLBACK
  637. PropertySheeDlgProc(
  638. HWND hDlg,
  639. UINT uMessage,
  640. WPARAM wParam,
  641. LPARAM lParam
  642. )
  643. {
  644. NMHDR FAR *lpnm;
  645. CMonitorPage * pMonitorPage = (CMonitorPage*)GetWindowLongPtr(hDlg, DWLP_USER);
  646. switch (uMessage)
  647. {
  648. case WM_INITDIALOG:
  649. if (!g_lpdoTarget)
  650. {
  651. return FALSE;
  652. }
  653. else
  654. {
  655. //ASSERT(!pMonitorPage);
  656. pMonitorPage = new CMonitorPage(hDlg);
  657. if(!pMonitorPage)
  658. return FALSE;
  659. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pMonitorPage);
  660. pMonitorPage->OnInitDialog();
  661. }
  662. break;
  663. case WM_DESTROY:
  664. if (pMonitorPage)
  665. {
  666. pMonitorPage->OnDestroy();
  667. SetWindowLongPtr(hDlg, DWLP_USER, NULL);
  668. delete pMonitorPage;
  669. }
  670. break;
  671. case WM_COMMAND:
  672. switch (GET_WM_COMMAND_ID(wParam, lParam))
  673. {
  674. case IDC_MONSET_FREQ:
  675. switch(GET_WM_COMMAND_CMD(wParam, lParam))
  676. {
  677. case CBN_SELCHANGE:
  678. PropSheet_Changed(GetParent(hDlg), hDlg);
  679. if(pMonitorPage)
  680. pMonitorPage->OnFrequencyChanged();
  681. break;
  682. default:
  683. break;
  684. }
  685. break;
  686. case IDC_PROPERTIES:
  687. if(pMonitorPage)
  688. pMonitorPage->OnProperties();
  689. break;
  690. case IDC_MONSET_PRUNNING_MODE:
  691. PropSheet_Changed(GetParent(hDlg), hDlg);
  692. if(pMonitorPage)
  693. pMonitorPage->OnPruningModeChanged();
  694. break;
  695. case IDC_MONITORS_LIST:
  696. switch(GET_WM_COMMAND_CMD(wParam, lParam))
  697. {
  698. case LBN_SELCHANGE:
  699. if(pMonitorPage)
  700. pMonitorPage->OnSelMonitorChanged();
  701. break;
  702. default:
  703. return FALSE;
  704. }
  705. break;
  706. default:
  707. return FALSE;
  708. }
  709. break;
  710. case WM_NOTIFY:
  711. switch (((NMHDR FAR *)lParam)->code)
  712. {
  713. case PSN_SETACTIVE:
  714. return (pMonitorPage && pMonitorPage->OnSetActive());
  715. case PSN_APPLY:
  716. if(pMonitorPage)
  717. pMonitorPage->OnApply();
  718. break;
  719. case PSN_RESET:
  720. if(pMonitorPage)
  721. pMonitorPage->OnCancel();
  722. break;
  723. default:
  724. return FALSE;
  725. }
  726. break;
  727. case WM_HELP:
  728. WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
  729. TEXT("display.hlp"),
  730. HELP_WM_HELP,
  731. (DWORD_PTR)(LPTSTR)sc_MonitorHelpIds);
  732. break;
  733. case WM_CONTEXTMENU:
  734. WinHelp((HWND)wParam,
  735. TEXT("display.hlp"),
  736. HELP_CONTEXTMENU,
  737. (DWORD_PTR)(LPTSTR)sc_MonitorHelpIds);
  738. break;
  739. default:
  740. return FALSE;
  741. }
  742. return TRUE;
  743. }