Allow loading shell extensions
[reactos.git] / reactos / dll / cpl / main / keyboard.c
1 /*
2 * ReactOS
3 * Copyright (C) 2004, 2007 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS Main Control Panel
22 * FILE: lib/cpl/main/keyboard.c
23 * PURPOSE: Keyboard Control Panel
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include <windows.h>
28 #include <devguid.h>
29 #include <commctrl.h>
30 #include <prsht.h>
31 #include <shlobj.h>
32 #include <cpl.h>
33 #include <regstr.h>
34
35 #include "main.h"
36 #include "resource.h"
37
38 #define ID_BLINK_TIMER 345
39
40 typedef struct _SPEED_DATA
41 {
42 INT nKeyboardDelay;
43 INT nOrigKeyboardDelay;
44 DWORD dwKeyboardSpeed;
45 DWORD dwOrigKeyboardSpeed;
46 UINT uCaretBlinkTime;
47 UINT uOrigCaretBlinkTime;
48 BOOL fShowCursor;
49 RECT rcCursor;
50 } SPEED_DATA, *PSPEED_DATA;
51
52 /* Property page dialog callback */
53 static INT_PTR CALLBACK
54 KeyboardSpeedProc(IN HWND hwndDlg,
55 IN UINT uMsg,
56 IN WPARAM wParam,
57 IN LPARAM lParam)
58 {
59 PSPEED_DATA pSpeedData;
60
61 pSpeedData = (PSPEED_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
62
63 switch (uMsg)
64 {
65 case WM_INITDIALOG:
66 pSpeedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SPEED_DATA));
67 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSpeedData);
68
69 /* Get current keyboard delay */
70 if (!SystemParametersInfo(SPI_GETKEYBOARDDELAY,
71 sizeof(INT),
72 &pSpeedData->nKeyboardDelay,
73 0))
74 {
75 pSpeedData->nKeyboardDelay = 2;
76 }
77
78 pSpeedData->nOrigKeyboardDelay = pSpeedData->nKeyboardDelay;
79
80 /* Get current keyboard delay */
81 if (!SystemParametersInfo(SPI_GETKEYBOARDSPEED,
82 sizeof(DWORD),
83 &pSpeedData->dwKeyboardSpeed,
84 0))
85 {
86 pSpeedData->dwKeyboardSpeed = 31;
87 }
88
89 pSpeedData->dwOrigKeyboardSpeed = pSpeedData->dwKeyboardSpeed;
90
91 pSpeedData->fShowCursor = TRUE;
92 GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT_CURSOR_BLINK), &pSpeedData->rcCursor);
93 ScreenToClient(hwndDlg, (LPPOINT)&pSpeedData->rcCursor.left);
94 ScreenToClient(hwndDlg, (LPPOINT)&pSpeedData->rcCursor.right);
95
96 /* Get the caret blink time and save its original value */
97 pSpeedData->uOrigCaretBlinkTime = GetCaretBlinkTime();
98 pSpeedData->uCaretBlinkTime = pSpeedData->uOrigCaretBlinkTime;
99
100 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 3));
101 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(3 - pSpeedData->nKeyboardDelay));
102
103 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 31));
104 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pSpeedData->dwKeyboardSpeed);
105
106 SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10));
107 SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(12 - (pSpeedData->uCaretBlinkTime / 100)));
108
109 /* Start the blink timer */
110 SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL);
111 break;
112
113 case WM_HSCROLL:
114 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_REPEAT_DELAY))
115 {
116 switch (LOWORD(wParam))
117 {
118 case TB_LINEUP:
119 case TB_LINEDOWN:
120 case TB_PAGEUP:
121 case TB_PAGEDOWN:
122 case TB_TOP:
123 case TB_BOTTOM:
124 case TB_ENDTRACK:
125 pSpeedData->nKeyboardDelay = 3 - (INT)SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_GETPOS, 0, 0);
126 SystemParametersInfo(SPI_SETKEYBOARDDELAY,
127 pSpeedData->nKeyboardDelay,
128 0,
129 0);
130 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
131 break;
132
133 case TB_THUMBTRACK:
134 pSpeedData->nKeyboardDelay = 3 - (INT)HIWORD(wParam);
135 SystemParametersInfo(SPI_SETKEYBOARDDELAY,
136 pSpeedData->nKeyboardDelay,
137 0,
138 0);
139 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
140 break;
141 }
142 }
143 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_REPEAT_RATE))
144 {
145 switch (LOWORD(wParam))
146 {
147 case TB_LINEUP:
148 case TB_LINEDOWN:
149 case TB_PAGEUP:
150 case TB_PAGEDOWN:
151 case TB_TOP:
152 case TB_BOTTOM:
153 case TB_ENDTRACK:
154 pSpeedData->dwKeyboardSpeed = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_GETPOS, 0, 0);
155 SystemParametersInfo(SPI_SETKEYBOARDSPEED,
156 pSpeedData->dwKeyboardSpeed,
157 0,
158 0);
159 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
160 break;
161
162 case TB_THUMBTRACK:
163 pSpeedData->dwKeyboardSpeed = (DWORD)HIWORD(wParam);
164 SystemParametersInfo(SPI_SETKEYBOARDSPEED,
165 pSpeedData->dwKeyboardSpeed,
166 0,
167 0);
168 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
169 break;
170 }
171 }
172 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_CURSOR_BLINK))
173 {
174 switch (LOWORD(wParam))
175 {
176 case TB_LINEUP:
177 case TB_LINEDOWN:
178 case TB_PAGEUP:
179 case TB_PAGEDOWN:
180 case TB_TOP:
181 case TB_BOTTOM:
182 case TB_ENDTRACK:
183 pSpeedData->uCaretBlinkTime = (12 - (UINT)SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_GETPOS, 0, 0)) * 100;
184 KillTimer(hwndDlg, ID_BLINK_TIMER);
185 SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL);
186 SetCaretBlinkTime(pSpeedData->uCaretBlinkTime);
187 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
188 break;
189
190 case TB_THUMBTRACK:
191 pSpeedData->uCaretBlinkTime = (12 - (UINT)HIWORD(wParam)) * 100;
192 KillTimer(hwndDlg, ID_BLINK_TIMER);
193 SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL);
194 SetCaretBlinkTime(pSpeedData->uCaretBlinkTime);
195 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
196 break;
197 }
198 }
199 break;
200
201 case WM_TIMER:
202 if (wParam == ID_BLINK_TIMER)
203 {
204 if (pSpeedData->fShowCursor)
205 {
206 HDC hDC = GetDC(hwndDlg);
207 HBRUSH hBrush = GetSysColorBrush(COLOR_BTNTEXT);
208 FillRect(hDC, &pSpeedData->rcCursor, hBrush);
209 DeleteObject(hBrush);
210 ReleaseDC(hwndDlg, hDC);
211 }
212 else
213 {
214 InvalidateRect(hwndDlg, &pSpeedData->rcCursor, TRUE);
215 }
216
217 pSpeedData->fShowCursor = !pSpeedData->fShowCursor;
218 }
219 break;
220
221 case WM_NOTIFY:
222 {
223 LPNMHDR lpnm = (LPNMHDR)lParam;
224
225 switch(lpnm->code)
226 {
227 case PSN_APPLY:
228 /* Set the new keyboard settings */
229 SystemParametersInfo(SPI_SETKEYBOARDDELAY,
230 pSpeedData->nKeyboardDelay,
231 0,
232 0);
233 SystemParametersInfo(SPI_SETKEYBOARDSPEED,
234 pSpeedData->dwKeyboardSpeed,
235 0,
236 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
237 return TRUE;
238
239 case PSN_RESET:
240 /* Restore the original settings */
241 SetCaretBlinkTime(pSpeedData->uOrigCaretBlinkTime);
242 SystemParametersInfo(SPI_SETKEYBOARDDELAY,
243 pSpeedData->nOrigKeyboardDelay,
244 0,
245 0);
246 SystemParametersInfo(SPI_SETKEYBOARDSPEED,
247 pSpeedData->dwOrigKeyboardSpeed,
248 0,
249 0);
250 break;
251
252 default:
253 break;
254 }
255 }
256 break;
257
258 case WM_DESTROY:
259 KillTimer(hwndDlg, ID_BLINK_TIMER);
260 HeapFree(GetProcessHeap(), 0, pSpeedData);
261 break;
262 }
263
264 return FALSE;
265 }
266
267
268 /* Property page dialog callback */
269 static INT_PTR CALLBACK
270 KeybHardwareProc(IN HWND hwndDlg,
271 IN UINT uMsg,
272 IN WPARAM wParam,
273 IN LPARAM lParam)
274 {
275 GUID Guids[1];
276 Guids[0] = GUID_DEVCLASS_KEYBOARD;
277
278 UNREFERENCED_PARAMETER(lParam);
279 UNREFERENCED_PARAMETER(wParam);
280
281 switch(uMsg)
282 {
283 case WM_INITDIALOG:
284 /* Create the hardware page */
285 DeviceCreateHardwarePageEx(hwndDlg,
286 Guids,
287 sizeof(Guids) / sizeof(Guids[0]),
288 HWPD_STANDARDLIST);
289 break;
290 }
291
292 return FALSE;
293 }
294
295
296 LONG APIENTRY
297 KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
298 {
299 HPROPSHEETPAGE hpsp[MAX_CPL_PAGES];
300 PROPSHEETHEADER psh;
301 HPSXA hpsxa;
302 TCHAR szCaption[256];
303 LONG ret;
304
305 UNREFERENCED_PARAMETER(lParam);
306 UNREFERENCED_PARAMETER(wParam);
307 UNREFERENCED_PARAMETER(uMsg);
308 UNREFERENCED_PARAMETER(hwnd);
309
310 LoadString(hApplet, IDS_CPLNAME_2, szCaption, sizeof(szCaption) / sizeof(TCHAR));
311
312 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
313 psh.dwSize = sizeof(PROPSHEETHEADER);
314 psh.dwFlags = PSH_PROPTITLE;
315 psh.hwndParent = NULL;
316 psh.hInstance = hApplet;
317 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_2));
318 psh.pszCaption = szCaption;
319 psh.nStartPage = 0;
320 psh.phpage = hpsp;
321
322 /* Load additional pages provided by shell extensions */
323 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Keyboard"), MAX_CPL_PAGES - psh.nPages);
324
325 /* NOTE: The speed page (CPLPAGE_KEYBOARD_SPEED) cannot be replaced by
326 shell extensions since Win2k! */
327 InitPropSheetPage(&psh, IDD_KEYBSPEED, KeyboardSpeedProc);
328 InitPropSheetPage(&psh, IDD_HARDWARE, KeybHardwareProc);
329
330 if (hpsxa != NULL)
331 SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh);
332
333 ret = (LONG)(PropertySheet(&psh) != -1);
334
335 if (hpsxa != NULL)
336 SHDestroyPropSheetExtArray(hpsxa);
337
338 return ret;
339 }
340
341 /* EOF */