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 ReleaseDC(hwndDlg, hDC); 200 } 201 else 202 { 203 InvalidateRect(hwndDlg, &pSpeedData->rcCursor, TRUE); 204 } 205 206 pSpeedData->fShowCursor = !pSpeedData->fShowCursor; 207 } 208 break; 209 210 case WM_NOTIFY: 211 { 212 LPNMHDR lpnm = (LPNMHDR)lParam; 213 214 switch(lpnm->code) 215 { 216 case PSN_APPLY: 217 /* Set the new keyboard settings */ 218 SystemParametersInfo(SPI_SETKEYBOARDDELAY, 219 pSpeedData->nKeyboardDelay, 220 0, 221 0); 222 SystemParametersInfo(SPI_SETKEYBOARDSPEED, 223 pSpeedData->dwKeyboardSpeed, 224 0, 225 SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); 226 return TRUE; 227 228 case PSN_RESET: 229 /* Restore the original settings */ 230 SetCaretBlinkTime(pSpeedData->uOrigCaretBlinkTime); 231 SystemParametersInfo(SPI_SETKEYBOARDDELAY, 232 pSpeedData->nOrigKeyboardDelay, 233 0, 234 0); 235 SystemParametersInfo(SPI_SETKEYBOARDSPEED, 236 pSpeedData->dwOrigKeyboardSpeed, 237 0, 238 0); 239 break; 240 241 default: 242 break; 243 } 244 } 245 break; 246 247 case WM_DESTROY: 248 KillTimer(hwndDlg, ID_BLINK_TIMER); 249 HeapFree(GetProcessHeap(), 0, pSpeedData); 250 break; 251 } 252 253 return FALSE; 254 } 255 256 257 /* Property page dialog callback */ 258 static INT_PTR CALLBACK 259 KeybHardwareProc(IN HWND hwndDlg, 260 IN UINT uMsg, 261 IN WPARAM wParam, 262 IN LPARAM lParam) 263 { 264 GUID Guids[1]; 265 Guids[0] = GUID_DEVCLASS_KEYBOARD; 266 267 UNREFERENCED_PARAMETER(lParam); 268 UNREFERENCED_PARAMETER(wParam); 269 270 switch(uMsg) 271 { 272 case WM_INITDIALOG: 273 /* Create the hardware page */ 274 DeviceCreateHardwarePageEx(hwndDlg, 275 Guids, 276 sizeof(Guids) / sizeof(Guids[0]), 277 HWPD_STANDARDLIST); 278 break; 279 } 280 281 return FALSE; 282 } 283 284 static int CALLBACK 285 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) 286 { 287 // NOTE: This callback is needed to set large icon correctly. 288 HICON hIcon; 289 switch (uMsg) 290 { 291 case PSCB_INITIALIZED: 292 { 293 hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_CPLICON_2)); 294 SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); 295 break; 296 } 297 } 298 return 0; 299 } 300 301 LONG APIENTRY 302 KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam) 303 { 304 HPROPSHEETPAGE hpsp[MAX_CPL_PAGES]; 305 PROPSHEETHEADER psh; 306 HPSXA hpsxa; 307 INT nPage = 0; 308 LONG ret; 309 310 UNREFERENCED_PARAMETER(lParam); 311 UNREFERENCED_PARAMETER(wParam); 312 UNREFERENCED_PARAMETER(uMsg); 313 UNREFERENCED_PARAMETER(hwnd); 314 315 if (uMsg == CPL_STARTWPARMSW && lParam != 0) 316 nPage = _wtoi((PWSTR)lParam); 317 318 ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); 319 psh.dwSize = sizeof(PROPSHEETHEADER); 320 psh.dwFlags = PSH_PROPTITLE | PSH_USEICONID | PSH_USECALLBACK; 321 psh.hwndParent = hwnd; 322 psh.hInstance = hApplet; 323 psh.pszIcon = MAKEINTRESOURCE(IDC_CPLICON_2); 324 psh.pszCaption = MAKEINTRESOURCE(IDS_CPLNAME_2); 325 psh.nStartPage = 0; 326 psh.phpage = hpsp; 327 psh.pfnCallback = PropSheetProc; 328 329 /* Load additional pages provided by shell extensions */ 330 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Keyboard"), MAX_CPL_PAGES - psh.nPages); 331 332 /* NOTE: The speed page (CPLPAGE_KEYBOARD_SPEED) cannot be replaced by 333 shell extensions since Win2k! */ 334 InitPropSheetPage(&psh, IDD_KEYBSPEED, KeyboardSpeedProc); 335 InitPropSheetPage(&psh, IDD_HARDWARE, KeybHardwareProc); 336 337 if (hpsxa != NULL) 338 SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh); 339 340 if (nPage != 0 && nPage <= psh.nPages) 341 psh.nStartPage = nPage; 342 343 ret = (LONG)(PropertySheet(&psh) != -1); 344 345 if (hpsxa != NULL) 346 SHDestroyPropSheetExtArray(hpsxa); 347 348 return ret; 349 } 350 351 /* EOF */ 352