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