mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
3aa5e8b897
Hide multiple monitor selection controls in this case. Otherwise, show them when multiple monitors are detected and hide the monitor preview bitmap. This fixes the focus on the resolution slider when tested in Windows XP. Also use the monitor bitmap globally, because it's used on multiple pages. CORE-17939 CORE-10606
407 lines
11 KiB
C
407 lines
11 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Display Control Panel
|
|
* FILE: dll/cpl/desk/desk.c
|
|
* PURPOSE: ReactOS Display Control Panel
|
|
*
|
|
* PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
|
|
*/
|
|
|
|
#include "desk.h"
|
|
#include <shellapi.h>
|
|
#include <cplext.h>
|
|
#include <debug.h>
|
|
|
|
#define NUM_APPLETS (1)
|
|
|
|
static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
|
|
|
|
INT_PTR CALLBACK ThemesPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
UINT CALLBACK SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
|
|
|
|
HINSTANCE hApplet = 0;
|
|
HWND hCPLWindow;
|
|
|
|
/* Applets */
|
|
APPLET Applets[NUM_APPLETS] =
|
|
{
|
|
{
|
|
IDC_DESK_ICON,
|
|
IDS_CPLNAME,
|
|
IDS_CPLDESCRIPTION,
|
|
DisplayApplet
|
|
}
|
|
};
|
|
|
|
HMENU
|
|
LoadPopupMenu(IN HINSTANCE hInstance,
|
|
IN LPCTSTR lpMenuName)
|
|
{
|
|
HMENU hMenu, hSubMenu = NULL;
|
|
|
|
hMenu = LoadMenu(hInstance,
|
|
lpMenuName);
|
|
|
|
if (hMenu != NULL)
|
|
{
|
|
hSubMenu = GetSubMenu(hMenu,
|
|
0);
|
|
if (hSubMenu != NULL &&
|
|
!RemoveMenu(hMenu,
|
|
0,
|
|
MF_BYPOSITION))
|
|
{
|
|
hSubMenu = NULL;
|
|
}
|
|
|
|
DestroyMenu(hMenu);
|
|
}
|
|
|
|
return hSubMenu;
|
|
}
|
|
|
|
static BOOL CALLBACK
|
|
DisplayAppletPropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam)
|
|
{
|
|
PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
|
|
if (ppsh != NULL && ppsh->nPages < MAX_DESK_PAGES)
|
|
{
|
|
ppsh->phpage[ppsh->nPages++] = hpage;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL
|
|
InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc, LPFNPSPCALLBACK pfnCallback)
|
|
{
|
|
HPROPSHEETPAGE hPage;
|
|
PROPSHEETPAGE psp;
|
|
|
|
if (ppsh->nPages < MAX_DESK_PAGES)
|
|
{
|
|
ZeroMemory(&psp, sizeof(psp));
|
|
psp.dwSize = sizeof(psp);
|
|
psp.dwFlags = PSP_DEFAULT;
|
|
if (pfnCallback != NULL)
|
|
psp.dwFlags |= PSP_USECALLBACK;
|
|
psp.hInstance = hApplet;
|
|
psp.pszTemplate = MAKEINTRESOURCE(idDlg);
|
|
psp.pfnDlgProc = DlgProc;
|
|
psp.pfnCallback = pfnCallback;
|
|
|
|
hPage = CreatePropertySheetPage(&psp);
|
|
if (hPage != NULL)
|
|
{
|
|
return DisplayAppletPropSheetAddPage(hPage, (LPARAM)ppsh);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static const struct
|
|
{
|
|
WORD idDlg;
|
|
DLGPROC DlgProc;
|
|
LPFNPSPCALLBACK Callback;
|
|
LPWSTR Name;
|
|
} PropPages[] =
|
|
{
|
|
/* { IDD_THEMES, ThemesPageProc, NULL, L"Themes" }, */ /* TODO: */
|
|
{ IDD_BACKGROUND, BackgroundPageProc, NULL, L"Desktop" },
|
|
{ IDD_SCREENSAVER, ScreenSaverPageProc, NULL, L"Screen Saver" },
|
|
{ IDD_APPEARANCE, AppearancePageProc, NULL, L"Appearance" },
|
|
{ IDD_SETTINGS, SettingsPageProc, SettingsPageCallbackProc, L"Settings" },
|
|
};
|
|
|
|
static int CALLBACK
|
|
PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
|
|
{
|
|
// NOTE: This callback is needed to set large icon correctly.
|
|
HICON hIcon;
|
|
switch (uMsg)
|
|
{
|
|
case PSCB_INITIALIZED:
|
|
{
|
|
hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_DESK_ICON));
|
|
SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Display Applet */
|
|
static LONG APIENTRY
|
|
DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
|
|
{
|
|
HPROPSHEETPAGE hpsp[MAX_DESK_PAGES];
|
|
PROPSHEETHEADER psh;
|
|
HPSXA hpsxa = NULL;
|
|
UINT i;
|
|
LPWSTR *argv = NULL;
|
|
LPCWSTR pwszSelectedTab = NULL;
|
|
LPCWSTR pwszFile = NULL;
|
|
LPCWSTR pwszAction = NULL;
|
|
INT nPage = 0;
|
|
BITMAP bitmap;
|
|
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
|
|
hCPLWindow = hwnd;
|
|
|
|
if (uMsg == CPL_STARTWPARMSW && lParam)
|
|
{
|
|
int argc;
|
|
int i;
|
|
|
|
nPage = _wtoi((PWSTR)lParam);
|
|
|
|
#if 0
|
|
argv = CommandLineToArgvW((LPCWSTR)lParam, &argc);
|
|
#else
|
|
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
|
#endif
|
|
|
|
if (argv && argc)
|
|
{
|
|
for (i = 0; i<argc; i++)
|
|
{
|
|
#if 0
|
|
if (argv[i][0] == L'@')
|
|
pwszSelectedTab = &argv[i][1];
|
|
#else
|
|
if (wcsncmp(argv[i], L"desk,@", 6) == 0)
|
|
pwszSelectedTab = &argv[i][6];
|
|
#endif
|
|
else if (wcsncmp(argv[i], L"/Action:", 8) == 0)
|
|
pwszAction = &argv[i][8];
|
|
else if (wcsncmp(argv[i], L"/file:", 6) == 0)
|
|
pwszFile = &argv[i][6];
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pwszAction && wcsncmp(pwszAction, L"ActivateMSTheme", 15) == 0)
|
|
{
|
|
ActivateThemeFile(pwszFile);
|
|
goto cleanup;
|
|
}
|
|
|
|
g_GlobalData.pwszFile = pwszFile;
|
|
g_GlobalData.pwszAction = pwszAction;
|
|
g_GlobalData.desktop_color = GetSysColor(COLOR_DESKTOP);
|
|
|
|
/* Initialize the monitor preview bitmap, used on multiple pages */
|
|
g_GlobalData.hMonitorBitmap = LoadBitmapW(hApplet, MAKEINTRESOURCEW(IDC_MONITOR));
|
|
if (g_GlobalData.hMonitorBitmap != NULL)
|
|
{
|
|
GetObjectW(g_GlobalData.hMonitorBitmap, sizeof(bitmap), &bitmap);
|
|
|
|
g_GlobalData.bmMonWidth = bitmap.bmWidth;
|
|
g_GlobalData.bmMonHeight = bitmap.bmHeight;
|
|
}
|
|
|
|
ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE | PSH_USEICONID;
|
|
psh.hwndParent = hCPLWindow;
|
|
psh.hInstance = hApplet;
|
|
psh.pszIcon = MAKEINTRESOURCEW(IDC_DESK_ICON);
|
|
psh.pszCaption = MAKEINTRESOURCEW(IDS_CPLNAME);
|
|
psh.nPages = 0;
|
|
psh.nStartPage = 0;
|
|
psh.phpage = hpsp;
|
|
psh.pfnCallback = PropSheetProc;
|
|
|
|
/* Allow shell extensions to replace the background page */
|
|
hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages);
|
|
|
|
for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
|
|
{
|
|
if (pwszSelectedTab && wcsicmp(pwszSelectedTab, PropPages[i].Name) == 0)
|
|
psh.nStartPage = i;
|
|
|
|
/* Override the background page if requested by a shell extension */
|
|
if (PropPages[i].idDlg == IDD_BACKGROUND && hpsxa != NULL &&
|
|
SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, DisplayAppletPropSheetAddPage, (LPARAM)&psh) != 0)
|
|
{
|
|
/* The shell extension added one or more pages to replace the background page.
|
|
Don't create the built-in page anymore! */
|
|
continue;
|
|
}
|
|
|
|
InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc, PropPages[i].Callback);
|
|
}
|
|
|
|
/* NOTE: Don't call SHAddFromPropSheetExtArray here because this applet only allows
|
|
replacing the background page but not extending the applet by more pages */
|
|
|
|
if (nPage != 0 && psh.nStartPage == 0)
|
|
psh.nStartPage = nPage;
|
|
|
|
PropertySheet(&psh);
|
|
|
|
cleanup:
|
|
DeleteObject(g_GlobalData.hMonitorBitmap);
|
|
|
|
if (hpsxa != NULL)
|
|
SHDestroyPropSheetExtArray(hpsxa);
|
|
|
|
if (argv)
|
|
LocalFree(argv);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* Control Panel Callback */
|
|
LONG CALLBACK
|
|
CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
|
|
{
|
|
UINT i = (UINT)lParam1;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case CPL_INIT:
|
|
return TRUE;
|
|
|
|
case CPL_GETCOUNT:
|
|
return NUM_APPLETS;
|
|
|
|
case CPL_INQUIRE:
|
|
if (i < NUM_APPLETS)
|
|
{
|
|
CPLINFO *CPlInfo = (CPLINFO*)lParam2;
|
|
CPlInfo->lData = 0;
|
|
CPlInfo->idIcon = Applets[i].idIcon;
|
|
CPlInfo->idName = Applets[i].idName;
|
|
CPlInfo->idInfo = Applets[i].idDescription;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case CPL_DBLCLK:
|
|
if (i < NUM_APPLETS)
|
|
Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
|
|
else
|
|
return TRUE;
|
|
break;
|
|
|
|
case CPL_STARTWPARMSW:
|
|
if (i < NUM_APPLETS)
|
|
return Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
WINAPI
|
|
InstallScreenSaverW(
|
|
IN HWND hWindow,
|
|
IN HANDLE hInstance,
|
|
IN LPCWSTR pszFile,
|
|
IN UINT nCmdShow)
|
|
{
|
|
WCHAR pszSystemDir[MAX_PATH];
|
|
WCHAR pszDrive[3];
|
|
WCHAR pszPath[MAX_PATH];
|
|
WCHAR pszFilename[MAX_PATH];
|
|
WCHAR pszExt[MAX_PATH];
|
|
LPWSTR pszOutName;
|
|
UINT uCompressionType=FILE_COMPRESSION_NONE;
|
|
DWORD dwSourceSize;
|
|
DWORD dwTargetSize;
|
|
DWORD rc;
|
|
|
|
if (!pszFile)
|
|
{
|
|
DPRINT("InstallScreenSaver() null file\n");
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return;
|
|
}
|
|
DPRINT("InstallScreenSaver() Installing screensaver %ls\n", pszFile);
|
|
|
|
rc = SetupGetFileCompressionInfoW(pszFile, &pszOutName, &dwSourceSize, &dwTargetSize, &uCompressionType);
|
|
if (ERROR_SUCCESS != rc)
|
|
{
|
|
DPRINT("InstallScreenSaver() SetupGetFileCompressionInfo failed with error 0x%lx\n", rc);
|
|
SetLastError(rc);
|
|
return;
|
|
}
|
|
if (!GetSystemDirectoryW((LPWSTR)pszSystemDir, sizeof(pszSystemDir)/sizeof(WCHAR)))
|
|
{
|
|
MyFree(pszOutName);
|
|
DPRINT("InstallScreenSaver() GetSystemDirectory failed with error 0x%lx\n", GetLastError());
|
|
return;
|
|
}
|
|
_wsplitpath(pszOutName, pszDrive, pszPath, pszFilename, pszExt);
|
|
MyFree(pszOutName);
|
|
StringCbCatW(pszSystemDir, sizeof(pszSystemDir), L"\\");
|
|
StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszFilename);
|
|
StringCbCatW(pszSystemDir, sizeof(pszSystemDir), pszExt);
|
|
rc = SetupDecompressOrCopyFileW(pszFile, pszSystemDir, &uCompressionType);
|
|
DPRINT("InstallScreenSaver() Copying to %ls, compression type %d return 0x%lx\n", pszFile, uCompressionType, rc);
|
|
}
|
|
|
|
void
|
|
WINAPI
|
|
InstallScreenSaverA(
|
|
IN HWND hWindow,
|
|
IN HANDLE hInstance,
|
|
IN LPCSTR pszFile,
|
|
IN UINT nCmdShow)
|
|
{
|
|
LPWSTR lpwString;
|
|
|
|
if (!pszFile)
|
|
{
|
|
DPRINT("InstallScreenSaver() null file\n");
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return;
|
|
}
|
|
DPRINT("InstallScreenSaver() Install from file %s\n", pszFile);
|
|
lpwString = pSetupMultiByteToUnicode(pszFile, 0);
|
|
if (!lpwString)
|
|
{
|
|
DPRINT("InstallScreenSaver() not enough memory to convert string to unicode\n");
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return;
|
|
}
|
|
InstallScreenSaverW(hWindow, hInstance, lpwString, nCmdShow);
|
|
MyFree(lpwString);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpvReserved);
|
|
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
RegisterPreviewControl(hInstDLL);
|
|
// case DLL_THREAD_ATTACH:
|
|
hApplet = hInstDLL;
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
UnregisterPreviewControl(hInstDLL);
|
|
CoUninitialize();
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|