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 static int CALLBACK 286 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) 287 { 288 // NOTE: This callback is needed to set large icon correctly. 289 HICON hIcon; 290 switch (uMsg) 291 { 292 case PSCB_INITIALIZED: 293 { 294 hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_CPLICON_2)); 295 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 296 break; 297 } 298 } 299 return 0; 300 } 301 302 LONG APIENTRY 303 KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam) 304 { 305 HPROPSHEETPAGE hpsp[MAX_CPL_PAGES]; 306 PROPSHEETHEADER psh; 307 HPSXA hpsxa; 308 INT nPage = 0; 309 LONG ret; 310 311 UNREFERENCED_PARAMETER(lParam); 312 UNREFERENCED_PARAMETER(wParam); 313 UNREFERENCED_PARAMETER(uMsg); 314 UNREFERENCED_PARAMETER(hwnd); 315 316 if (uMsg == CPL_STARTWPARMSW && lParam != 0) 317 nPage = _wtoi((PWSTR)lParam); 318 319 ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); 320 psh.dwSize = sizeof(PROPSHEETHEADER); 321 psh.dwFlags = PSH_PROPTITLE | PSH_USEICONID | PSH_USECALLBACK; 322 psh.hwndParent = hwnd; 323 psh.hInstance = hApplet; 324 psh.pszIcon = MAKEINTRESOURCE(IDC_CPLICON_2); 325 psh.pszCaption = MAKEINTRESOURCE(IDS_CPLNAME_2); 326 psh.nStartPage = 0; 327 psh.phpage = hpsp; 328 psh.pfnCallback = PropSheetProc; 329 330 /* Load additional pages provided by shell extensions */ 331 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Keyboard"), MAX_CPL_PAGES - psh.nPages); 332 333 /* NOTE: The speed page (CPLPAGE_KEYBOARD_SPEED) cannot be replaced by 334 shell extensions since Win2k! */ 335 InitPropSheetPage(&psh, IDD_KEYBSPEED, KeyboardSpeedProc); 336 InitPropSheetPage(&psh, IDD_HARDWARE, KeybHardwareProc); 337 338 if (hpsxa != NULL) 339 SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh); 340 341 if (nPage != 0 && nPage <= psh.nPages) 342 psh.nStartPage = nPage; 343 344 ret = (LONG)(PropertySheet(&psh) != -1); 345 346 if (hpsxa != NULL) 347 SHDestroyPropSheetExtArray(hpsxa); 348 349 return ret; 350 } 351 352 /* EOF */ 353