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