/****************************************************************************** Source File: deskadp.cpp Main code for the advanced desktop adapter page Copyright (c) 1997-1998 by Microsoft Corporation Change History: 12-16-97 AndreVa - Created It ******************************************************************************/ #include "deskadp.h" #define DECL_CRTFREE #include #include "shfusion.h" DWORD ApplyNowThd(LPVOID lpThreadParameter); // // The function DevicePropertiesW() is implemented in DevMgr.dll; Since we don't have a devmgr.h, we // explicitly declare it here. // typedef int (WINAPI *DEVPROPERTIESW)( HWND hwndParent, LPCTSTR MachineName, LPCTSTR DeviceID, BOOL ShowDeviceTree ); // OLE-Registry magic number // 42071712-76d4-11d1-8b24-00a0c9068ff3 // GUID g_CLSID_CplExt = { 0x42071712, 0x76d4, 0x11d1, { 0x8b, 0x24, 0x00, 0xa0, 0xc9, 0x06, 0x8f, 0xf3} }; DESK_EXTENSION_INTERFACE DeskInterface; static const DWORD sc_AdapterHelpIds[] = { ID_ADP_ADPINFGRP, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_AI1, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_AI2, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_AI3, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_AI4, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_AI5, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_CHIP, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_DAC, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_MEM, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_ADP_STRING, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_BIOS_INFO, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_INFO, ID_ADP_ADPGRP, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_TYPE, IDI_ADAPTER, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_TYPE, ID_ADP_ADAPTOR, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_ADAPTER_TYPE, IDC_LIST_ALL, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_LIST_MODES, IDC_PROPERTIES, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_PROPERTIES, 0, 0 }; static const DWORD sc_ListAllHelpIds[] = { ID_MODE_LIST, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_LISTMODE_DIALOGBOX, ID_MODE_LISTGRP, IDH_DISPLAY_SETTINGS_ADVANCED_ADAPTER_LISTMODE_DIALOGBOX, 0, 0 }; /////////////////////////////////////////////////////////////////////////////// // // Messagebox wrapper // /////////////////////////////////////////////////////////////////////////////// int FmtMessageBox( HWND hwnd, UINT fuStyle, DWORD dwTitleID, DWORD dwTextID) { TCHAR Title[256]; TCHAR Text[1500]; LoadString(g_hInst, dwTextID, Text, ARRAYSIZE(Text)); LoadString(g_hInst, dwTitleID, Title, ARRAYSIZE(Title)); return (MessageBox(hwnd, Text, Title, fuStyle)); } /////////////////////////////////////////////////////////////////////////////// // // Main dialog box Windows Proc // /////////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK ListAllModesProc( HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam ) { LPDEVMODEW lpdm, lpdmCur; HWND hList; DWORD i; LRESULT item; switch (uMessage) { case WM_INITDIALOG: // // Save the lParam - we will store the new mode here // SetWindowLongPtr(hDlg, DWLP_USER, lParam); lpdmCur = *((LPDEVMODEW *)lParam); Assert (lpdmCur != NULL); // // Build the list of modes to display // i = 0; hList = GetDlgItem(hDlg, ID_MODE_LIST); while (lpdm = DeskInterface.lpfnEnumAllModes(DeskInterface.pContext, i)) { TCHAR achFreData[50]; TCHAR achFre[50]; TCHAR achStr[80]; TCHAR achText[120]; DWORD idColor; DWORD idFreq; // // convert bit count to number of colors and make it a string // switch (lpdm->dmBitsPerPel) { case 32: idColor = IDS_MODE_TRUECOLOR32; break; case 24: idColor = IDS_MODE_TRUECOLOR24; break; case 16: idColor = IDS_MODE_16BIT_COLOR; break; case 15: idColor = IDS_MODE_15BIT_COLOR; break; case 8: idColor = IDS_MODE_8BIT_COLOR; break; case 4: idColor = IDS_MODE_4BIT_COLOR; break; default: FmtMessageBox(hDlg, MB_OK | MB_ICONINFORMATION, IDS_BAD_COLOR, IDS_BAD_COLOR); EndDialog(hDlg, -1); break; } if (lpdm->dmDisplayFrequency == 0) { FmtMessageBox(hDlg, MB_OK | MB_ICONINFORMATION, IDS_BAD_REFRESH, IDS_BAD_REFRESH); EndDialog(hDlg, -1); break; } else if (lpdm->dmDisplayFrequency == 1) { LoadString(g_hInst, IDS_MODE_REFRESH_DEF, achFre, ARRAYSIZE(achFre)); } else { if (lpdm->dmDisplayFrequency <= 50) idFreq = IDS_MODE_REFRESH_INT; else idFreq = IDS_MODE_REFRESH_HZ; LoadString(g_hInst, idFreq, achFreData, ARRAYSIZE(achFreData)); wsprintf(achFre, achFreData, lpdm->dmDisplayFrequency); } LoadString(g_hInst, idColor, achStr, ARRAYSIZE(achStr)); wsprintf(achText, achStr, lpdm->dmPelsWidth, lpdm->dmPelsHeight, achFre); item = ListBox_AddString(hList, achText); if (lpdm == lpdmCur) ListBox_SetCurSel(hList, item); ListBox_SetItemData(hList, item, lpdm); i++; } // // If no modes are available, put up a popup and exit. // if (i == 0) { EndDialog(hDlg, -1); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_MODE_LIST: if (HIWORD(wParam) != LBN_DBLCLK) { return FALSE; } // // fall through, as DBLCLK means select. // case IDOK: // // Save the mode back // item = SendDlgItemMessage(hDlg, ID_MODE_LIST, LB_GETCURSEL, 0, 0); if ((item != LB_ERR) && (lpdm = (LPDEVMODEW) SendDlgItemMessage(hDlg, ID_MODE_LIST, LB_GETITEMDATA, item, 0))) { *((LPDEVMODEW *)GetWindowLongPtr(hDlg, DWLP_USER)) = lpdm; EndDialog(hDlg, TRUE); break; } // // fall through // case IDCANCEL: EndDialog(hDlg, FALSE); break; default: return FALSE; } break; case WM_HELP: WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP, (DWORD_PTR)(LPTSTR)sc_ListAllHelpIds); break; case WM_CONTEXTMENU: WinHelp((HWND)wParam, TEXT("display.hlp"), HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)sc_ListAllHelpIds); break; default: return FALSE; } return TRUE; } void Adaptor_OnApply(HWND hDlg) { HINSTANCE hInst; LPDISPLAY_SAVE_SETTINGS lpfnDisplaySaveSettings = NULL; long lRet = PSNRET_INVALID_NOCHANGEPAGE; hInst = LoadLibrary(TEXT("desk.cpl")); if (hInst) { lpfnDisplaySaveSettings = (LPDISPLAY_SAVE_SETTINGS) GetProcAddress(hInst, "DisplaySaveSettings"); if (lpfnDisplaySaveSettings) { LONG lSave = lpfnDisplaySaveSettings(DeskInterface.pContext, hDlg); if (lSave == DISP_CHANGE_SUCCESSFUL) { // // Save the current mode - to restore it in case the user cancels the p. sheet // LPDEVMODEW lpdmOnCancel = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext); SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)lpdmOnCancel); lRet = PSNRET_NOERROR; } else if (lSave == DISP_CHANGE_RESTART) { // // User wants to reboot system. // PropSheet_RestartWindows(GetParent(hDlg)); lRet = PSNRET_NOERROR; } } FreeLibrary(hInst); } SetWindowLongPtr(hDlg, DWLP_MSGRESULT, lRet); } void Adaptor_OnInitDialog(HWND hDlg) { Assert (DeskInterface.cbSize == 0); // // Get the CPL extension interfaces from IDataObject. // FORMATETC fmte = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_INTERFACE), (DVTARGETDEVICE FAR *) NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM stgm; HRESULT hres = g_lpdoTarget->GetData(&fmte, &stgm); if (SUCCEEDED(hres) && stgm.hGlobal) { // // The storage now contains Display device path (\\.\DisplayX) in UNICODE. // PDESK_EXTENSION_INTERFACE pInterface = (PDESK_EXTENSION_INTERFACE) GlobalLock(stgm.hGlobal); if (pInterface != NULL) { RtlCopyMemory(&DeskInterface, pInterface, min(pInterface->cbSize, sizeof(DESK_EXTENSION_INTERFACE))); GlobalUnlock(stgm.hGlobal); SendDlgItemMessageW(hDlg, ID_ADP_CHIP, WM_SETTEXT, 0, (LPARAM)&(DeskInterface.Info.ChipType[0])); SendDlgItemMessageW(hDlg, ID_ADP_DAC, WM_SETTEXT, 0, (LPARAM)&(DeskInterface.Info.DACType[0])); SendDlgItemMessageW(hDlg, ID_ADP_MEM, WM_SETTEXT, 0, (LPARAM)&(DeskInterface.Info.MemSize[0])); SendDlgItemMessageW(hDlg, ID_ADP_ADP_STRING, WM_SETTEXT, 0, (LPARAM)&(DeskInterface.Info.AdapString[0])); SendDlgItemMessageW(hDlg, ID_ADP_BIOS_INFO, WM_SETTEXT, 0, (LPARAM)&(DeskInterface.Info.BiosString[0])); // // Save the initial selected mode - to restore it in case the user cancels the p. sheet // LPDEVMODEW lpdmOnCancel = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext); SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)lpdmOnCancel); } ReleaseStgMedium(&stgm); } // // Get device description from IDataObject. // LPWSTR pDeviceDescription; FORMATETC fmte2 = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_DISPLAY_NAME), (DVTARGETDEVICE FAR *) NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; hres = g_lpdoTarget->GetData(&fmte2, &stgm); if (SUCCEEDED(hres) && stgm.hGlobal) { pDeviceDescription = (LPWSTR) GlobalLock(stgm.hGlobal); SendDlgItemMessageW(hDlg, ID_ADP_ADAPTOR, WM_SETTEXT, 0, (LPARAM)pDeviceDescription); GlobalUnlock(stgm.hGlobal); ReleaseStgMedium(&stgm); } // // Enable/disable the properties button // BOOL bEnable = FALSE; LPWSTR pwDeviceID = NULL; FORMATETC fmte3 = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_DISPLAY_ID), (DVTARGETDEVICE FAR *)NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; hres = g_lpdoTarget->GetData(&fmte3, &stgm); if (SUCCEEDED(hres) && stgm.hGlobal) { pwDeviceID = (LPWSTR)GlobalLock(stgm.hGlobal); bEnable = ((pwDeviceID != NULL) && (*pwDeviceID != L'\0')); GlobalUnlock(stgm.hGlobal); ReleaseStgMedium(&stgm); } HWND hPropButton = GetDlgItem(hDlg, IDC_PROPERTIES); if (hPropButton != NULL) EnableWindow(hPropButton, bEnable); } void Adaptor_OnCancel(HWND hDlg) { // // Restore initial mode // LPDEVMODEW lpdmOnCancel = (LPDEVMODEW) GetWindowLongPtr(hDlg, DWLP_USER); DeskInterface.lpfnSetSelectedMode(DeskInterface.pContext, lpdmOnCancel); } void Adaptor_OnListAllModes(HWND hDlg) { LPDEVMODEW lpdmBefore, lpdmAfter; lpdmAfter = lpdmBefore = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext); if (DialogBoxParam(g_hInst, MAKEINTRESOURCE(DLG_SET_MODE_LIST), hDlg, ListAllModesProc, (LPARAM) &lpdmAfter) == 1 && lpdmAfter && (lpdmAfter != lpdmBefore)) { // // If the user selected a new setting, tell the property sheet // we have outstanding changes. This will enable the Apply button. // PropSheet_Changed(GetParent(hDlg), hDlg); DeskInterface.lpfnSetSelectedMode(DeskInterface.pContext, lpdmAfter); } } void Adaptor_OnProperties(HWND hDlg) { // Invoke the device manager property sheets to show the properties of the // given hardware. LPWSTR pwDeviceID; HRESULT hres; STGMEDIUM stgm; FORMATETC fmte2 = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_DISPLAY_ID), (DVTARGETDEVICE FAR *) NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; hres = g_lpdoTarget->GetData(&fmte2, &stgm); if (SUCCEEDED(hres) && stgm.hGlobal) { pwDeviceID = (LPWSTR) GlobalLock(stgm.hGlobal); HINSTANCE hinstDevMgr = LoadLibrary(TEXT("DEVMGR.DLL")); if (hinstDevMgr) { DEVPROPERTIESW pfnDevPropW = (DEVPROPERTIESW)GetProcAddress(hinstDevMgr, "DevicePropertiesW"); if (pfnDevPropW) { //Display the property sheets for this device. (*pfnDevPropW)(hDlg, NULL, pwDeviceID, FALSE); } FreeLibrary(hinstDevMgr); } GlobalUnlock(stgm.hGlobal); ReleaseStgMedium(&stgm); } } #if TEST_MODE void Adaptor_OnTestMode(HWND hDlg) { // // Warn the user // if (FmtMessageBox(hDlg, MB_OKCANCEL | MB_ICONINFORMATION, IDS_TEST_MODE, IDS_TEST_WARNING) == IDCANCEL) { return; } // // The user wants to test his new selection. We need to // create a new desktop with the selected resolution, switch // to it, and put up a dialog box so he can see if it works with // his hardware. // // All this needs to be done in a separate thread since you can't // switch a thread with open windows to a new desktop. // // // Create the test thread. It will do the work of creating the desktop // // // Get device name from IDataObject. // LPWSTR pDeviceName = NULL; FORMATETC fmte = {(CLIPFORMAT)RegisterClipboardFormat(DESKCPLEXT_DISPLAY_DEVICE), (DVTARGETDEVICE FAR *) NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM stgm; HRESULT hres = g_lpdoTarget->GetData(&fmte, &stgm); if (SUCCEEDED(hres) && stgm.hGlobal) { // // The storage now contains Display device path (\\.\DisplayX) in UNICODE. // pDeviceName = (LPWSTR) GlobalLock(stgm.hGlobal); } desktopParam.lpdevmode = DeskInterface.lpfnGetSelectedMode(DeskInterface.pContext); desktopParam.pwszDevice = pDeviceName; hThread = CreateThread(NULL, 4096, ApplyNowThd, (LPVOID) (&desktopParam), SYNCHRONIZE | THREAD_QUERY_INFORMATION, &idThread); WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, &bTest); // // clean up memory // if (pDeviceName) { GlobalUnlock(stgm.hGlobal); ReleaseStgMedium(&stgm); } CloseHandle(hThread); if (!bTest) { FmtMessageBox(hDlg, MB_ICONEXCLAMATION | MB_OK, IDS_TEST_MODE, IDS_TEST_FAILED); } SetForegroundWindow(hDlg); } #endif //--------------------------------------------------------------------------- // // PropertySheeDlgProc() // // The dialog procedure for the "Adapter" property sheet page. // //--------------------------------------------------------------------------- INT_PTR CALLBACK PropertySheeDlgProc( HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam ) { switch (uMessage) { case WM_INITDIALOG: RtlZeroMemory(&DeskInterface, sizeof(DESK_EXTENSION_INTERFACE)); if (!g_lpdoTarget) { return FALSE; } else { Adaptor_OnInitDialog(hDlg); } break; case WM_COMMAND: if (DeskInterface.cbSize > 0) { switch( LOWORD(wParam) ) { #if TEST_MODE case IDC_TEST_MODE: Adaptor_OnTestMode(hDlg); break; #endif case IDC_LIST_ALL: Adaptor_OnListAllModes(hDlg); break; case IDC_PROPERTIES: Adaptor_OnProperties(hDlg); break; default: return FALSE; } } break; case WM_NOTIFY: if (DeskInterface.cbSize > 0) { switch (((NMHDR FAR *)lParam)->code) { case PSN_APPLY: Adaptor_OnApply(hDlg); break; case PSN_RESET: Adaptor_OnCancel(hDlg); break; default: return FALSE; } } break; case WM_HELP: WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP, (DWORD_PTR)(LPTSTR)sc_AdapterHelpIds); break; case WM_CONTEXTMENU: WinHelp((HWND)wParam, TEXT("display.hlp"), HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)sc_AdapterHelpIds); break; default: return FALSE; } return TRUE; } // // This functionality has been deprectaed by the new style of testing a video // settings (apply the changes, bring up a countdown dialog to confirm). If // need to dipslay a bmp still exists, import TestDisplaySettings from desk.cpl // via LoadLibrary and GetProcAddress... // #if TEST_MODE /****************************************************************************\ * * DWORD WINAPI ApplyNowThd(LPVOID lpThreadParameter) * * Thread that gets started when the use hits the Apply Now button. * This thread creates a new desktop with the new video mode, switches to it * and then displays a dialog box asking if the display looks OK. If the * user does not respond within the time limit, then 'NO' is assumed to be * the answer. * \****************************************************************************/ DWORD ApplyNowThd(LPVOID lpThreadParameter) { PNEW_DESKTOP_PARAM lpDesktopParam = (PNEW_DESKTOP_PARAM) lpThreadParameter; HDESK hdsk = NULL; HDESK hdskDefault = NULL; BOOL bTest = FALSE; HDC hdc; // // HACK: // We need to make a USER call before calling the desktop stuff so we can // sure our threads internal data structure are associated with the default // desktop. // Otherwise USER has problems closing the desktop with our thread on it. // GetSystemMetrics(SM_CXSCREEN); // // Create the desktop // hdskDefault = GetThreadDesktop(GetCurrentThreadId()); if (hdskDefault != NULL) { hdsk = CreateDesktopW(L"Display.Cpl Desktop", lpDesktopParam->pwszDevice, lpDesktopParam->lpdevmode, 0, MAXIMUM_ALLOWED, NULL); if (hdsk != NULL) { // // use the desktop for this thread // if (SetThreadDesktop(hdsk)) { hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); if (hdc) { DrawBmp(hdc); DeleteDC(hdc); bTest = TRUE; } // // Sleep for some seconds so you have time to look at the screen. // Sleep(7000); } } // // Reset the thread to the right desktop // SetThreadDesktop(hdskDefault); SwitchDesktop(hdskDefault); // // Can only close the desktop after we have switched to the new one. // if (hdsk != NULL) CloseDesktop(hdsk); } ExitThread((DWORD) bTest); return 0; } #endif