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