* Sync up to trunk head (r60691).
[reactos.git] / dll / cpl / desk / desk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Display Control Panel
4 * FILE: dll/cpl/desk/desk.c
5 * PURPOSE: ReactOS Display Control Panel
6 *
7 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
8 */
9
10 #include "desk.h"
11
12 #define NUM_APPLETS (1)
13
14 static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam);
15
16 INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
17 INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
18 INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
19 INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
20 UINT CALLBACK SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
21
22 HINSTANCE hApplet = 0;
23 HWND hCPLWindow;
24
25 /* Applets */
26 APPLET Applets[NUM_APPLETS] =
27 {
28 {
29 IDC_DESK_ICON,
30 IDS_CPLNAME,
31 IDS_CPLDESCRIPTION,
32 DisplayApplet
33 }
34 };
35
36 HMENU
37 LoadPopupMenu(IN HINSTANCE hInstance,
38 IN LPCTSTR lpMenuName)
39 {
40 HMENU hMenu, hSubMenu = NULL;
41
42 hMenu = LoadMenu(hInstance,
43 lpMenuName);
44
45 if (hMenu != NULL)
46 {
47 hSubMenu = GetSubMenu(hMenu,
48 0);
49 if (hSubMenu != NULL &&
50 !RemoveMenu(hMenu,
51 0,
52 MF_BYPOSITION))
53 {
54 hSubMenu = NULL;
55 }
56
57 DestroyMenu(hMenu);
58 }
59
60 return hSubMenu;
61 }
62
63 static BOOL CALLBACK
64 PropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam)
65 {
66 PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam;
67 if (ppsh != NULL && ppsh->nPages < MAX_DESK_PAGES)
68 {
69 ppsh->phpage[ppsh->nPages++] = hpage;
70 return TRUE;
71 }
72
73 return FALSE;
74 }
75
76 static BOOL
77 InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc, LPFNPSPCALLBACK pfnCallback)
78 {
79 HPROPSHEETPAGE hPage;
80 PROPSHEETPAGE psp;
81
82 if (ppsh->nPages < MAX_DESK_PAGES)
83 {
84 ZeroMemory(&psp, sizeof(psp));
85 psp.dwSize = sizeof(psp);
86 psp.dwFlags = PSP_DEFAULT;
87 if (pfnCallback != NULL)
88 psp.dwFlags |= PSP_USECALLBACK;
89 psp.hInstance = hApplet;
90 psp.pszTemplate = MAKEINTRESOURCE(idDlg);
91 psp.pfnDlgProc = DlgProc;
92 psp.pfnCallback = pfnCallback;
93
94 hPage = CreatePropertySheetPage(&psp);
95 if (hPage != NULL)
96 {
97 return PropSheetAddPage(hPage, (LPARAM)ppsh);
98 }
99 }
100
101 return FALSE;
102 }
103
104 static const struct
105 {
106 WORD idDlg;
107 DLGPROC DlgProc;
108 LPFNPSPCALLBACK Callback;
109 } PropPages[] =
110 {
111 { IDD_BACKGROUND, BackgroundPageProc, NULL },
112 { IDD_SCREENSAVER, ScreenSaverPageProc, NULL },
113 { IDD_APPEARANCE, AppearancePageProc, NULL },
114 { IDD_SETTINGS, SettingsPageProc, SettingsPageCallbackProc },
115 };
116
117 /* Display Applet */
118 static LONG APIENTRY
119 DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
120 {
121 HPROPSHEETPAGE hpsp[MAX_DESK_PAGES];
122 PROPSHEETHEADER psh;
123 HPSXA hpsxa;
124 TCHAR Caption[1024];
125 LONG ret;
126 UINT i;
127
128 UNREFERENCED_PARAMETER(lParam);
129 UNREFERENCED_PARAMETER(wParam);
130 UNREFERENCED_PARAMETER(uMsg);
131 UNREFERENCED_PARAMETER(hwnd);
132
133 g_GlobalData.desktop_color = GetSysColor(COLOR_DESKTOP);
134
135 LoadString(hApplet, IDS_CPLNAME, Caption, sizeof(Caption) / sizeof(TCHAR));
136
137 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
138 psh.dwSize = sizeof(PROPSHEETHEADER);
139 psh.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
140 psh.hwndParent = hCPLWindow;
141 psh.hInstance = hApplet;
142 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_DESK_ICON));
143 psh.pszCaption = Caption;
144 psh.nPages = 0;
145 psh.nStartPage = 0;
146 psh.phpage = hpsp;
147
148 /* Allow shell extensions to replace the background page */
149 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Desk"), MAX_DESK_PAGES - psh.nPages);
150
151 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
152 {
153 /* Override the background page if requested by a shell extension */
154 if (PropPages[i].idDlg == IDD_BACKGROUND && hpsxa != NULL &&
155 SHReplaceFromPropSheetExtArray(hpsxa, CPLPAGE_DISPLAY_BACKGROUND, PropSheetAddPage, (LPARAM)&psh) != 0)
156 {
157 /* The shell extension added one or more pages to replace the background page.
158 Don't create the built-in page anymore! */
159 continue;
160 }
161
162 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc, PropPages[i].Callback);
163 }
164
165 /* NOTE: Don't call SHAddFromPropSheetExtArray here because this applet only allows
166 replacing the background page but not extending the applet by more pages */
167
168 ret = (LONG)(PropertySheet(&psh) != -1);
169
170 if (hpsxa != NULL)
171 SHDestroyPropSheetExtArray(hpsxa);
172
173 return ret;
174 }
175
176
177 /* Control Panel Callback */
178 LONG CALLBACK
179 CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
180 {
181 int i = (int)lParam1;
182
183 switch (uMsg)
184 {
185 case CPL_INIT:
186 return TRUE;
187
188 case CPL_GETCOUNT:
189 return NUM_APPLETS;
190
191 case CPL_INQUIRE:
192 {
193 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
194 CPlInfo->lData = 0;
195 CPlInfo->idIcon = Applets[i].idIcon;
196 CPlInfo->idName = Applets[i].idName;
197 CPlInfo->idInfo = Applets[i].idDescription;
198 }
199 break;
200
201 case CPL_DBLCLK:
202 hCPLWindow = hwndCPl;
203 Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2);
204 break;
205 }
206
207 return FALSE;
208 }
209
210
211 BOOL WINAPI
212 DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
213 {
214 UNREFERENCED_PARAMETER(lpvReserved);
215
216 switch (dwReason)
217 {
218 case DLL_PROCESS_ATTACH:
219 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
220 RegisterPreviewControl(hInstDLL);
221 // case DLL_THREAD_ATTACH:
222 hApplet = hInstDLL;
223 break;
224
225 case DLL_PROCESS_DETACH:
226 UnregisterPreviewControl(hInstDLL);
227 CoUninitialize();
228 break;
229 }
230
231 return TRUE;
232 }