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