diff --git a/dll/cpl/desk/desk.h b/dll/cpl/desk/desk.h index 3c479251cfe..36470ffe8a3 100644 --- a/dll/cpl/desk/desk.h +++ b/dll/cpl/desk/desk.h @@ -122,6 +122,9 @@ HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY,LPCWSTR,UINT,IDataObject*); INT_PTR CALLBACK AdvGeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +BOOL +SwitchDisplayMode(HWND hwndDlg, PWSTR DeviceName, PSETTINGS_ENTRY seInit, PSETTINGS_ENTRY seNew, OUT PLONG rc); + LONG RegLoadMUIStringW(IN HKEY hKey, IN LPCWSTR pszValue OPTIONAL, diff --git a/dll/cpl/desk/devsett.c b/dll/cpl/desk/devsett.c index dc801f4c624..d48c9493440 100644 --- a/dll/cpl/desk/devsett.c +++ b/dll/cpl/desk/devsett.c @@ -38,6 +38,10 @@ typedef struct _CDevSettings DESK_EXT_INTERFACE ExtInterface; + PDEVMODEW lpOrigDevMode; + PDEVMODEW lpCurDevMode; + PDEVMODEW * DevModes; + DWORD nDevModes; DWORD StateFlags; union @@ -285,28 +289,63 @@ PDEVMODEW DESK_EXT_CALLBACK CDevSettings_EnumAllModes(PVOID Context, DWORD Index) { - //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); - /* FIXME: Implement */ + PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + DWORD i, idx = 0; + DPRINT1("CDevSettings::EnumAllModes(%u)\n", Index); + + if (!This->DevModes) + return NULL; + + for (i = 0; i < This->nDevModes; i++) + { + /* FIXME: Add more sanity checks */ + if (!This->DevModes[i]) + continue; + + if (idx == Index) + return This->DevModes[i]; + + idx++; + } + return NULL; } PDEVMODEW DESK_EXT_CALLBACK CDevSettings_GetCurrentMode(PVOID Context) { - //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); - /* FIXME: Implement */ + PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + DPRINT1("CDevSettings::GetCurrentMode\n"); - return NULL; + return This->lpCurDevMode; } BOOL DESK_EXT_CALLBACK CDevSettings_SetCurrentMode(PVOID Context, - const DEVMODEW *pDevMode) + DEVMODEW *pDevMode) { - //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); - /* FIXME: Implement */ + PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); + DWORD i; + DPRINT1("CDevSettings::SetCurrentMode(0x%p)\n", pDevMode); + + if (!This->DevModes) + return FALSE; + + for (i = 0; i < This->nDevModes; i++) + { + /* FIXME: Add more sanity checks */ + if (!This->DevModes[i]) + continue; + + if (This->DevModes[i] == pDevMode) + { + This->lpCurDevMode = pDevMode; + return TRUE; + } + } + return FALSE; } @@ -455,7 +494,13 @@ pCDevSettings_Initialize(PCDevSettings This, PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo) { HKEY hKey; + DWORD i = 0, dwSize; + DEVMODEW devmode; + This->lpOrigDevMode = NULL; + This->lpCurDevMode = NULL; + This->DevModes = NULL; + This->nDevModes = 0; This->Flags = 0; This->StateFlags = DisplayDeviceInfo->DeviceStateFlags; DPRINT1("This->StateFlags: %x\n", This->StateFlags); @@ -498,7 +543,7 @@ pCDevSettings_Initialize(PCDevSettings This, if (hKey != NULL) { DWORD dw = 0; - DWORD dwType, dwSize; + DWORD dwType; dwSize = sizeof(dw); if (RegQueryValueEx(hKey, @@ -515,6 +560,80 @@ pCDevSettings_Initialize(PCDevSettings This, RegCloseKey(hKey); } + /* Initialize display modes */ + ZeroMemory(&devmode, sizeof(devmode)); + devmode.dmSize = (WORD)sizeof(devmode); + while (EnumDisplaySettingsExW(This->pDisplayDevice, i, &devmode, EDS_RAWMODE)) + { + dwSize = devmode.dmSize + devmode.dmDriverExtra; + PDEVMODEW pDevMode = LocalAlloc(LMEM_FIXED, dwSize); + PDEVMODEW * DevModesNew = NULL; + + if (pDevMode) + { + CopyMemory(pDevMode, + &devmode, + dwSize); + + dwSize = (This->nDevModes + 1) * sizeof(pDevMode); + DevModesNew = LocalAlloc(LMEM_FIXED, dwSize); + if (DevModesNew) + { + if (This->DevModes) + { + CopyMemory(DevModesNew, + This->DevModes, + This->nDevModes * sizeof(pDevMode)); + + LocalFree(This->DevModes); + } + + This->DevModes = DevModesNew; + This->DevModes[This->nDevModes++] = pDevMode; + } + else + { + DPRINT1("LocalAlloc failed to allocate %d bytes\n", dwSize); + return E_OUTOFMEMORY; + } + } + else + { + DPRINT1("LocalAlloc failed to allocate %d bytes\n", dwSize); + return E_OUTOFMEMORY; + } + + devmode.dmDriverExtra = 0; + i++; + } + + /* FIXME: Detect duplicated modes and mark them. + * Enumeration functions should check these marks + * and skip corresponding array entries. */ + + /* Get current display mode */ + ZeroMemory(&devmode, sizeof(devmode)); + devmode.dmSize = (WORD)sizeof(devmode); + if (EnumDisplaySettingsExW(This->pDisplayDevice, ENUM_CURRENT_SETTINGS, &devmode, 0)) + { + for (i = 0; i < This->nDevModes; i++) + { + PDEVMODEW CurMode = This->DevModes[i]; + + if (!CurMode) + continue; + + if (((CurMode->dmFields & DM_PELSWIDTH) && devmode.dmPelsWidth == CurMode->dmPelsWidth) && + ((CurMode->dmFields & DM_PELSHEIGHT) && devmode.dmPelsHeight == CurMode->dmPelsHeight) && + ((CurMode->dmFields & DM_BITSPERPEL) && devmode.dmBitsPerPel == CurMode->dmBitsPerPel) && + ((CurMode->dmFields & DM_DISPLAYFREQUENCY) && devmode.dmDisplayFrequency == CurMode->dmDisplayFrequency)) + { + This->lpOrigDevMode = This->lpCurDevMode = CurMode; + break; + } + } + } + /* Initialize the shell extension interface */ pCDevSettings_InitializeExtInterface(This); @@ -524,6 +643,15 @@ pCDevSettings_Initialize(PCDevSettings This, static VOID pCDevSettings_Free(PCDevSettings This) { + This->lpOrigDevMode = NULL; + This->lpCurDevMode = NULL; + while (This->nDevModes) + { + LocalFree(This->DevModes[--This->nDevModes]); + } + LocalFree(This->DevModes); + This->DevModes = NULL; + pCDevSettings_FreeString(&This->pDisplayDevice); pCDevSettings_FreeString(&This->pDisplayName); pCDevSettings_FreeString(&This->pDisplayKey); @@ -942,7 +1070,38 @@ LONG WINAPI DisplaySaveSettings(PVOID pContext, HWND hwndPropSheet) { - //PCDevSettings This = impl_from_IDataObject((IDataObject *)Context); - DPRINT("DisplaySaveSettings() UNIMPLEMENTED!\n"); - return DISP_CHANGE_BADPARAM; + PCDevSettings This = impl_from_IDataObject((IDataObject *)pContext); + LONG rc = DISP_CHANGE_SUCCESSFUL; + + if (This->lpCurDevMode != This->lpOrigDevMode) + { + SETTINGS_ENTRY seOrig, seCur; + BOOL Ret; + + seOrig.dmPelsWidth = This->lpOrigDevMode->dmPelsWidth; + seOrig.dmPelsHeight = This->lpOrigDevMode->dmPelsHeight; + seOrig.dmBitsPerPel = This->lpOrigDevMode->dmBitsPerPel; + seOrig.dmDisplayFrequency = This->lpOrigDevMode->dmDisplayFrequency; + + seCur.dmPelsWidth = This->lpCurDevMode->dmPelsWidth; + seCur.dmPelsHeight = This->lpCurDevMode->dmPelsHeight; + seCur.dmBitsPerPel = This->lpCurDevMode->dmBitsPerPel; + seCur.dmDisplayFrequency = This->lpCurDevMode->dmDisplayFrequency; + + Ret = SwitchDisplayMode(hwndPropSheet, + This->pDisplayDevice, + &seOrig, + &seCur, + &rc); + + if (rc == DISP_CHANGE_SUCCESSFUL) + { + if (Ret) + This->lpOrigDevMode = This->lpCurDevMode; + else + This->lpCurDevMode = This->lpOrigDevMode; + } + } + + return rc; } diff --git a/dll/cpl/desk/settings.c b/dll/cpl/desk/settings.c index d0b8d12a06b..b161214fd69 100644 --- a/dll/cpl/desk/settings.c +++ b/dll/cpl/desk/settings.c @@ -727,27 +727,26 @@ ConfirmDlgProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam return FALSE; } -static VOID -ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData) +BOOL +SwitchDisplayMode(HWND hwndDlg, PWSTR DeviceName, PSETTINGS_ENTRY seInit, PSETTINGS_ENTRY seNew, OUT PLONG rc) { TCHAR Message[1024], Title[256]; DEVMODE devmode; - LONG rc; RtlZeroMemory(&devmode, sizeof(devmode)); devmode.dmSize = (WORD)sizeof(devmode); - devmode.dmPelsWidth = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth; - devmode.dmPelsHeight = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight; - devmode.dmBitsPerPel = pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel; - devmode.dmDisplayFrequency = pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency; + devmode.dmPelsWidth = seNew->dmPelsWidth; + devmode.dmPelsHeight = seNew->dmPelsHeight; + devmode.dmBitsPerPel = seNew->dmBitsPerPel; + devmode.dmDisplayFrequency = seNew->dmDisplayFrequency; devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; - rc = ChangeDisplaySettingsEx(pData->CurrentDisplayDevice->DeviceName, - &devmode, - NULL, - CDS_UPDATEREGISTRY, - NULL); - switch (rc) + *rc = ChangeDisplaySettingsEx(DeviceName, + &devmode, + NULL, + CDS_UPDATEREGISTRY, + NULL); + switch (*rc) { case DISP_CHANGE_SUCCESSFUL: break; @@ -756,17 +755,69 @@ ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData) LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR)); LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR)); MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION); - return; + return FALSE; case DISP_CHANGE_FAILED: default: LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR)); LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR)); MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP); - return; + return FALSE; } if (DialogBox(hApplet, MAKEINTRESOURCE(IDD_CONFIRMSETTINGS), hwndDlg, ConfirmDlgProc) == IDYES) + { + return TRUE; + } + else + { + devmode.dmPelsWidth = seInit->dmPelsWidth; + devmode.dmPelsHeight = seInit->dmPelsHeight; + devmode.dmBitsPerPel = seInit->dmBitsPerPel; + devmode.dmDisplayFrequency = seInit->dmDisplayFrequency; + + *rc = ChangeDisplaySettingsEx(DeviceName, + &devmode, + NULL, + CDS_UPDATEREGISTRY, + NULL); + switch (*rc) + { + case DISP_CHANGE_SUCCESSFUL: + return FALSE; + + case DISP_CHANGE_RESTART: + LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR)); + LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR)); + MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION); + return FALSE; + + case DISP_CHANGE_FAILED: + default: + LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR)); + LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR)); + MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP); + return FALSE; + } + } +} + +static VOID +ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData) +{ + BOOL Ret; + LONG rc; + + Ret = SwitchDisplayMode(hwndDlg, + pData->CurrentDisplayDevice->DeviceName, + &pData->CurrentDisplayDevice->InitialSettings, + pData->CurrentDisplayDevice->CurrentSettings, + &rc); + + if (rc != DISP_CHANGE_SUCCESSFUL) + return; + + if (Ret) { pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth; pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight; @@ -775,39 +826,11 @@ ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData) } else { - devmode.dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth; - devmode.dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight; - devmode.dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel; - devmode.dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency; - - rc = ChangeDisplaySettingsEx(pData->CurrentDisplayDevice->DeviceName, - &devmode, - NULL, - CDS_UPDATEREGISTRY, - NULL); - switch (rc) - { - case DISP_CHANGE_SUCCESSFUL: - pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth; - pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight; - pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel; - pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency; - UpdateDisplay(hwndDlg, pData, TRUE); - break; - - case DISP_CHANGE_RESTART: - LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR)); - LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR)); - MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION); - return; - - case DISP_CHANGE_FAILED: - default: - LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR)); - LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR)); - MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP); - return; - } + pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth; + pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight; + pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel; + pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency; + UpdateDisplay(hwndDlg, pData, TRUE); } } @@ -841,7 +864,26 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar DWORD command = HIWORD(wParam); if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED) - DisplayAdvancedSettings(hwndDlg, pData->CurrentDisplayDevice); + { + if (DisplayAdvancedSettings(hwndDlg, pData->CurrentDisplayDevice)) + { + DEVMODE devmode; + ZeroMemory(&devmode, sizeof(devmode)); + devmode.dmSize = (WORD)sizeof(devmode); + if (EnumDisplaySettingsExW(pData->CurrentDisplayDevice->DeviceName, ENUM_CURRENT_SETTINGS, &devmode, 0)) + { + pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = devmode.dmPelsWidth; + pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = devmode.dmPelsHeight; + pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = devmode.dmBitsPerPel; + pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency = devmode.dmDisplayFrequency; + pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth; + pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight; + pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel; + pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency; + UpdateDisplay(hwndDlg, pData, TRUE); + } + } + } else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE) OnBPPChanged(hwndDlg, pData); break; diff --git a/sdk/include/reactos/dll/desk/deskcplx.h b/sdk/include/reactos/dll/desk/deskcplx.h index 8647191a966..1b773449121 100644 --- a/sdk/include/reactos/dll/desk/deskcplx.h +++ b/sdk/include/reactos/dll/desk/deskcplx.h @@ -15,7 +15,7 @@ typedef PDEVMODEW (DESK_EXT_CALLBACK *PDESK_EXT_ENUMALLMODES)(PVOID Context, DWORD Index); typedef PDEVMODEW (DESK_EXT_CALLBACK *PDESK_EXT_GETCURRENTMODE)(PVOID Context); -typedef BOOL (DESK_EXT_CALLBACK *PDESK_EXT_SETCURRENTMODE)(PVOID Context, const DEVMODEW *pDevMode); +typedef BOOL (DESK_EXT_CALLBACK *PDESK_EXT_SETCURRENTMODE)(PVOID Context, DEVMODEW *pDevMode); typedef VOID (DESK_EXT_CALLBACK *PDESK_EXT_GETPRUNINGMODE)(PVOID Context, PBOOL pbModesPruned, PBOOL pbKeyIsReadOnly, PBOOL pbPruningOn); typedef VOID (DESK_EXT_CALLBACK *PDESK_EXT_SETPRUNINGMODE)(PVOID Context, BOOL PruningOn);