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 static VOID 43 UpdateCaretBlinkTimeReg( 44 _In_ UINT uCaretBlinkTime) 45 { 46 HKEY hKey; 47 WCHAR szBuffer[12]; 48 49 if (RegOpenKeyExW(HKEY_CURRENT_USER, 50 L"Control Panel\\Desktop", 51 0, KEY_SET_VALUE, 52 &hKey) != ERROR_SUCCESS) 53 { 54 return; 55 } 56 57 wsprintf(szBuffer, L"%d", uCaretBlinkTime); 58 59 RegSetValueExW(hKey, L"CursorBlinkRate", 60 0, REG_SZ, 61 (CONST BYTE*)szBuffer, 62 (wcslen(szBuffer) + 1) * sizeof(WCHAR)); 63 64 RegCloseKey(hKey); 65 } 66 67 /* Property page dialog callback */ 68 static INT_PTR CALLBACK 69 KeyboardSpeedProc(IN HWND hwndDlg, 70 IN UINT uMsg, 71 IN WPARAM wParam, 72 IN LPARAM lParam) 73 { 74 PSPEED_DATA pSpeedData; 75 76 pSpeedData = (PSPEED_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); 77 78 switch (uMsg) 79 { 80 case WM_INITDIALOG: 81 pSpeedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SPEED_DATA)); 82 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSpeedData); 83 84 /* Get current keyboard delay */ 85 if (!SystemParametersInfo(SPI_GETKEYBOARDDELAY, 86 sizeof(INT), 87 &pSpeedData->nKeyboardDelay, 88 0)) 89 { 90 pSpeedData->nKeyboardDelay = 2; 91 } 92 93 pSpeedData->nOrigKeyboardDelay = pSpeedData->nKeyboardDelay; 94 95 /* Get current keyboard delay */ 96 if (!SystemParametersInfo(SPI_GETKEYBOARDSPEED, 97 sizeof(DWORD), 98 &pSpeedData->dwKeyboardSpeed, 99 0)) 100 { 101 pSpeedData->dwKeyboardSpeed = 31; 102 } 103 104 pSpeedData->dwOrigKeyboardSpeed = pSpeedData->dwKeyboardSpeed; 105 106 pSpeedData->fShowCursor = TRUE; 107 GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT_CURSOR_BLINK), &pSpeedData->rcCursor); 108 ScreenToClient(hwndDlg, (LPPOINT)&pSpeedData->rcCursor.left); 109 ScreenToClient(hwndDlg, (LPPOINT)&pSpeedData->rcCursor.right); 110 111 /* Get the caret blink time and save its original value */ 112 pSpeedData->uOrigCaretBlinkTime = GetCaretBlinkTime(); 113 pSpeedData->uCaretBlinkTime = pSpeedData->uOrigCaretBlinkTime; 114 115 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 3)); 116 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(3 - pSpeedData->nKeyboardDelay)); 117 118 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 31)); 119 SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pSpeedData->dwKeyboardSpeed); 120 121 SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10)); 122 SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(12 - (pSpeedData->uCaretBlinkTime / 100))); 123 124 /* Start the blink timer */ 125 pSpeedData->uCaretBlinkTime = pSpeedData->uCaretBlinkTime >= 1200 ? -1 : pSpeedData->uCaretBlinkTime; 126 if ((INT)pSpeedData->uCaretBlinkTime > 0) 127 { 128 SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL); 129 } 130 else 131 { 132 PostMessage(hwndDlg, WM_TIMER, ID_BLINK_TIMER, 0); 133 } 134 135 break; 136 137 case WM_HSCROLL: 138 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_REPEAT_DELAY)) 139 { 140 switch (LOWORD(wParam)) 141 { 142 case TB_LINEUP: 143 case TB_LINEDOWN: 144 case TB_PAGEUP: 145 case TB_PAGEDOWN: 146 case TB_TOP: 147 case TB_BOTTOM: 148 case TB_ENDTRACK: 149 pSpeedData->nKeyboardDelay = 3 - (INT)SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_GETPOS, 0, 0); 150 SystemParametersInfo(SPI_SETKEYBOARDDELAY, 151 pSpeedData->nKeyboardDelay, 152 0, 153 0); 154 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 155 break; 156 157 case TB_THUMBTRACK: 158 pSpeedData->nKeyboardDelay = 3 - (INT)HIWORD(wParam); 159 SystemParametersInfo(SPI_SETKEYBOARDDELAY, 160 pSpeedData->nKeyboardDelay, 161 0, 162 0); 163 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 164 break; 165 } 166 } 167 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_REPEAT_RATE)) 168 { 169 switch (LOWORD(wParam)) 170 { 171 case TB_LINEUP: 172 case TB_LINEDOWN: 173 case TB_PAGEUP: 174 case TB_PAGEDOWN: 175 case TB_TOP: 176 case TB_BOTTOM: 177 case TB_ENDTRACK: 178 pSpeedData->dwKeyboardSpeed = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_GETPOS, 0, 0); 179 SystemParametersInfo(SPI_SETKEYBOARDSPEED, 180 pSpeedData->dwKeyboardSpeed, 181 0, 182 0); 183 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 184 break; 185 186 case TB_THUMBTRACK: 187 pSpeedData->dwKeyboardSpeed = (DWORD)HIWORD(wParam); 188 SystemParametersInfo(SPI_SETKEYBOARDSPEED, 189 pSpeedData->dwKeyboardSpeed, 190 0, 191 0); 192 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 193 break; 194 } 195 } 196 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_CURSOR_BLINK)) 197 { 198 switch (LOWORD(wParam)) 199 { 200 case TB_LINEUP: 201 case TB_LINEDOWN: 202 case TB_PAGEUP: 203 case TB_PAGEDOWN: 204 case TB_TOP: 205 case TB_BOTTOM: 206 case TB_ENDTRACK: 207 pSpeedData->uCaretBlinkTime = (12 - (UINT)SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_GETPOS, 0, 0)) * 100; 208 KillTimer(hwndDlg, ID_BLINK_TIMER); 209 pSpeedData->uCaretBlinkTime = pSpeedData->uCaretBlinkTime >= 1200 ? -1 : pSpeedData->uCaretBlinkTime; 210 if ((INT)pSpeedData->uCaretBlinkTime > 0) 211 { 212 SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL); 213 } 214 else if (pSpeedData->fShowCursor) 215 { 216 SendMessage(hwndDlg, WM_TIMER, ID_BLINK_TIMER, 0); 217 } 218 SetCaretBlinkTime(pSpeedData->uCaretBlinkTime); 219 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 220 break; 221 222 case TB_THUMBTRACK: 223 pSpeedData->uCaretBlinkTime = (12 - (UINT)HIWORD(wParam)) * 100; 224 KillTimer(hwndDlg, ID_BLINK_TIMER); 225 pSpeedData->uCaretBlinkTime = pSpeedData->uCaretBlinkTime >= 1200 ? -1 : pSpeedData->uCaretBlinkTime; 226 if ((INT)pSpeedData->uCaretBlinkTime > 0) 227 { 228 SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL); 229 } 230 else if (pSpeedData->fShowCursor) 231 { 232 SendMessage(hwndDlg, WM_TIMER, ID_BLINK_TIMER, 0); 233 } 234 SetCaretBlinkTime(pSpeedData->uCaretBlinkTime); 235 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 236 break; 237 } 238 } 239 break; 240 241 case WM_TIMER: 242 if (wParam == ID_BLINK_TIMER) 243 { 244 if (pSpeedData->fShowCursor) 245 { 246 HDC hDC = GetDC(hwndDlg); 247 HBRUSH hBrush = GetSysColorBrush(COLOR_BTNTEXT); 248 FillRect(hDC, &pSpeedData->rcCursor, hBrush); 249 ReleaseDC(hwndDlg, hDC); 250 } 251 else 252 { 253 InvalidateRect(hwndDlg, &pSpeedData->rcCursor, TRUE); 254 } 255 256 pSpeedData->fShowCursor = !pSpeedData->fShowCursor; 257 } 258 break; 259 260 case WM_NOTIFY: 261 { 262 LPNMHDR lpnm = (LPNMHDR)lParam; 263 264 switch(lpnm->code) 265 { 266 case PSN_APPLY: 267 /* Set the new keyboard settings */ 268 if (pSpeedData->uOrigCaretBlinkTime != pSpeedData->uCaretBlinkTime) 269 { 270 UpdateCaretBlinkTimeReg(pSpeedData->uCaretBlinkTime); 271 } 272 273 SystemParametersInfo(SPI_SETKEYBOARDDELAY, 274 pSpeedData->nKeyboardDelay, 275 0, 276 0); 277 SystemParametersInfo(SPI_SETKEYBOARDSPEED, 278 pSpeedData->dwKeyboardSpeed, 279 0, 280 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); 281 return TRUE; 282 283 case PSN_RESET: 284 /* Restore the original settings */ 285 SetCaretBlinkTime(pSpeedData->uOrigCaretBlinkTime); 286 SystemParametersInfo(SPI_SETKEYBOARDDELAY, 287 pSpeedData->nOrigKeyboardDelay, 288 0, 289 0); 290 SystemParametersInfo(SPI_SETKEYBOARDSPEED, 291 pSpeedData->dwOrigKeyboardSpeed, 292 0, 293 0); 294 break; 295 296 default: 297 break; 298 } 299 } 300 break; 301 302 case WM_DESTROY: 303 KillTimer(hwndDlg, ID_BLINK_TIMER); 304 HeapFree(GetProcessHeap(), 0, pSpeedData); 305 break; 306 } 307 308 return FALSE; 309 } 310 311 312 /* Property page dialog callback */ 313 static INT_PTR CALLBACK 314 KeybHardwareProc(IN HWND hwndDlg, 315 IN UINT uMsg, 316 IN WPARAM wParam, 317 IN LPARAM lParam) 318 { 319 GUID Guids[1]; 320 Guids[0] = GUID_DEVCLASS_KEYBOARD; 321 322 UNREFERENCED_PARAMETER(lParam); 323 UNREFERENCED_PARAMETER(wParam); 324 325 switch(uMsg) 326 { 327 case WM_INITDIALOG: 328 /* Create the hardware page */ 329 DeviceCreateHardwarePageEx(hwndDlg, 330 Guids, 331 sizeof(Guids) / sizeof(Guids[0]), 332 HWPD_STANDARDLIST); 333 break; 334 } 335 336 return FALSE; 337 } 338 339 static int CALLBACK 340 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) 341 { 342 // NOTE: This callback is needed to set large icon correctly. 343 HICON hIcon; 344 switch (uMsg) 345 { 346 case PSCB_INITIALIZED: 347 { 348 hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_CPLICON_2)); 349 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 350 break; 351 } 352 } 353 return 0; 354 } 355 356 LONG APIENTRY 357 KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam) 358 { 359 HPROPSHEETPAGE hpsp[MAX_CPL_PAGES]; 360 PROPSHEETHEADER psh; 361 HPSXA hpsxa; 362 INT nPage = 0; 363 LONG ret; 364 365 UNREFERENCED_PARAMETER(lParam); 366 UNREFERENCED_PARAMETER(wParam); 367 UNREFERENCED_PARAMETER(uMsg); 368 UNREFERENCED_PARAMETER(hwnd); 369 370 if (uMsg == CPL_STARTWPARMSW && lParam != 0) 371 nPage = _wtoi((PWSTR)lParam); 372 373 ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); 374 psh.dwSize = sizeof(PROPSHEETHEADER); 375 psh.dwFlags = PSH_PROPTITLE | PSH_USEICONID | PSH_USECALLBACK; 376 psh.hwndParent = hwnd; 377 psh.hInstance = hApplet; 378 psh.pszIcon = MAKEINTRESOURCE(IDC_CPLICON_2); 379 psh.pszCaption = MAKEINTRESOURCE(IDS_CPLNAME_2); 380 psh.nStartPage = 0; 381 psh.phpage = hpsp; 382 psh.pfnCallback = PropSheetProc; 383 384 /* Load additional pages provided by shell extensions */ 385 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Keyboard"), MAX_CPL_PAGES - psh.nPages); 386 387 /* NOTE: The speed page (CPLPAGE_KEYBOARD_SPEED) cannot be replaced by 388 shell extensions since Win2k! */ 389 InitPropSheetPage(&psh, IDD_KEYBSPEED, KeyboardSpeedProc); 390 InitPropSheetPage(&psh, IDD_HARDWARE, KeybHardwareProc); 391 392 if (hpsxa != NULL) 393 SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh); 394 395 if (nPage != 0 && nPage <= psh.nPages) 396 psh.nStartPage = nPage; 397 398 ret = (LONG)(PropertySheet(&psh) != -1); 399 400 if (hpsxa != NULL) 401 SHDestroyPropSheetExtArray(hpsxa); 402 403 return ret; 404 } 405 406 /* EOF */ 407