- Set mouse speed an mouse trail on-the-fly.
[reactos.git] / reactos / dll / cpl / main / mouse.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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS Main Control Panel
22 * FILE: lib/cpl/main/mouse.c
23 * PURPOSE: Mouse Control Panel
24 * PROGRAMMER: Eric Kohl
25 * Johannes Anderwald
26 */
27
28 //TODO:
29 //detect slider changes - for apply stuff
30 // cursor icon shows - may need overriden items
31 // implement Pointer-APPLY
32 // implement Pointer-Browser
33 // add missing icons
34 // Options- pointer precision
35
36 #define WINVER 0x0501
37
38 #include <windows.h>
39 #include <winuser.h>
40 #include <devguid.h>
41 #include <commctrl.h>
42 #include <cpl.h>
43 #include <tchar.h>
44 #include <math.h>
45 #include <limits.h>
46
47 #include "main.h"
48 #include "resource.h"
49
50 #define DEFAULT_DOUBLE_CLICK_SPEED 500
51 #define DEFAULT_CLICK_LOCK_TIME 2200
52 #define DEFAULT_MOUSE_SENSITIVITY 16
53 #define DEFAULT_MOUSE_THRESHOLD1 6
54 #define DEFAULT_MOUSE_THRESHOLD2 10
55 #define MIN_DOUBLE_CLICK_SPEED 200
56 #define MAX_DOUBLE_CLICK_SPEED 900
57 #define DEFAULT_WHEEL_SCROLL_LINES 3
58
59
60 typedef struct _BUTTON_DATA
61 {
62 ULONG g_SwapMouseButtons;
63 ULONG g_OrigSwapMouseButtons;
64 ULONG g_DoubleClickSpeed; // = DEFAULT_DOUBLE_CLICK_SPEED;
65 ULONG g_OrigDoubleClickSpeed;
66 BOOL g_ClickLockEnabled; // = 0;
67 DWORD g_ClickLockTime; // = DEFAULT_CLICK_LOCK_TIME;
68
69 HICON hButtonLeft;
70 HICON hButtonRight;
71
72 HICON hIcon1;
73 HICON hIcon2;
74 BOOL bClicked;
75 } BUTTON_DATA, *PBUTTON_DATA;
76
77
78 typedef struct _OPTION_DATA
79 {
80 ULONG ulMouseSensitivity;
81 ULONG ulOrigMouseSensitivity;
82
83 ULONG ulMouseSpeed; // = 1;
84 ULONG ulMouseThreshold1; // = DEFAULT_MOUSE_THRESHOLD1;
85 ULONG ulMouseThreshold2; // = DEFAULT_MOUSE_THRESHOLD2;
86
87 ULONG ulSnapToDefaultButton; // = 0;
88
89 UINT uMouseTrails;
90
91 ULONG ulShowPointer; // = 0;
92 ULONG ulHidePointer; // = 0;
93
94 } OPTION_DATA, *POPTION_DATA;
95
96
97 typedef struct _WHEEL_DATA
98 {
99 UINT uWheelScrollLines;
100 } WHEEL_DATA, *PWHEEL_DATA;
101
102
103 ULONG g_Initialized = 0;
104
105 BOOL g_DropShadow = 0;
106
107 ULONG g_ApplyCount = 0;
108
109
110 TCHAR g_CurrentScheme[MAX_PATH];
111 TCHAR g_szArrow[MAX_PATH];
112 TCHAR g_szHelp[MAX_PATH];
113 TCHAR g_szAppStarting[MAX_PATH];
114 TCHAR g_szWait[MAX_PATH];
115 TCHAR g_szCrosshair[MAX_PATH];
116 TCHAR g_szIBeam[MAX_PATH];
117 TCHAR g_szNWPen[MAX_PATH];
118 TCHAR g_szNo[MAX_PATH];
119 TCHAR g_szSizeNS[MAX_PATH];
120 TCHAR g_szSizeWE[MAX_PATH];
121 TCHAR g_szSizeNWSE[MAX_PATH];
122 TCHAR g_szSizeNESW[MAX_PATH];
123 TCHAR g_szSizeAll[MAX_PATH];
124 TCHAR g_szUpArrow[MAX_PATH];
125 TCHAR g_szHand[MAX_PATH];
126
127 TCHAR g_szNewScheme[MAX_PATH];
128
129
130 /* Property page dialog callback */
131 static INT_PTR CALLBACK
132 MouseHardwareProc(IN HWND hwndDlg,
133 IN UINT uMsg,
134 IN WPARAM wParam,
135 IN LPARAM lParam)
136 {
137 GUID Guids[1];
138 Guids[0] = GUID_DEVCLASS_MOUSE;
139
140 UNREFERENCED_PARAMETER(lParam);
141 UNREFERENCED_PARAMETER(wParam);
142
143 switch(uMsg)
144 {
145 case WM_INITDIALOG:
146 /* create the hardware page */
147 DeviceCreateHardwarePageEx(hwndDlg,
148 Guids,
149 sizeof(Guids) / sizeof(Guids[0]),
150 HWPD_STANDARDLIST);
151 break;
152 }
153
154 return FALSE;
155 }
156
157
158 static INT_PTR CALLBACK
159 ClickLockProc(IN HWND hwndDlg,
160 IN UINT uMsg,
161 IN WPARAM wParam,
162 IN LPARAM lParam)
163 {
164 HWND hDlgCtrl;
165 int pos;
166
167 PBUTTON_DATA pButtonData;
168
169 pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
170
171 switch(uMsg)
172 {
173 case WM_INITDIALOG:
174 pButtonData = (PBUTTON_DATA)lParam;
175 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData);
176
177 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK);
178 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10));
179 pos = (pButtonData->g_ClickLockTime - 200) / 200;
180 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
181 return TRUE;
182
183 case WM_COMMAND:
184 if (LOWORD(wParam) == IDOK)
185 {
186 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK);
187 pButtonData->g_ClickLockTime = (DWORD) (SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) * 200) + 200;
188 EndDialog(hwndDlg, TRUE);
189 }
190 else if (LOWORD(wParam) == IDCANCEL)
191 {
192 EndDialog(hwndDlg, FALSE);
193 }
194 break;
195 }
196
197 return FALSE;
198 }
199
200
201 static INT_PTR CALLBACK
202 ButtonProc(IN HWND hwndDlg,
203 IN UINT uMsg,
204 IN WPARAM wParam,
205 IN LPARAM lParam)
206 {
207 HWND hDlgCtrl;
208 LRESULT lResult;
209 LPPSHNOTIFY lppsn;
210
211 PBUTTON_DATA pButtonData;
212
213 pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
214
215 switch (uMsg)
216 {
217 case WM_INITDIALOG:
218 pButtonData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BUTTON_DATA));
219 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData);
220
221 pButtonData->g_SwapMouseButtons = GetSystemMetrics(SM_SWAPBUTTON);
222 pButtonData->g_OrigSwapMouseButtons = pButtonData->g_SwapMouseButtons;
223 pButtonData->g_DoubleClickSpeed = GetDoubleClickTime();
224 pButtonData->g_OrigDoubleClickSpeed = pButtonData->g_DoubleClickSpeed;
225
226 /* Click lock time */
227 SystemParametersInfo(SPI_GETMOUSECLICKLOCK, 0, &pButtonData->g_ClickLockEnabled, 0);
228 SystemParametersInfo(SPI_GETMOUSECLICKLOCKTIME, 0, &pButtonData->g_ClickLockTime, 0);
229
230 /* Load mouse button icons */
231 pButtonData->hButtonLeft = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_LEFT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
232 pButtonData->hButtonRight = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_RIGHT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
233
234 /* Load folder icons */
235 pButtonData->hIcon1 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_CLOSED), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
236 pButtonData->hIcon2 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_OPEN), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
237
238 if (pButtonData->g_SwapMouseButtons)
239 {
240 SendDlgItemMessage(hwndDlg, IDC_SWAP_MOUSE_BUTTONS, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
241 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight);
242 }
243 else
244 {
245 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft);
246 }
247
248 if (pButtonData->g_ClickLockEnabled)
249 {
250 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_CLICK_LOCK);
251 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
252 }
253 else
254 {
255 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK);
256 EnableWindow(hDlgCtrl, FALSE);
257 }
258
259 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED);
260 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 14));
261 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, 14 - ((pButtonData->g_DoubleClickSpeed - 200) / 50));
262
263
264 SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hIcon1);
265 pButtonData->bClicked = TRUE;
266 return TRUE;
267
268 case WM_DESTROY:
269 DestroyIcon(pButtonData->hButtonLeft);
270 DestroyIcon(pButtonData->hButtonRight);
271 DestroyIcon(pButtonData->hIcon1);
272 DestroyIcon(pButtonData->hIcon2);
273 HeapFree(GetProcessHeap(), 0, pButtonData);
274 break;
275
276 case WM_COMMAND:
277 switch(LOWORD(wParam))
278 {
279 case IDC_SWAP_MOUSE_BUTTONS:
280 lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
281 if (lResult == BST_CHECKED)
282 {
283 pButtonData->g_SwapMouseButtons = FALSE;
284 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
285 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft);
286 }
287 else if (lResult == BST_UNCHECKED)
288 {
289 pButtonData->g_SwapMouseButtons = TRUE;
290 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
291 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight);
292 }
293 SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_SwapMouseButtons, NULL, SPIF_SENDCHANGE);
294 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
295 break;
296
297 case IDC_CHECK_CLICK_LOCK:
298 lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
299 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK);
300 if (lResult == BST_CHECKED)
301 {
302 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
303 pButtonData->g_ClickLockEnabled = FALSE;
304 EnableWindow(hDlgCtrl, FALSE);
305 }
306 else if (lResult == BST_UNCHECKED)
307 {
308 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
309 EnableWindow(hDlgCtrl, TRUE);
310 pButtonData->g_ClickLockEnabled = TRUE;
311 }
312 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
313 break;
314
315 case IDC_BUTTON_CLICK_LOCK:
316 DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CLICK_LOCK), hwndDlg, ClickLockProc, (LPARAM)pButtonData);
317 break;
318
319 case IDC_IMAGE_DOUBLE_CLICK_SPEED:
320 if (HIWORD(wParam) == STN_DBLCLK)
321 {
322 pButtonData->bClicked = !pButtonData->bClicked;
323 SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON,
324 (LPARAM)(pButtonData->bClicked ? pButtonData->hIcon1 : pButtonData->hIcon2));
325 }
326 break;
327 }
328 break;
329
330 case WM_NOTIFY:
331 lppsn = (LPPSHNOTIFY) lParam;
332 if (lppsn->hdr.code == PSN_APPLY)
333 {
334 #if (WINVER >= 0x0500)
335 SystemParametersInfo(SPI_SETMOUSECLICKLOCK, pButtonData->g_ClickLockEnabled, NULL, SPIF_SENDCHANGE);
336 if (pButtonData->g_ClickLockEnabled)
337 SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, pButtonData->g_ClickLockTime, NULL, SPIF_SENDCHANGE);
338 #endif
339 SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
340 }
341 else if (lppsn->hdr.code == PSN_RESET)
342 {
343 /* Reset swap mouse button setting */
344 SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_OrigSwapMouseButtons, NULL, SPIF_SENDCHANGE);
345
346 /* Reset double click speed setting */
347 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_OrigDoubleClickSpeed, NULL, SPIF_SENDCHANGE);
348 SetDoubleClickTime(pButtonData->g_OrigDoubleClickSpeed);
349 }
350 return TRUE;
351
352 case WM_HSCROLL:
353 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED))
354 {
355 switch (LOWORD(wParam))
356 {
357 case TB_LINEUP:
358 case TB_LINEDOWN:
359 case TB_PAGEUP:
360 case TB_PAGEDOWN:
361 case TB_TOP:
362 case TB_BOTTOM:
363 case TB_ENDTRACK:
364 lResult = SendDlgItemMessage(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED, TBM_GETPOS, 0, 0);
365 pButtonData->g_DoubleClickSpeed = (14 - (INT)lResult) * 50 + 200;
366 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE);
367 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
368 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
369 break;
370
371 case TB_THUMBTRACK:
372 pButtonData->g_DoubleClickSpeed = (14 - (INT)HIWORD(wParam)) * 50 + 200;
373 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE);
374 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
375 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
376 break;
377 }
378 }
379 break;
380 }
381
382 return FALSE;
383 }
384
385
386 #if 0
387 static BOOL
388 ReadActiveCursorScheme(VOID)
389 {
390 HKEY hCuKey;
391 HKEY hCuCursorKey;
392 DWORD dwIndex;
393 TCHAR szValueName[MAX_PATH];
394 DWORD dwValueName;
395 TCHAR szValueData[2000];
396 DWORD dwValueData;
397 LONG dwResult;
398
399 if (RegOpenCurrentUser(KEY_READ, &hCuKey) != ERROR_SUCCESS)
400 return FALSE;
401
402 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors"), 0, KEY_READ, &hCuCursorKey) != ERROR_SUCCESS)
403 {
404 RegCloseKey(hCuKey);
405 return FALSE;
406 }
407
408 memset(g_szArrow, 0x0, sizeof(g_szArrow));
409 memset(g_szHelp, 0x0, sizeof(g_szHelp));
410 memset(g_szAppStarting, 0x0, sizeof(g_szAppStarting));
411 memset(g_szWait, 0x0, sizeof(g_szWait));
412 memset(g_szCrosshair, 0x0, sizeof(g_szCrosshair));
413 memset(g_szIBeam, 0x0, sizeof(g_szIBeam));
414 memset(g_szNWPen, 0x0, sizeof(g_szNWPen));
415 memset(g_szNo, 0x0, sizeof(g_szNo));
416 memset(g_szSizeNS, 0x0, sizeof(g_szSizeNS));
417 memset(g_szSizeWE, 0x0, sizeof(g_szSizeWE));
418 memset(g_szSizeNWSE, 0x0, sizeof(g_szSizeNWSE));
419 memset(g_szSizeNESW, 0x0, sizeof(g_szSizeNESW));
420 memset(g_szSizeAll, 0x0, sizeof(g_szSizeAll));
421 memset(g_szUpArrow, 0x0, sizeof(g_szUpArrow));
422 memset(g_szHand, 0x0, sizeof(g_szHand));
423
424 dwIndex = 0;
425 for (;;)
426 {
427 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
428 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
429 dwResult = RegEnumValue(hCuCursorKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (LPBYTE)szValueData, &dwValueData);
430 if (dwResult == ERROR_NO_MORE_ITEMS)
431 break;
432
433 if (_tcsicmp(_T("Arrow"), szValueName))
434 _tcsncpy(g_szArrow, szValueData, MAX_PATH);
435 else if (_tcsicmp(_T("Help"), szValueName))
436 _tcsncpy(g_szHelp, szValueData, MAX_PATH);
437 else if (_tcsicmp(_T("AppStarting"), szValueName))
438 _tcsncpy(g_szAppStarting, szValueData, MAX_PATH);
439 else if (_tcsicmp(_T("Wait"), szValueName))
440 _tcsncpy(g_szWait, szValueData, MAX_PATH);
441 else if (_tcsicmp(_T("Crosshair"), szValueName))
442 _tcsncpy(g_szCrosshair, szValueData, MAX_PATH);
443 else if (_tcsicmp(_T("IBeam"), szValueName))
444 _tcsncpy(g_szIBeam, szValueData, MAX_PATH);
445 else if (_tcsicmp(_T("NWPen"), szValueName))
446 _tcsncpy(g_szNWPen, szValueData, MAX_PATH);
447 else if (_tcscmp(_T("No"), szValueName))
448 _tcsncpy(g_szNo, szValueData, MAX_PATH);
449 else if (_tcsicmp(_T("SizeNS"), szValueName))
450 _tcsncpy(g_szSizeNS, szValueData, MAX_PATH);
451 else if (_tcsicmp(_T("SizeWE"), szValueName))
452 _tcsncpy(g_szSizeWE, szValueData, MAX_PATH);
453 else if (_tcsicmp(_T("SizeNWSE"), szValueName))
454 _tcsncpy(g_szSizeNWSE, szValueData, MAX_PATH);
455 else if (_tcsicmp(_T("SizeNESW"), szValueName))
456 _tcsncpy(g_szSizeNESW, szValueData, MAX_PATH);
457 else if (_tcsicmp(_T("SizeAll"), szValueName))
458 _tcsncpy(g_szSizeAll, szValueData, MAX_PATH);
459 else if (_tcsicmp(_T("UpArrow"), szValueName))
460 _tcsncpy(g_szUpArrow, szValueData, MAX_PATH);
461 else if (_tcsicmp(_T("Hand"), szValueName))
462 _tcsncpy(g_szHand, szValueData, MAX_PATH);
463
464 dwIndex++;
465 }
466
467 RegCloseKey(hCuCursorKey);
468 RegCloseKey(hCuKey);
469
470 return TRUE;
471 }
472 #endif
473
474
475 static BOOL
476 EnumerateCursorSchemes(HWND hwndDlg)
477 {
478 HKEY hCuKey;
479 HKEY hCuCursorKey;
480 DWORD dwIndex;
481 TCHAR szValueName[MAX_PATH];
482 DWORD dwValueName;
483 TCHAR szSystemScheme[MAX_PATH];
484 TCHAR szValueData[2000];
485 DWORD dwValueData;
486 LONG dwResult;
487 HWND hDlgCtrl;
488 LRESULT lResult;
489 BOOL ProcessedHKLM = FALSE;
490
491 if (RegOpenCurrentUser(KEY_READ, &hCuKey) != ERROR_SUCCESS)
492 return FALSE;
493
494 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ, &hCuCursorKey) != ERROR_SUCCESS)
495 {
496 RegCloseKey(hCuKey);
497 return FALSE;
498 }
499
500 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
501 SendMessage(hDlgCtrl, CB_RESETCONTENT, 0, 0);
502 dwIndex = 0;
503
504 for (;;)
505 {
506 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
507 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
508 dwResult = RegEnumValue(hCuCursorKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (LPBYTE)szValueData, &dwValueData);
509
510 if (dwResult == ERROR_NO_MORE_ITEMS)
511 {
512 if(!ProcessedHKLM)
513 {
514 RegCloseKey(hCuCursorKey);
515 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
516 _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes"),
517 0, KEY_READ, &hCuCursorKey);
518 if (dwResult == ERROR_SUCCESS)
519 {
520 dwIndex = 0;
521 ProcessedHKLM = TRUE;
522 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
523 continue;
524 }
525 }
526 break;
527 }
528
529 if(_tcslen(szValueData) > 0)
530 {
531 TCHAR * copy = _tcsdup(szValueData);
532 if (ProcessedHKLM)
533 {
534 _tcscat(szValueName, TEXT(" "));
535 _tcscat(szValueName, szSystemScheme);
536 }
537 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName);
538 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)copy);
539 }
540
541 dwIndex++;
542 }
543
544 RegCloseKey(hCuCursorKey);
545 RegCloseKey(hCuKey);
546
547 LoadString(hApplet, IDS_NONE, szSystemScheme, MAX_PATH);
548 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szSystemScheme);
549 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)NULL);
550 SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
551
552 return TRUE;
553 }
554
555
556 static VOID
557 RefreshCursorList(HWND hwndDlg)
558 {
559 TCHAR szCursorName[MAX_PATH];
560 HWND hDlgCtrl;
561 LV_ITEM listItem;
562 LV_COLUMN column;
563 INT index = 0;
564
565 hDlgCtrl = GetDlgItem(hwndDlg, IDC_LISTVIEW_CURSOR);
566 (void)ListView_DeleteAllItems(hDlgCtrl);
567
568 ZeroMemory(&column, sizeof(LV_COLUMN));
569 column.mask = LVCF_SUBITEM | LVCF_WIDTH;
570 column.iSubItem = 0;
571 column.cx = 200;
572
573 (void)ListView_InsertColumn(hDlgCtrl, 0, &column);
574
575 LoadString(hApplet, IDS_ARROW, szCursorName, MAX_PATH);
576
577 ZeroMemory(&listItem, sizeof(LV_ITEM));
578 listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
579 listItem.pszText = szCursorName;
580 listItem.state = 0;
581 listItem.iImage = -1;
582 listItem.iItem = index++;
583 listItem.lParam = 0;
584
585 (void)ListView_InsertItem(hDlgCtrl, &listItem);
586
587 LoadString(hApplet, IDS_HELP, szCursorName, MAX_PATH);
588 listItem.iItem = index++;
589 (void)ListView_InsertItem(hDlgCtrl, &listItem);
590
591 LoadString(hApplet, IDS_APPSTARTING, szCursorName, MAX_PATH);
592 listItem.iItem = index++;
593 (void)ListView_InsertItem(hDlgCtrl, &listItem);
594
595 LoadString(hApplet, IDS_WAIT, szCursorName, MAX_PATH);
596 listItem.iItem = index++;
597 (void)ListView_InsertItem(hDlgCtrl, &listItem);
598
599 LoadString(hApplet, IDS_CROSSHAIR, szCursorName, MAX_PATH);
600 listItem.iItem = index++;
601 (void)ListView_InsertItem(hDlgCtrl, &listItem);
602
603 LoadString(hApplet, IDS_IBEAM, szCursorName, MAX_PATH);
604 listItem.iItem = index++;
605 (void)ListView_InsertItem(hDlgCtrl, &listItem);
606
607 LoadString(hApplet, IDS_NWPEN, szCursorName, MAX_PATH);
608 listItem.iItem = index++;
609 (void)ListView_InsertItem(hDlgCtrl, &listItem);
610
611 LoadString(hApplet, IDS_NO, szCursorName, MAX_PATH);
612 listItem.iItem = index++;
613 (void)ListView_InsertItem(hDlgCtrl, &listItem);
614
615 LoadString(hApplet, IDS_SIZENS, szCursorName, MAX_PATH);
616 listItem.iItem = index++;
617 (void)ListView_InsertItem(hDlgCtrl, &listItem);
618
619
620 LoadString(hApplet, IDS_SIZENWSE, szCursorName, MAX_PATH);
621 listItem.iItem = index++;
622 (void)ListView_InsertItem(hDlgCtrl, &listItem);
623
624 LoadString(hApplet, IDS_SIZENESW, szCursorName, MAX_PATH);
625 listItem.iItem = index++;
626 (void)ListView_InsertItem(hDlgCtrl, &listItem);
627
628 LoadString(hApplet, IDS_SIZEALL, szCursorName, MAX_PATH);
629 listItem.iItem = index++;
630 (void)ListView_InsertItem(hDlgCtrl, &listItem);
631
632 LoadString(hApplet, IDS_UPARROW, szCursorName, MAX_PATH);
633 listItem.iItem = index++;
634 (void)ListView_InsertItem(hDlgCtrl, &listItem);
635
636 LoadString(hApplet, IDS_HAND, szCursorName, MAX_PATH);
637 listItem.iItem = index++;
638 (void)ListView_InsertItem(hDlgCtrl, &listItem);
639 }
640
641
642 static BOOL
643 DeleteUserCursorScheme(TCHAR * szScheme)
644 {
645 HKEY hCuKey;
646 HKEY hCuCursorKey;
647 LONG Result;
648
649 if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS)
650 return FALSE;
651
652 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS)
653 {
654 RegCloseKey(hCuKey);
655 return FALSE;
656 }
657
658 Result = RegDeleteValue(hCuCursorKey, szScheme);
659
660 RegCloseKey(hCuCursorKey);
661 RegCloseKey(hCuKey);
662
663 return (Result == ERROR_SUCCESS);
664 }
665
666
667 static INT_PTR CALLBACK
668 SaveSchemeProc(IN HWND hwndDlg,
669 IN UINT uMsg,
670 IN WPARAM wParam,
671 IN LPARAM lParam)
672 {
673 HWND hDlgCtrl;
674 UNREFERENCED_PARAMETER(lParam);
675
676 switch(uMsg)
677 {
678 case WM_COMMAND:
679 if (LOWORD(wParam) == IDOK)
680 {
681 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_SCHEME_NAME);
682 SendMessage(hDlgCtrl, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)g_szNewScheme);
683 EndDialog(hwndDlg, TRUE);
684 }
685 else if (LOWORD(wParam) == IDCANCEL)
686 {
687 EndDialog(hwndDlg, FALSE);
688 }
689 break;
690 }
691
692 return FALSE;
693 }
694
695
696 static BOOL
697 BrowseCursor(TCHAR * szFileName, HWND hwndDlg)
698 {
699 //FIXME load text resources from string
700 OPENFILENAME ofn;
701 static TCHAR szFilter[] = _T("Cursors\0*.ani;*.cur\0Animated Cursors\0*.ani\0Static Cursors\0*.cur\0All Files\0*.*\0\0");
702
703 ZeroMemory(&ofn, sizeof(OPENFILENAME));
704
705 ofn.lStructSize = sizeof(OPENFILENAME);
706 ofn.hwndOwner = hwndDlg;
707 ofn.lpstrFilter = szFilter;
708 ofn.nFilterIndex = 1;
709 ofn.lpstrFile = szFileName;
710 ofn.nMaxFile = MAX_PATH;
711 ofn.lpstrInitialDir = _T("%WINDIR%\\Cursors");
712 ofn.lpstrTitle = _T("Browse");
713 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
714
715 if (GetOpenFileName(&ofn))
716 return TRUE;
717 else
718 return FALSE;
719 }
720
721
722 static VOID
723 LoadCurrentCursorScheme(LPTSTR lpName, BOOL bSystem)
724 {
725 HKEY hCursorKey;
726 TCHAR szValue[2048];
727 TCHAR szRaw[256];
728 DWORD dwValueLen;
729 LONG lError;
730 LPTSTR ptrStart, ptrEnd;
731 INT_PTR len;
732 int i;
733
734 if (lpName == NULL)
735 {
736 memset(g_szArrow, 0x0, sizeof(g_szArrow));
737 memset(g_szHelp, 0x0, sizeof(g_szHelp));
738 memset(g_szAppStarting, 0x0, sizeof(g_szAppStarting));
739 memset(g_szWait, 0x0, sizeof(g_szWait));
740 memset(g_szCrosshair, 0x0, sizeof(g_szCrosshair));
741 memset(g_szIBeam, 0x0, sizeof(g_szIBeam));
742 memset(g_szNWPen, 0x0, sizeof(g_szNWPen));
743 memset(g_szNo, 0x0, sizeof(g_szNo));
744 memset(g_szSizeNS, 0x0, sizeof(g_szSizeNS));
745 memset(g_szSizeWE, 0x0, sizeof(g_szSizeWE));
746 memset(g_szSizeNWSE, 0x0, sizeof(g_szSizeNWSE));
747 memset(g_szSizeNESW, 0x0, sizeof(g_szSizeNESW));
748 memset(g_szSizeAll, 0x0, sizeof(g_szSizeAll));
749 memset(g_szUpArrow, 0x0, sizeof(g_szUpArrow));
750 memset(g_szHand, 0x0, sizeof(g_szHand));
751 }
752 else
753 {
754 if (bSystem)
755 {
756 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
757 _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes"),
758 0, KEY_READ, &hCursorKey))
759 return;
760 }
761 else
762 {
763 if (RegOpenKeyEx(HKEY_CURRENT_USER,
764 _T("Control Panel\\Cursors\\Schemes"),
765 0, KEY_READ, &hCursorKey) != ERROR_SUCCESS)
766 return;
767 }
768
769 dwValueLen = 2048 * sizeof(TCHAR);
770 lError = RegQueryValueEx(hCursorKey, lpName, NULL, NULL, (LPBYTE)szValue, &dwValueLen);
771
772 RegCloseKey(hCursorKey);
773
774 if (lError == ERROR_SUCCESS)
775 {
776 ptrStart = szValue;
777 for (i = 0; ; i++)
778 {
779 ptrEnd = _tcschr(ptrStart, TEXT(','));
780 if (ptrEnd != NULL)
781 {
782 len = (ptrEnd - ptrStart) / sizeof(TCHAR);
783 _tcsncpy(szRaw, ptrStart, len);
784 szRaw[len] = 0;
785 }
786 else
787 {
788 _tcscpy(szRaw, ptrStart);
789 }
790
791 switch (i)
792 {
793 case 0:
794 ExpandEnvironmentStrings(szRaw, g_szArrow, MAX_PATH);
795 break;
796
797 }
798
799
800
801 if (ptrEnd == NULL)
802 break;
803
804 ptrStart = ptrEnd + 1;
805 }
806 }
807 }
808 }
809
810
811 static INT_PTR CALLBACK
812 PointerProc(IN HWND hwndDlg,
813 IN UINT uMsg,
814 IN WPARAM wParam,
815 IN LPARAM lParam)
816 {
817 LPPSHNOTIFY lppsn;
818 TCHAR buffer[MAX_PATH];
819 TCHAR szSystemScheme[MAX_PATH];
820 HWND hDlgCtrl;
821 HDC memDC;
822 HCURSOR hCursor;
823 LRESULT lResult;
824
825 switch(uMsg)
826 {
827 case WM_INITDIALOG:
828 EnumerateCursorSchemes(hwndDlg);
829 RefreshCursorList(hwndDlg);
830 /* drop shadow */
831 SystemParametersInfo(SPI_GETDROPSHADOW, 0, &g_DropShadow, 0);
832 if (g_DropShadow)
833 {
834 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_DROP_SHADOW);
835 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
836 }
837 if ((INT)wParam == IDC_LISTVIEW_CURSOR)
838 return TRUE;
839 else
840 return FALSE;
841
842 case WM_NOTIFY:
843 lppsn = (LPPSHNOTIFY) lParam;
844 if (lppsn->hdr.code == PSN_APPLY)
845 {
846 #if (WINVER >= 0x0500)
847 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)g_DropShadow, SPIF_SENDCHANGE);
848 #endif
849 SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
850 return TRUE;
851 }
852 break;
853
854 case WM_COMMAND:
855 switch(HIWORD(wParam))
856 {
857 case CBN_SELENDOK:
858 {
859 BOOL bEnable;
860 LPTSTR lpName;
861
862 wParam = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
863 if(wParam == CB_ERR)
864 break;
865 SendMessage((HWND)lParam, CB_GETLBTEXT, wParam, (LPARAM)buffer);
866 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
867 if(_tcsstr(buffer, szSystemScheme) || wParam == 0) //avoid the default scheme can be deleted
868 bEnable = FALSE;
869 else
870 bEnable = TRUE;
871
872 /* delete button */
873 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME);
874 EnableWindow(hDlgCtrl, bEnable);
875
876 lpName = (LPTSTR)SendMessage((HWND)lParam, CB_GETITEMDATA, wParam, 0);
877 LoadCurrentCursorScheme(lpName, !bEnable);
878 break;
879 }
880 }
881
882 switch (LOWORD(wParam))
883 {
884 case IDC_BUTTON_SAVEAS_SCHEME:
885 if (DialogBox(hApplet, MAKEINTRESOURCE(IDD_CURSOR_SCHEME_SAVEAS), hwndDlg, SaveSchemeProc))
886 {
887 //FIXME
888 //save cursor scheme
889 }
890 break;
891
892 case IDC_BUTTON_USE_DEFAULT_CURSOR:
893 hDlgCtrl = GetDlgItem(hwndDlg, IDC_LISTVIEW_CURSOR);
894 lResult = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
895 if (lResult != CB_ERR)
896 {
897 if ((INT)lResult == 0)
898 memset(g_szArrow, 0x0, MAX_PATH * sizeof(TCHAR));
899 else if ((INT)lResult == 1)
900 memset(g_szHelp, 0x0, MAX_PATH * sizeof(TCHAR));
901 else if ((INT)lResult == 2)
902 memset(g_szAppStarting, 0x0, MAX_PATH * sizeof(TCHAR));
903 else if ((INT)lResult == 3)
904 memset(g_szWait, 0x0, MAX_PATH * sizeof(TCHAR));
905 else if ((INT)lResult == 4)
906 memset(g_szCrosshair, 0x0, MAX_PATH * sizeof(TCHAR));
907 else if ((INT)lResult == 5)
908 memset(g_szIBeam, 0x0, MAX_PATH * sizeof(TCHAR));
909 else if ((INT)lResult == 6)
910 memset(g_szNWPen, 0x0, MAX_PATH * sizeof(TCHAR));
911 else if ((INT)lResult == 7)
912 memset(g_szNo, 0x0, MAX_PATH * sizeof(TCHAR));
913 else if ((INT)lResult == 8)
914 memset(g_szSizeNS, 0x0, MAX_PATH * sizeof(TCHAR));
915 else if ((INT)lResult == 9)
916 memset(g_szSizeWE,0x0, MAX_PATH * sizeof(TCHAR));
917 else if ((INT)lResult == 10)
918 memset(g_szSizeNWSE, 0x0, MAX_PATH * sizeof(TCHAR));
919 else if ((INT)lResult == 11)
920 memset(g_szSizeNESW, 0x0, MAX_PATH * sizeof(TCHAR));
921 else if ((INT)lResult == 12)
922 memset(g_szSizeAll, 0x0, MAX_PATH * sizeof(TCHAR));
923 else if ((INT)lResult == 13)
924 memset(g_szUpArrow, 0x0, MAX_PATH * sizeof(TCHAR));
925 else if ((INT)lResult == 14)
926 memset(g_szHand, 0x0, MAX_PATH * sizeof(TCHAR));
927 }
928 break;
929
930 case IDC_BUTTON_BROWSE_CURSOR:
931 memset(buffer, 0x0, sizeof(buffer));
932 hDlgCtrl = GetDlgItem(hwndDlg, IDC_LISTVIEW_CURSOR);
933 lResult = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
934 if (lResult == CB_ERR)
935 MessageBox(hwndDlg, _T("CB_ERR"), _T(""),MB_ICONERROR);
936 if (BrowseCursor(buffer, hwndDlg))
937 {
938 if ((INT)lResult == 0)
939 _tcsncpy(g_szArrow, buffer, MAX_PATH);
940 else if ((INT)lResult == 1)
941 _tcsncpy(g_szHelp, buffer, MAX_PATH);
942 else if ((INT)lResult == 2)
943 _tcsncpy(g_szAppStarting, buffer, MAX_PATH);
944 else if ((INT)lResult == 3)
945 _tcsncpy(g_szWait, buffer, MAX_PATH);
946 else if ((INT)lResult == 4)
947 _tcsncpy(g_szCrosshair, buffer, MAX_PATH);
948 else if ((INT)lResult == 5)
949 _tcsncpy(g_szIBeam, buffer, MAX_PATH);
950 else if ((INT)lResult == 6)
951 _tcsncpy(g_szNWPen, buffer, MAX_PATH);
952 else if ((INT)lResult == 7)
953 _tcsncpy(g_szNo, buffer, MAX_PATH);
954 else if ((INT)lResult == 8)
955 _tcsncpy(g_szSizeNS, buffer, MAX_PATH);
956 else if ((INT)lResult == 9)
957 _tcsncpy(g_szSizeWE, buffer, MAX_PATH);
958 else if ((INT)lResult == 10)
959 _tcsncpy(g_szSizeNWSE, buffer, MAX_PATH);
960 else if ((INT)lResult == 11)
961 _tcsncpy(g_szSizeNESW, buffer, MAX_PATH);
962 else if ((INT)lResult == 12)
963 _tcsncpy(g_szSizeAll, buffer, MAX_PATH);
964 else if ((INT)lResult == 13)
965 _tcsncpy(g_szUpArrow, buffer, MAX_PATH);
966 else if ((INT)lResult == 14)
967 _tcsncpy(g_szHand, buffer, MAX_PATH);
968
969 //FIXME
970 //clear screen
971
972 hDlgCtrl = GetDlgItem(hwndDlg, IDC_IMAGE_CURRENT_CURSOR);
973 memDC = GetDC(hDlgCtrl);
974 hCursor = (HCURSOR) LoadImage(NULL, buffer, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE | LR_SHARED);
975 if (hCursor)
976 {
977 DrawIcon(memDC, 10, 10, (HICON)hCursor);
978 DestroyCursor(hCursor);
979 }
980 ReleaseDC(hDlgCtrl, memDC);
981 }
982 break;
983
984 case IDC_BUTTON_DELETE_SCHEME:
985 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
986 wParam = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
987 if(wParam == CB_ERR)
988 break;
989 SendMessage(hDlgCtrl, CB_GETLBTEXT, wParam, (LPARAM)buffer);
990 if (DeleteUserCursorScheme(buffer))
991 {
992 SendMessage(hDlgCtrl, CB_DELETESTRING, wParam, 0);
993 SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
994 }
995 break;
996
997 case IDC_CHECK_DROP_SHADOW:
998 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_DROP_SHADOW))
999 {
1000 g_DropShadow = 0;
1001 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1002 }
1003 else
1004 {
1005 g_DropShadow = 1;
1006 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1007 }
1008 }
1009 break;
1010 }
1011
1012 return FALSE;
1013 }
1014
1015
1016 static BOOL
1017 InitializeMouse(POPTION_DATA pOptionData)
1018 {
1019 //FIXME
1020 //pointer precision
1021 // SPI_GETMOUSE?
1022
1023 /* Get mouse sensitivity */
1024 if (!SystemParametersInfo(SPI_GETMOUSESPEED, 0, &pOptionData->ulMouseSensitivity, 0))
1025 pOptionData->ulMouseSensitivity = DEFAULT_MOUSE_SENSITIVITY;
1026 pOptionData->ulOrigMouseSensitivity = pOptionData->ulMouseSensitivity;
1027
1028 pOptionData->ulMouseSpeed = 1;
1029 pOptionData->ulMouseThreshold1 = DEFAULT_MOUSE_THRESHOLD1;
1030 pOptionData->ulMouseThreshold2 = DEFAULT_MOUSE_THRESHOLD2;
1031
1032 /* snap to default button */
1033 if (SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &pOptionData->ulSnapToDefaultButton, 0))
1034 pOptionData->ulSnapToDefaultButton = 0;
1035
1036 /* mouse trails */
1037 if (!SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &pOptionData->uMouseTrails, 0))
1038 pOptionData->uMouseTrails = 0;
1039
1040 /* hide pointer while typing */
1041 if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &pOptionData->ulHidePointer, 0))
1042 pOptionData->ulHidePointer = 0;
1043
1044 /* show pointer with Ctrl-Key */
1045 if (!SystemParametersInfo(SPI_GETMOUSESONAR, 0, &pOptionData->ulShowPointer, 0))
1046 pOptionData->ulShowPointer = 0;
1047
1048 return TRUE;
1049 }
1050
1051
1052 static INT_PTR CALLBACK
1053 OptionProc(IN HWND hwndDlg,
1054 IN UINT uMsg,
1055 IN WPARAM wParam,
1056 IN LPARAM lParam)
1057 {
1058 HWND hDlgCtrl;
1059 LPPSHNOTIFY lppsn;
1060 LRESULT lResult;
1061 POPTION_DATA pOptionData;
1062
1063 pOptionData = (POPTION_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1064
1065 switch(uMsg)
1066 {
1067 case WM_INITDIALOG:
1068 pOptionData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPTION_DATA));
1069 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pOptionData);
1070
1071 InitializeMouse(pOptionData);
1072
1073 /* set mouse sensitivity */
1074 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY);
1075 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 19));
1076 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->ulMouseSensitivity - 1);
1077
1078 if (pOptionData->ulMouseSpeed)
1079 {
1080 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_POINTER_PRECISION);
1081 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1082 }
1083
1084 if (pOptionData->ulSnapToDefaultButton)
1085 {
1086 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SNAP_TO);
1087 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1088 }
1089
1090 /* set mouse trail */
1091 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1092 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 5));
1093 if (pOptionData->uMouseTrails < 2)
1094 EnableWindow(hDlgCtrl, FALSE);
1095 else
1096 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->uMouseTrails - 2);
1097
1098 if (pOptionData->ulShowPointer)
1099 {
1100 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SHOW_POINTER);
1101 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1102 }
1103
1104 if (pOptionData->ulHidePointer)
1105 {
1106 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_HIDE_POINTER);
1107 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1108 }
1109 break;
1110
1111 case WM_DESTROY:
1112 HeapFree(GetProcessHeap(), 0, pOptionData);
1113 break;
1114
1115 case WM_COMMAND:
1116 switch(LOWORD(wParam))
1117 {
1118 case IDC_CHECK_POINTER_PRECISION:
1119 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_PRECISION))
1120 {
1121 pOptionData->ulMouseSpeed = 0;
1122 pOptionData->ulMouseThreshold1 = 0;
1123 pOptionData->ulMouseThreshold2 = 0;
1124 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1125 }
1126 else
1127 {
1128 pOptionData->ulMouseSpeed = 1;
1129 pOptionData->ulMouseThreshold1 = 6;
1130 pOptionData->ulMouseThreshold2 = 10;
1131 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1132 }
1133 break;
1134
1135 case IDC_CHECK_SNAP_TO:
1136 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SNAP_TO))
1137 {
1138 pOptionData->ulSnapToDefaultButton = 0;
1139 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1140 }
1141 else
1142 {
1143 pOptionData->ulSnapToDefaultButton = 1;
1144 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1145 }
1146 break;
1147
1148 case IDC_CHECK_POINTER_TRAIL:
1149 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1150 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL))
1151 {
1152 pOptionData->uMouseTrails = 0;
1153 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1154 EnableWindow(hDlgCtrl, FALSE);
1155 }
1156 else
1157 {
1158 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1159 EnableWindow(hDlgCtrl, TRUE);
1160 pOptionData->uMouseTrails = (ULONG)SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2;
1161 }
1162 break;
1163
1164 case IDC_CHECK_SHOW_POINTER:
1165 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHOW_POINTER))
1166 {
1167 pOptionData->ulShowPointer = 0;
1168 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1169 }
1170 else
1171 {
1172 pOptionData->ulShowPointer = 1;
1173 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1174 }
1175 break;
1176
1177 case IDC_CHECK_HIDE_POINTER:
1178 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_HIDE_POINTER))
1179 {
1180 pOptionData->ulHidePointer = 0;
1181 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1182 }
1183 else
1184 {
1185 pOptionData->ulHidePointer = 1;
1186 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1187 }
1188 break;
1189 }
1190 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1191 break;
1192
1193 case WM_NOTIFY:
1194 lppsn = (LPPSHNOTIFY)lParam;
1195 if (lppsn->hdr.code == PSN_APPLY)
1196 {
1197 /* set snap to default button */
1198 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, pOptionData->ulSnapToDefaultButton, 0, SPIF_SENDCHANGE);
1199
1200 #if 0
1201 /* set mouse trails */
1202 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL))
1203 {
1204 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1205 lResult = SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2;
1206 }
1207 else
1208 {
1209 lResult = 0;
1210 }
1211
1212 SystemParametersInfo(SPI_SETMOUSETRAILS, (UINT) lResult, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1213 #endif
1214
1215 //FIXME
1216 //pointer precision
1217 //SPI_SETMOUSE?
1218
1219 /* calc pos and set mouse sensitivity */
1220 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY);
1221 lResult = SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 1;
1222 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSensitivity, SPIF_SENDCHANGE);
1223
1224 /* hide pointer while typing */
1225 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, (PVOID)pOptionData->ulHidePointer, SPIF_SENDCHANGE);
1226
1227 /* show pointer with Ctrl-Key */
1228 SystemParametersInfo(SPI_SETMOUSESONAR, 0, (PVOID)pOptionData->ulShowPointer, SPIF_SENDCHANGE);
1229
1230 SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
1231 return TRUE;
1232 }
1233 else if (lppsn->hdr.code == PSN_RESET)
1234 {
1235 /* Set the original mouse speed */
1236 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulOrigMouseSensitivity, SPIF_SENDCHANGE);
1237 }
1238 break;
1239
1240 case WM_HSCROLL:
1241 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY))
1242 {
1243 switch (LOWORD(wParam))
1244 {
1245 case TB_LINEUP:
1246 case TB_LINEDOWN:
1247 case TB_PAGEUP:
1248 case TB_PAGEDOWN:
1249 case TB_TOP:
1250 case TB_BOTTOM:
1251 case TB_ENDTRACK:
1252 pOptionData->ulMouseSensitivity = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY, TBM_GETPOS, 0, 0) + 1;
1253 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSensitivity, SPIF_SENDCHANGE);
1254 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1255 break;
1256 #if 0
1257 case TB_THUMBTRACK:
1258 pOptionData->ulMouseSensitivity = (ULONG)HIWORD(wParam) + 1;
1259 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSensitivity, SPIF_SENDCHANGE);
1260 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1261 break;
1262 #endif
1263 }
1264 }
1265 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL))
1266 {
1267 switch (LOWORD(wParam))
1268 {
1269 case TB_LINEUP:
1270 case TB_LINEDOWN:
1271 case TB_PAGEUP:
1272 case TB_PAGEDOWN:
1273 case TB_TOP:
1274 case TB_BOTTOM:
1275 case TB_ENDTRACK:
1276 pOptionData->uMouseTrails = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_POINTER_TRAIL, TBM_GETPOS, 0, 0) + 2;
1277 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1278 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1279 break;
1280
1281 case TB_THUMBTRACK:
1282 pOptionData->uMouseTrails = (ULONG)HIWORD(wParam) + 2;
1283 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1284 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1285 break;
1286 }
1287 }
1288 break;
1289 }
1290
1291 return FALSE;
1292 }
1293
1294
1295 static VOID
1296 ShowDialogWheelControls(HWND hwndDlg, UINT uWheelScrollLines, BOOL bInit)
1297 {
1298 HWND hDlgCtrl;
1299
1300 if (uWheelScrollLines != WHEEL_PAGESCROLL)
1301 {
1302 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1303 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1304
1305 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1306 EnableWindow(hDlgCtrl, TRUE);
1307
1308 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1309 EnableWindow(hDlgCtrl, TRUE);
1310
1311 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1312 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1313 }
1314 else
1315 {
1316 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1317 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1318
1319 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1320 EnableWindow(hDlgCtrl, FALSE);
1321
1322 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1323 EnableWindow(hDlgCtrl, FALSE);
1324
1325 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1326 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1327
1328 /* Set the default scroll lines value */
1329 if (bInit == TRUE)
1330 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, DEFAULT_WHEEL_SCROLL_LINES, FALSE);
1331 }
1332 }
1333
1334
1335 static INT_PTR CALLBACK
1336 WheelProc(IN HWND hwndDlg,
1337 IN UINT uMsg,
1338 IN WPARAM wParam,
1339 IN LPARAM lParam)
1340 {
1341 LPPSHNOTIFY lppsn;
1342 PWHEEL_DATA pWheelData;
1343
1344 pWheelData = (PWHEEL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1345
1346 switch (uMsg)
1347 {
1348 case WM_INITDIALOG:
1349 pWheelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WHEEL_DATA));
1350 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pWheelData);
1351
1352 /* Get wheel scroll lines */
1353 if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pWheelData->uWheelScrollLines, 0))
1354 {
1355 pWheelData->uWheelScrollLines = DEFAULT_WHEEL_SCROLL_LINES;
1356 }
1357
1358 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, TRUE);
1359 SendDlgItemMessage(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES, UDM_SETRANGE, 0, MAKELONG((short)100, (short)0));
1360 if (pWheelData->uWheelScrollLines != WHEEL_PAGESCROLL)
1361 {
1362 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, pWheelData->uWheelScrollLines, FALSE);
1363 }
1364 return TRUE;
1365
1366 case WM_DESTROY:
1367 HeapFree(GetProcessHeap(), 0, pWheelData);
1368 break;
1369
1370 case WM_COMMAND:
1371 switch (LOWORD(wParam))
1372 {
1373 case IDC_RADIO_WHEEL_SCROLL_LINES:
1374 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1375 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1376 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1377 break;
1378
1379 case IDC_RADIO_WHEEL_SCROLL_PAGE:
1380 pWheelData->uWheelScrollLines = WHEEL_PAGESCROLL;
1381 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1382 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1383 break;
1384
1385 case IDC_EDIT_WHEEL_SCROLL_LINES:
1386 if (pWheelData && HIWORD(wParam) == EN_CHANGE)
1387 {
1388 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1389 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1390 }
1391 break;
1392 }
1393 break;
1394
1395 case WM_NOTIFY:
1396 lppsn = (LPPSHNOTIFY)lParam;
1397 if (lppsn->hdr.code == PSN_APPLY)
1398 {
1399 SystemParametersInfo(SPI_SETWHEELSCROLLLINES, pWheelData->uWheelScrollLines,
1400 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1401 return TRUE;
1402 }
1403 break;
1404 }
1405
1406 return FALSE;
1407 }
1408
1409
1410 LONG APIENTRY
1411 MouseApplet(HWND hwnd, UINT uMsg, LONG lParam1, LONG lParam2)
1412 {
1413 PROPSHEETPAGE psp[5];
1414 PROPSHEETHEADER psh;
1415 TCHAR Caption[256];
1416
1417 UNREFERENCED_PARAMETER(lParam1);
1418 UNREFERENCED_PARAMETER(lParam2);
1419 UNREFERENCED_PARAMETER(uMsg);
1420 UNREFERENCED_PARAMETER(hwnd);
1421
1422 LoadString(hApplet, IDS_CPLNAME_1, Caption, sizeof(Caption) / sizeof(TCHAR));
1423
1424 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
1425 psh.dwSize = sizeof(PROPSHEETHEADER);
1426 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE;
1427 psh.hwndParent = NULL;
1428 psh.hInstance = hApplet;
1429 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_1));
1430 psh.pszCaption = Caption;
1431 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
1432 psh.nStartPage = 0;
1433 psh.ppsp = psp;
1434
1435 InitPropSheetPage(&psp[0], IDD_PAGE_BUTTON, ButtonProc);
1436 InitPropSheetPage(&psp[1], IDD_PAGE_POINTER, PointerProc);
1437 InitPropSheetPage(&psp[2], IDD_PAGE_OPTION, OptionProc);
1438 InitPropSheetPage(&psp[3], IDD_PAGE_WHEEL, WheelProc);
1439 InitPropSheetPage(&psp[4], IDD_HARDWARE, MouseHardwareProc);
1440 return (LONG)(PropertySheet(&psh) != -1);
1441 }
1442
1443 /* EOF */