[KSPROXY]
[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 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 /* $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 // add missing icons
30
31 #include <windows.h>
32 #include <winuser.h>
33 #include <devguid.h>
34 #include <commctrl.h>
35 #include <cpl.h>
36 #include <tchar.h>
37 #include <math.h>
38 #include <limits.h>
39 #include <shlobj.h>
40 #include <cplext.h>
41 #include <regstr.h>
42
43 #include <stdio.h>
44
45 #include "main.h"
46 #include "resource.h"
47
48 #define DEFAULT_DOUBLE_CLICK_SPEED 500
49 #define DEFAULT_CLICK_LOCK_TIME 2200
50 #define DEFAULT_MOUSE_SPEED 10
51 #define DEFAULT_MOUSE_ACCELERATION 1
52 #define DEFAULT_MOUSE_THRESHOLD1 6
53 #define DEFAULT_MOUSE_THRESHOLD2 10
54 #define MIN_DOUBLE_CLICK_SPEED 200
55 #define MAX_DOUBLE_CLICK_SPEED 900
56 #define DEFAULT_WHEEL_SCROLL_LINES 3
57
58 typedef struct _BUTTON_DATA
59 {
60 ULONG g_SwapMouseButtons;
61 ULONG g_OrigSwapMouseButtons;
62 ULONG g_DoubleClickSpeed; // = DEFAULT_DOUBLE_CLICK_SPEED;
63 ULONG g_OrigDoubleClickSpeed;
64 BOOL g_ClickLockEnabled; // = 0;
65 DWORD g_ClickLockTime; // = DEFAULT_CLICK_LOCK_TIME;
66
67 HICON hButtonLeft;
68 HICON hButtonRight;
69
70 HICON hIcon1;
71 HICON hIcon2;
72 BOOL bClicked;
73 } BUTTON_DATA, *PBUTTON_DATA;
74
75
76 typedef struct _POINTER_DATA
77 {
78 BOOL bCursorShadow;
79 BOOL bOrigCursorShadow;
80
81 INT cxCursor;
82 INT cyCursor;
83 } POINTER_DATA, *PPOINTER_DATA;
84
85
86 typedef struct _MOUSE_ACCEL
87 {
88 INT nThreshold1;
89 INT nThreshold2;
90 INT nAcceleration;
91 } MOUSE_ACCEL;
92
93 typedef struct _OPTION_DATA
94 {
95 ULONG ulMouseSpeed;
96 ULONG ulOrigMouseSpeed;
97
98 MOUSE_ACCEL MouseAccel;
99 MOUSE_ACCEL OrigMouseAccel;
100
101 BOOL bSnapToDefaultButton;
102 BOOL bOrigSnapToDefaultButton;
103
104 UINT uMouseTrails;
105 UINT uOrigMouseTrails;
106
107 BOOL bMouseVanish;
108 BOOL bOrigMouseVanish;
109
110 BOOL bMouseSonar;
111 BOOL bOrigMouseSonar;
112 } OPTION_DATA, *POPTION_DATA;
113
114
115 typedef struct _WHEEL_DATA
116 {
117 UINT uWheelScrollLines;
118 } WHEEL_DATA, *PWHEEL_DATA;
119
120
121 typedef struct _CURSOR_DATA
122 {
123 UINT uStringId;
124 UINT uDefaultCursorId;
125 LPTSTR lpValueName;
126 HCURSOR hCursor;
127 TCHAR szCursorName[MAX_PATH];
128 TCHAR szCursorPath[MAX_PATH];
129 } CURSOR_DATA, *PCURSOR_DATA;
130
131
132 CURSOR_DATA g_CursorData[] =
133 {{IDS_ARROW, 100/*OCR_NORMAL*/, _T("Arrow"), 0, _T(""), _T("")},
134 {IDS_HELP, 112/*OCR_HELP*/, _T("Help"), 0, _T(""), _T("")},
135 {IDS_APPSTARTING, 111/*OCR_APPSTARTING*/, _T("AppStarting"), 0, _T(""), _T("")},
136 {IDS_WAIT, 102/*OCR_WAIT*/, _T("Wait"), 0, _T(""), _T("")},
137 {IDS_CROSSHAIR, 103/*OCR_CROSS*/, _T("Crosshair"), 0, _T(""), _T("")},
138 {IDS_IBEAM, 101/*OCR_IBEAM*/, _T("IBeam"), 0, _T(""), _T("")},
139 {IDS_NWPEN, 113/*OCR_NWPEN*/, _T("NWPen"), 0, _T(""), _T("")},
140 {IDS_NO, 110/*OCR_NO*/, _T("No"), 0, _T(""), _T("")},
141 {IDS_SIZENS, 108/*OCR_SIZENS*/, _T("SizeNS"), 0, _T(""), _T("")},
142 {IDS_SIZEWE, 107/*OCR_SIZEWE*/, _T("SizeWE"), 0, _T(""), _T("")},
143 {IDS_SIZENWSE, 105/*OCR_SIZENWSE*/, _T("SizeNWSE"), 0, _T(""), _T("")},
144 {IDS_SIZENESW, 106/*OCR_SIZENESW*/, _T("SizeNESW"), 0, _T(""), _T("")},
145 {IDS_SIZEALL, 109/*OCR_SIZEALL*/, _T("SizeAll"), 0, _T(""), _T("")},
146 {IDS_UPARROW, 104/*OCR_UP*/, _T("UpArrow"), 0, _T(""), _T("")},
147 {IDS_HAND, 114/*OCR_HAND*/, _T("Hand"), 0, _T(""), _T("")}};
148
149
150 #if 0
151 static VOID
152 DebugMsg(LPTSTR fmt, ...)
153 {
154 TCHAR szBuffer[2048];
155 va_list marker;
156
157 va_start(marker, fmt);
158 _vstprintf(szBuffer, fmt, marker);
159 va_end(marker);
160
161 MessageBox(NULL, szBuffer, _T("Debug message"), MB_OK);
162 }
163 #endif
164
165
166 /* Property page dialog callback */
167 static INT_PTR CALLBACK
168 MouseHardwareProc(IN HWND hwndDlg,
169 IN UINT uMsg,
170 IN WPARAM wParam,
171 IN LPARAM lParam)
172 {
173 GUID Guids[1];
174 Guids[0] = GUID_DEVCLASS_MOUSE;
175
176 UNREFERENCED_PARAMETER(lParam);
177 UNREFERENCED_PARAMETER(wParam);
178
179 switch(uMsg)
180 {
181 case WM_INITDIALOG:
182 /* create the hardware page */
183 DeviceCreateHardwarePageEx(hwndDlg,
184 Guids,
185 sizeof(Guids) / sizeof(Guids[0]),
186 HWPD_STANDARDLIST);
187 break;
188 }
189
190 return FALSE;
191 }
192
193
194 static INT_PTR CALLBACK
195 ClickLockProc(IN HWND hwndDlg,
196 IN UINT uMsg,
197 IN WPARAM wParam,
198 IN LPARAM lParam)
199 {
200 HWND hDlgCtrl;
201 int pos;
202 static HICON hIcon;
203
204 PBUTTON_DATA pButtonData;
205
206 pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
207
208 switch(uMsg)
209 {
210 case WM_INITDIALOG:
211 pButtonData = (PBUTTON_DATA)lParam;
212 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData);
213
214 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK);
215 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10));
216 pos = (pButtonData->g_ClickLockTime - 200) / 200;
217 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
218
219 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_LOOK_KEY),
220 IMAGE_ICON, 16, 16, 0);
221 SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
222 return TRUE;
223
224 case WM_COMMAND:
225 if (LOWORD(wParam) == IDOK)
226 {
227 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK);
228 pButtonData->g_ClickLockTime = (DWORD) (SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) * 200) + 200;
229 EndDialog(hwndDlg, TRUE);
230 if (hIcon) DestroyIcon(hIcon);
231 }
232 else if (LOWORD(wParam) == IDCANCEL)
233 {
234 EndDialog(hwndDlg, FALSE);
235 if (hIcon) DestroyIcon(hIcon);
236 }
237 break;
238 }
239
240 return FALSE;
241 }
242
243
244 static INT_PTR CALLBACK
245 ButtonProc(IN HWND hwndDlg,
246 IN UINT uMsg,
247 IN WPARAM wParam,
248 IN LPARAM lParam)
249 {
250 HWND hDlgCtrl;
251 LRESULT lResult;
252 LPPSHNOTIFY lppsn;
253
254 PBUTTON_DATA pButtonData;
255
256 pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
257
258 switch (uMsg)
259 {
260 case WM_INITDIALOG:
261 pButtonData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BUTTON_DATA));
262 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData);
263
264 pButtonData->g_SwapMouseButtons = GetSystemMetrics(SM_SWAPBUTTON);
265 pButtonData->g_OrigSwapMouseButtons = pButtonData->g_SwapMouseButtons;
266 pButtonData->g_DoubleClickSpeed = GetDoubleClickTime();
267 pButtonData->g_OrigDoubleClickSpeed = pButtonData->g_DoubleClickSpeed;
268
269 /* Click lock time */
270 SystemParametersInfo(SPI_GETMOUSECLICKLOCK, 0, &pButtonData->g_ClickLockEnabled, 0);
271 SystemParametersInfo(SPI_GETMOUSECLICKLOCKTIME, 0, &pButtonData->g_ClickLockTime, 0);
272
273 /* Load mouse button icons */
274 pButtonData->hButtonLeft = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_LEFT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
275 pButtonData->hButtonRight = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_RIGHT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
276
277 /* Load folder icons */
278 pButtonData->hIcon1 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_CLOSED), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
279 pButtonData->hIcon2 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_OPEN), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
280
281 if (pButtonData->g_SwapMouseButtons)
282 {
283 SendDlgItemMessage(hwndDlg, IDC_SWAP_MOUSE_BUTTONS, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
284 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight);
285 }
286 else
287 {
288 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft);
289 }
290
291 if (pButtonData->g_ClickLockEnabled)
292 {
293 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_CLICK_LOCK);
294 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
295 }
296 else
297 {
298 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK);
299 EnableWindow(hDlgCtrl, FALSE);
300 }
301
302 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED);
303 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 14));
304 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, 14 - ((pButtonData->g_DoubleClickSpeed - 200) / 50));
305
306
307 SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hIcon1);
308 pButtonData->bClicked = TRUE;
309 return TRUE;
310
311 case WM_DESTROY:
312 DestroyIcon(pButtonData->hButtonLeft);
313 DestroyIcon(pButtonData->hButtonRight);
314 DestroyIcon(pButtonData->hIcon1);
315 DestroyIcon(pButtonData->hIcon2);
316 HeapFree(GetProcessHeap(), 0, pButtonData);
317 break;
318
319 case WM_COMMAND:
320 switch(LOWORD(wParam))
321 {
322 case IDC_SWAP_MOUSE_BUTTONS:
323 lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
324 if (lResult == BST_CHECKED)
325 {
326 pButtonData->g_SwapMouseButtons = FALSE;
327 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
328 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft);
329 }
330 else if (lResult == BST_UNCHECKED)
331 {
332 pButtonData->g_SwapMouseButtons = TRUE;
333 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
334 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight);
335 }
336 //SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_SwapMouseButtons, NULL, 0);
337 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
338 break;
339
340 case IDC_CHECK_CLICK_LOCK:
341 lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
342 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK);
343 if (lResult == BST_CHECKED)
344 {
345 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
346 pButtonData->g_ClickLockEnabled = FALSE;
347 EnableWindow(hDlgCtrl, FALSE);
348 }
349 else if (lResult == BST_UNCHECKED)
350 {
351 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
352 pButtonData->g_ClickLockEnabled = TRUE;
353 EnableWindow(hDlgCtrl, TRUE);
354 }
355 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
356 break;
357
358 case IDC_BUTTON_CLICK_LOCK:
359 DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CLICK_LOCK), hwndDlg, ClickLockProc, (LPARAM)pButtonData);
360 break;
361
362 case IDC_IMAGE_DOUBLE_CLICK_SPEED:
363 if (HIWORD(wParam) == STN_DBLCLK)
364 {
365 pButtonData->bClicked = !pButtonData->bClicked;
366 SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON,
367 (LPARAM)(pButtonData->bClicked ? pButtonData->hIcon1 : pButtonData->hIcon2));
368 }
369 break;
370 }
371 break;
372
373 case WM_NOTIFY:
374 lppsn = (LPPSHNOTIFY) lParam;
375 if (lppsn->hdr.code == PSN_APPLY)
376 {
377 if (pButtonData->g_OrigSwapMouseButtons != pButtonData->g_SwapMouseButtons)
378 {
379 pButtonData->g_OrigSwapMouseButtons = pButtonData->g_SwapMouseButtons;
380 SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_OrigSwapMouseButtons, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
381
382 }
383 SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
384 //SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
385
386 #if (WINVER >= 0x0500)
387 SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, UlongToPtr(pButtonData->g_ClickLockEnabled), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
388 if (pButtonData->g_ClickLockEnabled)
389 SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, pButtonData->g_ClickLockTime, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
390 #endif
391 }
392 else if (lppsn->hdr.code == PSN_RESET)
393 {
394 /* Reset swap mouse button setting */
395 SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_OrigSwapMouseButtons, NULL, 0);
396
397 /* Reset double click speed setting */
398 SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_OrigDoubleClickSpeed, NULL, 0);
399 //SetDoubleClickTime(pButtonData->g_OrigDoubleClickSpeed);
400 }
401 return TRUE;
402
403 case WM_HSCROLL:
404 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED))
405 {
406 switch (LOWORD(wParam))
407 {
408 case TB_LINEUP:
409 case TB_LINEDOWN:
410 case TB_PAGEUP:
411 case TB_PAGEDOWN:
412 case TB_TOP:
413 case TB_BOTTOM:
414 case TB_ENDTRACK:
415 lResult = SendDlgItemMessage(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED, TBM_GETPOS, 0, 0);
416 pButtonData->g_DoubleClickSpeed = (14 - (INT)lResult) * 50 + 200;
417 //SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
418 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
419 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
420 break;
421
422 case TB_THUMBTRACK:
423 pButtonData->g_DoubleClickSpeed = (14 - (INT)HIWORD(wParam)) * 50 + 200;
424 //SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, 0);
425 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
426 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
427 break;
428 }
429 }
430 break;
431 }
432
433 return FALSE;
434 }
435
436
437 static VOID
438 CompressPath(LPTSTR lpShortPath, LPTSTR lpPath)
439 {
440 TCHAR szUserProfile[MAX_PATH];
441 TCHAR szSystemRoot[MAX_PATH];
442 TCHAR szProgramFiles[MAX_PATH];
443 DWORD dwUserProfile;
444 DWORD dwSystemRoot;
445 DWORD dwProgramFiles;
446
447 dwUserProfile = GetEnvironmentVariable(_T("USERPROFILE"), szUserProfile, MAX_PATH);
448 dwSystemRoot = GetEnvironmentVariable(_T("SystemRoot"), szSystemRoot, MAX_PATH);
449 dwProgramFiles = GetEnvironmentVariable(_T("ProgramFiles"), szProgramFiles, MAX_PATH);
450
451 if (dwUserProfile > 0 && _tcsncmp(lpPath, szUserProfile, dwUserProfile) == 0)
452 {
453 _tcscpy(lpShortPath, _T("%USERPROFILE%"));
454 _tcscat(lpShortPath, &lpPath[dwUserProfile]);
455 }
456 else if (dwSystemRoot > 0 && _tcsncmp(lpPath, szSystemRoot, dwSystemRoot) == 0)
457 {
458 _tcscpy(lpShortPath, _T("%SystemRoot%"));
459 _tcscat(lpShortPath, &lpPath[dwSystemRoot]);
460 }
461 else if (dwProgramFiles > 0 && _tcsncmp(lpPath, szProgramFiles, dwProgramFiles) == 0)
462 {
463 _tcscpy(lpShortPath, _T("%ProgramFiles%"));
464 _tcscat(lpShortPath, &lpPath[dwProgramFiles]);
465 }
466 else
467 {
468 _tcscpy(lpShortPath, lpPath);
469 }
470 }
471
472
473 static BOOL
474 EnumerateCursorSchemes(HWND hwndDlg)
475 {
476 HKEY hCursorKey;
477 DWORD dwIndex;
478 TCHAR szValueName[MAX_PATH];
479 DWORD dwValueName;
480 TCHAR szSystemScheme[MAX_PATH];
481 TCHAR szValueData[2000];
482 TCHAR szTempData[2000];
483 DWORD dwValueData;
484 LONG lError;
485 HWND hDlgCtrl;
486 LRESULT lResult;
487
488 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
489 SendMessage(hDlgCtrl, CB_RESETCONTENT, 0, 0);
490
491 /* Read the users cursor schemes */
492 lError = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors\\Schemes"),
493 0, KEY_READ | KEY_QUERY_VALUE , &hCursorKey);
494 if (lError == ERROR_SUCCESS)
495 {
496 for (dwIndex = 0;; dwIndex++)
497 {
498 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
499 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
500 lError = RegEnumValue(hCursorKey, dwIndex, szValueName, &dwValueName,
501 NULL, NULL, (LPBYTE)szValueData, &dwValueData);
502 if (lError == ERROR_NO_MORE_ITEMS)
503 break;
504
505 ExpandEnvironmentStrings(szValueData, szTempData, 2000);
506
507 if (_tcslen(szTempData) > 0)
508 {
509 LPTSTR lpCopy, lpStart;
510
511 /* Remove quotation marks */
512 if (szTempData[0] == _T('"'))
513 {
514 lpStart = szValueData + 1;
515 szTempData[_tcslen(szTempData) - 1] = 0;
516 }
517 else
518 {
519 lpStart = szTempData;
520 }
521
522 lpCopy = _tcsdup(lpStart);
523
524 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName);
525 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)lpCopy);
526 }
527 }
528
529 RegCloseKey(hCursorKey);
530 }
531
532 /* Read the system cursor schemes */
533 lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
534 _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes"),
535 0, KEY_READ | KEY_QUERY_VALUE , &hCursorKey);
536 if (lError == ERROR_SUCCESS)
537 {
538 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
539
540 for (dwIndex = 0;; dwIndex++)
541 {
542 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
543 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
544 lError = RegEnumValue(hCursorKey, dwIndex, szValueName, &dwValueName,
545 NULL, NULL, (LPBYTE)szValueData, &dwValueData);
546 if (lError == ERROR_NO_MORE_ITEMS)
547 break;
548
549 if (_tcslen(szValueData) > 0)
550 {
551 LPTSTR lpCopy, lpStart;
552
553 /* Remove quotation marks */
554 if (szValueData[0] == _T('"'))
555 {
556 lpStart = szValueData + 1;
557 szValueData[_tcslen(szValueData) - 1] = 0;
558 }
559 else
560 {
561 lpStart = szValueData;
562 }
563
564 lpCopy = _tcsdup(lpStart);
565
566 _tcscat(szValueName, TEXT(" "));
567 _tcscat(szValueName, szSystemScheme);
568
569 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName);
570 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)lpCopy);
571 }
572 }
573
574 RegCloseKey(hCursorKey);
575 }
576
577 /* Add the "(none)" entry */
578 LoadString(hApplet, IDS_NONE, szSystemScheme, MAX_PATH);
579 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szSystemScheme);
580 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)NULL);
581
582 return TRUE;
583 }
584
585
586 static VOID
587 RefreshCursorList(HWND hwndDlg, BOOL bInit)
588 {
589 INT index;
590 INT i;
591 INT nSel;
592
593 nSel = bInit ? 0 : SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
594
595 if (bInit)
596 {
597 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_RESETCONTENT, 0, 0);
598 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
599 {
600 LoadString(hApplet, index, g_CursorData[i].szCursorName, MAX_PATH);
601 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_ADDSTRING, 0, (LPARAM)i);
602 }
603
604 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_SETCURSEL, nSel, 0);
605 }
606 else
607 {
608 InvalidateRect(GetDlgItem(hwndDlg, IDC_LISTBOX_CURSOR), NULL, FALSE);
609 }
610
611 SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR,
612 (LPARAM)g_CursorData[nSel].hCursor);
613
614 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), (g_CursorData[nSel].szCursorPath[0] != 0));
615 }
616
617
618 static BOOL
619 DeleteUserCursorScheme(HWND hwndDlg)
620 {
621 TCHAR szSchemeName[MAX_PATH];
622 TCHAR szTitle[128];
623 TCHAR szRawText[256];
624 TCHAR szText[256];
625 HWND hDlgCtrl;
626 HKEY hCuKey;
627 HKEY hCuCursorKey;
628 LONG lResult;
629 INT nSel;
630
631 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
632 nSel = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
633 if (nSel == CB_ERR)
634 return FALSE;
635
636 SendMessage(hDlgCtrl, CB_GETLBTEXT, nSel, (LPARAM)szSchemeName);
637
638 LoadString(hApplet, IDS_REMOVE_TITLE, szTitle, 128);
639 LoadString(hApplet, IDS_REMOVE_TEXT, szRawText, 256);
640
641 _stprintf(szText, szRawText, szSchemeName);
642
643 /* Confirm scheme removal */
644 if (MessageBox(hwndDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO)
645 return TRUE;
646
647 if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS)
648 return FALSE;
649
650 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS)
651 {
652 RegCloseKey(hCuKey);
653 return FALSE;
654 }
655
656 lResult = RegDeleteValue(hCuCursorKey, szSchemeName);
657
658 RegCloseKey(hCuCursorKey);
659 RegCloseKey(hCuKey);
660
661 if (lResult == ERROR_SUCCESS)
662 {
663 SendMessage(hDlgCtrl, CB_DELETESTRING, nSel, 0);
664 SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
665 }
666
667 return (lResult == ERROR_SUCCESS);
668 }
669
670
671 static INT_PTR CALLBACK
672 SaveSchemeProc(IN HWND hwndDlg,
673 IN UINT uMsg,
674 IN WPARAM wParam,
675 IN LPARAM lParam)
676 {
677 LPTSTR pSchemeName;
678
679 switch (uMsg)
680 {
681 case WM_INITDIALOG:
682 pSchemeName = (LPTSTR)lParam;
683 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSchemeName);
684 SendDlgItemMessage(hwndDlg, IDC_EDIT_SCHEME_NAME, WM_SETTEXT,
685 0, (LPARAM)pSchemeName);
686 break;
687
688 case WM_COMMAND:
689 if (LOWORD(wParam) == IDOK)
690 {
691 pSchemeName = (LPTSTR)GetWindowLongPtr(hwndDlg, DWLP_USER);
692 SendDlgItemMessage(hwndDlg, IDC_EDIT_SCHEME_NAME, WM_GETTEXT,
693 (WPARAM)MAX_PATH, (LPARAM)pSchemeName);
694 EndDialog(hwndDlg, TRUE);
695 }
696 else if (LOWORD(wParam) == IDCANCEL)
697 {
698 EndDialog(hwndDlg, FALSE);
699 }
700 break;
701 }
702
703 return FALSE;
704 }
705
706
707 static BOOL
708 SaveCursorScheme(HWND hwndDlg)
709 {
710 TCHAR szSystemScheme[MAX_PATH];
711 TCHAR szSchemeName[MAX_PATH];
712 TCHAR szNewSchemeName[MAX_PATH];
713 TCHAR szTempPath[MAX_PATH];
714 TCHAR szTitle[128];
715 TCHAR szText[256];
716 INT nSel;
717 INT index, i, nLength;
718 LPTSTR lpSchemeData;
719 HKEY hCuKey;
720 HKEY hCuCursorKey;
721 LONG lError = ERROR_SUCCESS;
722 BOOL bSchemeExists;
723
724 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
725
726 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
727 if (nSel == CB_ERR)
728 return FALSE;
729
730 if (nSel == 0)
731 {
732 szSchemeName[0] = 0;
733 }
734 else
735 {
736 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szNewSchemeName);
737
738 if (_tcsstr(szNewSchemeName, szSystemScheme))
739 {
740 szNewSchemeName[_tcslen(szNewSchemeName) - _tcslen(szSystemScheme) - 1] = 0;
741 }
742 }
743
744 /* Ask for a name for the new cursor scheme */
745 if (!DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CURSOR_SCHEME_SAVEAS),
746 hwndDlg, SaveSchemeProc, (LPARAM)szNewSchemeName))
747 return TRUE;
748
749 /* Check all non-system schemes for the new name */
750 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCOUNT, 0, 0);
751 if (nSel == CB_ERR)
752 return FALSE;
753
754 bSchemeExists = FALSE;
755 for (i = 0; i < nSel; i++)
756 {
757 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, i, (LPARAM)szSchemeName);
758 if (_tcsstr(szSchemeName, szSystemScheme) == NULL)
759 {
760 if (_tcscmp(szSchemeName, szNewSchemeName) == 0)
761 {
762 bSchemeExists = TRUE;
763 break;
764 }
765 }
766 }
767
768 if (bSchemeExists)
769 {
770 LoadString(hApplet, IDS_OVERWRITE_TITLE, szTitle, 128);
771 LoadString(hApplet, IDS_OVERWRITE_TEXT, szText, 256);
772
773 /* Confirm scheme overwrite */
774 if (MessageBox(hwndDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO)
775 return TRUE;
776 }
777
778 /* Save the cursor scheme */
779 nLength = 0;
780 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
781 {
782 if (i > 0)
783 nLength++;
784 nLength += _tcslen(g_CursorData[i].szCursorPath);
785 }
786 nLength++;
787
788 lpSchemeData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(TCHAR));
789
790 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
791 {
792 CompressPath(szTempPath, g_CursorData[i].szCursorPath);
793 if (i > 0)
794 _tcscat(lpSchemeData, _T(","));
795 _tcscat(lpSchemeData, szTempPath);
796 }
797
798 if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS)
799 return FALSE;
800
801 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS)
802 {
803 RegCloseKey(hCuKey);
804 return FALSE;
805 }
806
807 lError = RegSetValueEx(hCuCursorKey, szNewSchemeName, 0,
808 REG_EXPAND_SZ, (LPBYTE)lpSchemeData,
809 (_tcslen(lpSchemeData) + 1) * sizeof(TCHAR));
810
811 RegCloseKey(hCuCursorKey);
812 RegCloseKey(hCuKey);
813
814 /* Add the new scheme to the scheme list and select it */
815 if (lError == ERROR_SUCCESS)
816 {
817 LPTSTR copy = _tcsdup(lpSchemeData);
818
819 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_ADDSTRING, (WPARAM)0, (LPARAM)szNewSchemeName);
820 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETITEMDATA, (WPARAM)nSel, (LPARAM)copy);
821 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0);
822 }
823
824 HeapFree(GetProcessHeap(), 0, lpSchemeData);
825
826 return (lError == ERROR_SUCCESS);
827 }
828
829
830 static BOOL
831 BrowseCursor(HWND hwndDlg)
832 {
833 TCHAR szFileName[MAX_PATH];
834 TCHAR szFilter[MAX_PATH];
835 TCHAR szTitle[MAX_PATH];
836 OPENFILENAME ofn;
837 INT nSel;
838
839 LoadString(hApplet, IDS_BROWSE_FILTER, szFilter, MAX_PATH);
840 LoadString(hApplet, IDS_BROWSE_TITLE, szTitle, MAX_PATH);
841
842 memset(szFileName, 0x0, sizeof(szFileName));
843 nSel = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
844 if (nSel == LB_ERR)
845 {
846 MessageBox(hwndDlg, _T("LB_ERR"), _T(""), MB_ICONERROR);
847 return FALSE;
848 }
849
850 ZeroMemory(&ofn, sizeof(OPENFILENAME));
851 ofn.lStructSize = sizeof(OPENFILENAME);
852 ofn.hwndOwner = hwndDlg;
853 ofn.lpstrFilter = szFilter;
854 ofn.nFilterIndex = 1;
855 ofn.lpstrFile = szFileName;
856 ofn.nMaxFile = MAX_PATH;
857 ofn.lpstrInitialDir = _T("%WINDIR%\\Cursors");
858 ofn.lpstrTitle = szTitle;
859 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
860
861 if (!GetOpenFileName(&ofn))
862 return FALSE;
863
864 /* Store the new cursor file path */
865 _tcsncpy(g_CursorData[nSel].szCursorPath, szFileName, MAX_PATH);
866
867 return TRUE;
868 }
869
870
871 static VOID
872 LoadCursorScheme(LPTSTR lpName, BOOL bSystem)
873 {
874 UINT index, i;
875
876 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
877 {
878 if (g_CursorData[i].hCursor != NULL)
879 {
880 DestroyCursor(g_CursorData[i].hCursor);
881 g_CursorData[i].hCursor = 0;
882 }
883 g_CursorData[i].szCursorPath[0] = 0;
884 }
885
886 if (lpName != NULL)
887 {
888 LPTSTR pStart = lpName;
889 LPTSTR pEnd = pStart;
890 INT nLength;
891
892 i = 0;
893 while (pEnd)
894 {
895 pEnd = _tcschr(pStart, _T(','));
896 if (pEnd)
897 nLength = ((INT_PTR)pEnd - (INT_PTR)pStart) / sizeof(TCHAR);
898 else
899 nLength = _tcslen(pStart);
900
901 _tcsncpy(g_CursorData[i].szCursorPath, pStart, nLength);
902 g_CursorData[i].szCursorPath[nLength] = 0;
903
904 pStart = pStart + (nLength + 1);
905 i++;
906 }
907
908 }
909
910 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
911 {
912 if (g_CursorData[i].szCursorPath[0] == 0)
913 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId),
914 IMAGE_CURSOR, 0, 0,
915 LR_DEFAULTSIZE | LR_SHARED);
916 else
917 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
918 IMAGE_CURSOR, 0, 0,
919 LR_LOADFROMFILE | LR_DEFAULTSIZE);
920 }
921 }
922
923
924 static VOID
925 ReloadCurrentCursorScheme(VOID)
926 {
927 UINT index, i;
928
929 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
930 {
931 if (g_CursorData[i].hCursor != NULL)
932 DestroyCursor(g_CursorData[i].hCursor);
933
934 if (g_CursorData[i].szCursorPath[0] == 0)
935 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId),
936 IMAGE_CURSOR, 0, 0,
937 LR_DEFAULTSIZE | LR_SHARED);
938 else
939 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
940 IMAGE_CURSOR, 0, 0,
941 LR_LOADFROMFILE | LR_DEFAULTSIZE);
942 }
943 }
944
945
946 static VOID
947 OnDrawItem(UINT idCtl,
948 LPDRAWITEMSTRUCT lpdis,
949 PPOINTER_DATA pPointerData)
950 {
951 RECT rc;
952
953 if (lpdis->itemState & ODS_SELECTED)
954 {
955 FillRect(lpdis->hDC,
956 &lpdis->rcItem,
957 (HBRUSH)(COLOR_HIGHLIGHT + 1));
958 SetBkColor(lpdis->hDC,
959 GetSysColor(COLOR_HIGHLIGHT));
960 SetTextColor(lpdis->hDC,
961 GetSysColor(COLOR_HIGHLIGHTTEXT));
962 }
963 else
964 {
965 FillRect(lpdis->hDC,
966 &lpdis->rcItem,
967 (HBRUSH)(COLOR_WINDOW + 1));
968 SetBkColor(lpdis->hDC,
969 GetSysColor(COLOR_WINDOW));
970 SetTextColor(lpdis->hDC,
971 GetSysColor(COLOR_WINDOWTEXT));
972 }
973
974 if (lpdis->itemID != (UINT)-1)
975 {
976 CopyRect(&rc, &lpdis->rcItem);
977 rc.left += 5;
978 DrawText(lpdis->hDC,
979 g_CursorData[lpdis->itemData].szCursorName,
980 -1,
981 &rc,
982 DT_SINGLELINE | DT_VCENTER | DT_LEFT);
983
984 if (g_CursorData[lpdis->itemData].hCursor != NULL)
985 {
986 DrawIcon(lpdis->hDC,
987 lpdis->rcItem.right - pPointerData->cxCursor - 4,
988 lpdis->rcItem.top + 2,
989 g_CursorData[lpdis->itemData].hCursor);
990 }
991 }
992
993 if (lpdis->itemState & ODS_FOCUS)
994 {
995 CopyRect(&rc, &lpdis->rcItem);
996 InflateRect(&rc, -1, -1);
997 DrawFocusRect(lpdis->hDC, &rc);
998 }
999 }
1000
1001
1002 static VOID
1003 LoadNewCursorScheme(HWND hwndDlg)
1004 {
1005 TCHAR buffer[MAX_PATH];
1006 TCHAR szSystemScheme[MAX_PATH];
1007 HWND hDlgCtrl;
1008 BOOL bEnable;
1009 LPTSTR lpName;
1010 INT nSel;
1011
1012 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
1013 if (nSel == CB_ERR)
1014 return;
1015
1016 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)buffer);
1017
1018 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1019 if (_tcsstr(buffer, szSystemScheme) || nSel == 0) //avoid the default scheme can be deleted
1020 bEnable = FALSE;
1021 else
1022 bEnable = TRUE;
1023
1024 /* delete button */
1025 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME);
1026 EnableWindow(hDlgCtrl, bEnable);
1027
1028 lpName = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0);
1029 LoadCursorScheme(lpName, !bEnable);
1030 RefreshCursorList(hwndDlg, FALSE);
1031 }
1032
1033
1034 static VOID
1035 LoadInitialCursorScheme(HWND hwndDlg)
1036 {
1037 TCHAR szSchemeName[256];
1038 TCHAR szSystemScheme[256];
1039 TCHAR szCursorPath[256];
1040 HKEY hCursorKey;
1041 LONG lError;
1042 DWORD dwDataSize;
1043 DWORD dwSchemeSource = 0;
1044 UINT index, i;
1045 DWORD dwType;
1046 INT nSel;
1047
1048 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1049 {
1050 g_CursorData[i].hCursor = 0;
1051 g_CursorData[i].szCursorPath[0] = 0;
1052 }
1053
1054 lError = RegOpenKeyEx(HKEY_CURRENT_USER,
1055 _T("Control Panel\\Cursors"),
1056 0,
1057 KEY_READ | KEY_QUERY_VALUE,
1058 &hCursorKey);
1059 if (lError != ERROR_SUCCESS)
1060 return;
1061
1062 dwDataSize = sizeof(DWORD);
1063 lError = RegQueryValueEx(hCursorKey,
1064 _T("Scheme Source"),
1065 NULL,
1066 NULL,
1067 (LPBYTE)&dwSchemeSource,
1068 &dwDataSize);
1069
1070 if (dwSchemeSource != 0)
1071 {
1072 dwDataSize = 256 * sizeof(TCHAR);
1073 lError = RegQueryValueEx(hCursorKey,
1074 NULL,
1075 NULL,
1076 NULL,
1077 (LPBYTE)szSchemeName,
1078 &dwDataSize);
1079
1080 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1081 {
1082 dwDataSize = MAX_PATH * sizeof(TCHAR);
1083 lError = RegQueryValueEx(hCursorKey,
1084 g_CursorData[i].lpValueName,
1085 NULL,
1086 &dwType,
1087 (LPBYTE)szCursorPath,
1088 &dwDataSize);
1089 if (lError == ERROR_SUCCESS)
1090 {
1091 if (dwType == REG_EXPAND_SZ)
1092 {
1093 ExpandEnvironmentStrings(szCursorPath, g_CursorData[i].szCursorPath, MAX_PATH);
1094 }
1095 else
1096 {
1097 _tcscpy(g_CursorData[i].szCursorPath, szCursorPath);
1098 }
1099 }
1100 }
1101 }
1102
1103 RegCloseKey(hCursorKey);
1104
1105 ReloadCurrentCursorScheme();
1106 RefreshCursorList(hwndDlg, TRUE);
1107
1108 /* Build the full scheme name */
1109 if (dwSchemeSource == 0)
1110 {
1111 LoadString(hApplet, IDS_NONE, szSchemeName, MAX_PATH);
1112 }
1113 else if (dwSchemeSource == 2)
1114 {
1115 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1116 _tcscat(szSchemeName, _T(" "));
1117 _tcscat(szSchemeName, szSystemScheme);
1118 }
1119
1120 /* Search and select the curent scheme name from the scheme list */
1121 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_FINDSTRINGEXACT, -1, (LPARAM)szSchemeName);
1122 if (nSel != CB_ERR)
1123 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0);
1124
1125 /* Enable /disable delete button */
1126 EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME), (dwSchemeSource == 1));
1127 }
1128
1129
1130 static BOOL
1131 ApplyCursorScheme(HWND hwndDlg)
1132 {
1133 TCHAR szSchemeName[MAX_PATH];
1134 TCHAR szSystemScheme[MAX_PATH];
1135 TCHAR szTempPath[MAX_PATH];
1136 LPTSTR lpSchemeData;
1137 DWORD dwNameLength;
1138 DWORD dwSchemeSource;
1139 UINT index, i;
1140 HKEY hCursorKey;
1141 INT nSel;
1142
1143 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
1144 if (nSel == CB_ERR)
1145 return FALSE;
1146
1147 lpSchemeData = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0);
1148 if (lpSchemeData == NULL)
1149 {
1150 /* "None" cursor scheme */
1151 dwSchemeSource = 0;
1152 szSchemeName[0] = 0;
1153 dwNameLength = 0;
1154 }
1155 else
1156 {
1157 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szSchemeName);
1158 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1159
1160 if (_tcsstr(szSchemeName, szSystemScheme))
1161 {
1162 /* System scheme */
1163 dwSchemeSource = 2;
1164 szSchemeName[_tcslen(szSchemeName) - _tcslen(szSystemScheme) - 1] = 0;
1165 }
1166 else
1167 {
1168 /* User scheme */
1169 dwSchemeSource = 1;
1170 }
1171
1172 dwNameLength = (_tcslen(szSchemeName) + 1) * sizeof(TCHAR);
1173 }
1174
1175 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors"), 0,
1176 KEY_READ | KEY_SET_VALUE, &hCursorKey) != ERROR_SUCCESS)
1177 return FALSE;
1178
1179 RegSetValueEx(hCursorKey, NULL, 0, REG_SZ,
1180 (LPBYTE)szSchemeName, dwNameLength);
1181
1182 RegSetValueEx(hCursorKey, _T("Scheme Source"), 0, REG_DWORD,
1183 (LPBYTE)&dwSchemeSource, sizeof(DWORD));
1184
1185 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1186 {
1187 CompressPath(szTempPath, g_CursorData[i].szCursorPath);
1188 RegSetValueEx(hCursorKey, g_CursorData[i].lpValueName, 0,
1189 REG_EXPAND_SZ, (LPBYTE)szTempPath,
1190 (_tcslen(szTempPath) + 1) * sizeof(TCHAR));
1191 }
1192
1193 RegCloseKey(hCursorKey);
1194
1195 /* Force the system to reload its cursors */
1196 SystemParametersInfo(SPI_SETCURSORS, 0, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1197
1198 return TRUE;
1199 }
1200
1201
1202 static INT_PTR CALLBACK
1203 PointerProc(IN HWND hwndDlg,
1204 IN UINT uMsg,
1205 IN WPARAM wParam,
1206 IN LPARAM lParam)
1207 {
1208 PPOINTER_DATA pPointerData;
1209 LPPSHNOTIFY lppsn;
1210 INT nSel;
1211
1212 pPointerData = (PPOINTER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1213
1214 switch (uMsg)
1215 {
1216 case WM_INITDIALOG:
1217 pPointerData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(POINTER_DATA));
1218 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pPointerData);
1219
1220 pPointerData->cxCursor = GetSystemMetrics(SM_CXCURSOR);
1221 pPointerData->cyCursor = GetSystemMetrics(SM_CYCURSOR);
1222
1223 EnumerateCursorSchemes(hwndDlg);
1224 LoadInitialCursorScheme(hwndDlg);
1225
1226 /* Get cursor shadow setting */
1227 SystemParametersInfo(SPI_GETCURSORSHADOW, 0, &pPointerData->bCursorShadow, 0);
1228 pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow;
1229
1230 if (pPointerData->bCursorShadow)
1231 {
1232 SendDlgItemMessage(hwndDlg, IDC_CHECK_CURSOR_SHADOW, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1233 }
1234
1235 if ((INT)wParam == IDC_LISTBOX_CURSOR)
1236 return TRUE;
1237 else
1238 return FALSE;
1239
1240 case WM_MEASUREITEM:
1241 ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = GetSystemMetrics(SM_CYCURSOR) + 4;
1242 break;
1243
1244 case WM_DRAWITEM:
1245 if (wParam == IDC_LISTBOX_CURSOR)
1246 OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam, pPointerData);
1247 return TRUE;
1248
1249 case WM_DESTROY:
1250 HeapFree(GetProcessHeap(), 0, pPointerData);
1251 break;
1252
1253 case WM_NOTIFY:
1254 lppsn = (LPPSHNOTIFY) lParam;
1255 if (lppsn->hdr.code == PSN_APPLY)
1256 {
1257 ApplyCursorScheme(hwndDlg);
1258 //#if (WINVER >= 0x0500)
1259 if (pPointerData->bOrigCursorShadow != pPointerData->bCursorShadow)
1260 {
1261 SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1262 pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow;
1263 }
1264 //#endif
1265 return TRUE;
1266 }
1267 else if (lppsn->hdr.code == PSN_RESET)
1268 {
1269 //#if (WINVER >= 0x0500)
1270 SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bOrigCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1271 //#endif
1272 }
1273 break;
1274
1275 case WM_COMMAND:
1276 switch (LOWORD(wParam))
1277 {
1278 case IDC_COMBO_CURSOR_SCHEME:
1279 if (HIWORD(wParam) == CBN_SELENDOK)
1280 {
1281 LoadNewCursorScheme(hwndDlg);
1282 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1283 }
1284 break;
1285
1286 case IDC_LISTBOX_CURSOR:
1287 switch (HIWORD(wParam))
1288 {
1289 case LBN_SELCHANGE:
1290 nSel = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
1291 SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR,
1292 (LPARAM)g_CursorData[nSel].hCursor);
1293 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR),
1294 (g_CursorData[nSel].szCursorPath[0] != 0));
1295 break;
1296
1297 case LBN_DBLCLK:
1298 if (BrowseCursor(hwndDlg))
1299 {
1300 /* Update cursor list and preview */
1301 ReloadCurrentCursorScheme();
1302 RefreshCursorList(hwndDlg, FALSE);
1303
1304 /* Enable the "Set Default" button */
1305 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), TRUE);
1306
1307 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1308 }
1309 break;
1310 }
1311 break;
1312
1313 case IDC_BUTTON_SAVEAS_SCHEME:
1314 SaveCursorScheme(hwndDlg);
1315 break;
1316
1317 case IDC_BUTTON_USE_DEFAULT_CURSOR:
1318 nSel = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
1319 if (nSel != LB_ERR)
1320 {
1321 /* Clean the path of the currently selected cursor */
1322 memset(g_CursorData[nSel].szCursorPath, 0x0, MAX_PATH * sizeof(TCHAR));
1323
1324 /* Update cursor list and preview */
1325 ReloadCurrentCursorScheme();
1326 RefreshCursorList(hwndDlg, FALSE);
1327
1328 /* Disable the "Set Default" button */
1329 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), FALSE);
1330
1331 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1332 }
1333 break;
1334
1335 case IDC_BUTTON_BROWSE_CURSOR:
1336 if (BrowseCursor(hwndDlg))
1337 {
1338 /* Update cursor list and preview */
1339 ReloadCurrentCursorScheme();
1340 RefreshCursorList(hwndDlg, FALSE);
1341
1342 /* Enable the "Set Default" button */
1343 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), TRUE);
1344
1345 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1346 }
1347 break;
1348
1349 case IDC_BUTTON_DELETE_SCHEME:
1350 DeleteUserCursorScheme(hwndDlg);
1351 break;
1352
1353 case IDC_CHECK_CURSOR_SHADOW:
1354 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_CURSOR_SHADOW))
1355 {
1356 pPointerData->bCursorShadow = FALSE;
1357 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1358 //#if (WINVER >= 0x0500)
1359 // SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, 0);
1360 //#endif
1361 // PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1362 }
1363 else
1364 {
1365 pPointerData->bCursorShadow = TRUE;
1366 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1367 }
1368 //#if (WINVER >= 0x0500)
1369 //SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1370 //#endif
1371 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1372 break;
1373 }
1374 break;
1375 }
1376
1377 return FALSE;
1378 }
1379
1380
1381 static INT_PTR CALLBACK
1382 OptionProc(IN HWND hwndDlg,
1383 IN UINT uMsg,
1384 IN WPARAM wParam,
1385 IN LPARAM lParam)
1386 {
1387 POPTION_DATA pOptionData;
1388 HWND hDlgCtrl;
1389 LPPSHNOTIFY lppsn;
1390
1391 pOptionData = (POPTION_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1392
1393 switch(uMsg)
1394 {
1395 case WM_INITDIALOG:
1396 pOptionData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPTION_DATA));
1397 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pOptionData);
1398
1399 /* Get mouse sensitivity */
1400 if (!SystemParametersInfo(SPI_GETMOUSESPEED, 0, &pOptionData->ulMouseSpeed, 0))
1401 pOptionData->ulMouseSpeed = DEFAULT_MOUSE_SPEED;
1402 pOptionData->ulOrigMouseSpeed = pOptionData->ulMouseSpeed;
1403
1404
1405 if (!SystemParametersInfo(SPI_GETMOUSE, 0, &pOptionData->MouseAccel, 0))
1406 {
1407 pOptionData->MouseAccel.nAcceleration = DEFAULT_MOUSE_ACCELERATION;
1408 pOptionData->MouseAccel.nThreshold1 = DEFAULT_MOUSE_THRESHOLD1;
1409 pOptionData->MouseAccel.nThreshold2 = DEFAULT_MOUSE_THRESHOLD2;
1410 }
1411 pOptionData->OrigMouseAccel.nAcceleration = pOptionData->MouseAccel.nAcceleration;
1412 pOptionData->OrigMouseAccel.nThreshold1 = pOptionData->MouseAccel.nThreshold1;
1413 pOptionData->OrigMouseAccel.nThreshold2 = pOptionData->MouseAccel.nThreshold2;
1414
1415 /* snap to default button */
1416 SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &pOptionData->bSnapToDefaultButton, 0);
1417 pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton;
1418
1419 /* mouse trails */
1420 SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &pOptionData->uMouseTrails, 0);
1421 pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails;
1422
1423 /* hide pointer while typing */
1424 SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &pOptionData->bMouseVanish, 0);
1425 pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish;
1426
1427 /* show pointer with Ctrl-Key */
1428 SystemParametersInfo(SPI_GETMOUSESONAR, 0, &pOptionData->bMouseSonar, 0);
1429 pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar;
1430
1431 /* Set mouse speed */
1432 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED);
1433 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 19));
1434 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->ulMouseSpeed - 1);
1435
1436 if (pOptionData->MouseAccel.nAcceleration)
1437 {
1438 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_POINTER_PRECISION);
1439 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1440 }
1441
1442 if (pOptionData->bSnapToDefaultButton)
1443 {
1444 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SNAP_TO);
1445 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1446 }
1447
1448 /* set mouse trail */
1449 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1450 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 5));
1451 if (pOptionData->uMouseTrails < 2)
1452 {
1453 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)5);
1454 EnableWindow(hDlgCtrl, FALSE);
1455 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE);
1456 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE);
1457 }
1458 else
1459 {
1460 SendDlgItemMessage(hwndDlg, IDC_CHECK_POINTER_TRAIL, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1461 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->uMouseTrails - 2);
1462 }
1463
1464 if (pOptionData->bMouseVanish)
1465 {
1466 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_HIDE_POINTER);
1467 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1468 }
1469
1470 if (pOptionData->bMouseSonar)
1471 {
1472 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SHOW_POINTER);
1473 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1474 }
1475
1476 break;
1477
1478 case WM_DESTROY:
1479 HeapFree(GetProcessHeap(), 0, pOptionData);
1480 break;
1481
1482 case WM_COMMAND:
1483 switch(LOWORD(wParam))
1484 {
1485 case IDC_CHECK_POINTER_PRECISION:
1486 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_PRECISION))
1487 {
1488 pOptionData->MouseAccel.nAcceleration = 0;
1489 pOptionData->MouseAccel.nThreshold1 = 0;
1490 pOptionData->MouseAccel.nThreshold2 = 0;
1491 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1492 }
1493 else
1494 {
1495 pOptionData->MouseAccel.nAcceleration = 1;
1496 pOptionData->MouseAccel.nThreshold1 = 6;
1497 pOptionData->MouseAccel.nThreshold2 = 10;
1498 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1499 }
1500 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, 0);
1501 break;
1502
1503 case IDC_CHECK_SNAP_TO:
1504 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SNAP_TO))
1505 {
1506 pOptionData->bSnapToDefaultButton = 0;
1507 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1508 }
1509 else
1510 {
1511 pOptionData->bSnapToDefaultButton = 1;
1512 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1513 }
1514 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, 0);
1515 break;
1516
1517 case IDC_CHECK_POINTER_TRAIL:
1518 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1519 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL))
1520 {
1521 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1522 EnableWindow(hDlgCtrl, FALSE);
1523 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE);
1524 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE);
1525 pOptionData->uMouseTrails = 0;
1526 }
1527 else
1528 {
1529 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1530 EnableWindow(hDlgCtrl, TRUE);
1531 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), TRUE);
1532 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), TRUE);
1533 pOptionData->uMouseTrails = (UINT)SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2;
1534 }
1535 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, 0);
1536 break;
1537
1538 case IDC_CHECK_HIDE_POINTER:
1539 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_HIDE_POINTER))
1540 {
1541 pOptionData->bMouseVanish = FALSE;
1542 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1543 }
1544 else
1545 {
1546 pOptionData->bMouseVanish = TRUE;
1547 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1548 }
1549 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bMouseVanish), 0);
1550 break;
1551
1552 case IDC_CHECK_SHOW_POINTER:
1553 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHOW_POINTER))
1554 {
1555 pOptionData->bMouseSonar = FALSE;
1556 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1557 }
1558 else
1559 {
1560 pOptionData->bMouseSonar = TRUE;
1561 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1562 }
1563 SystemParametersInfo(SPI_SETMOUSESONAR, 0, IntToPtr(pOptionData->bMouseSonar), 0);
1564 break;
1565
1566 }
1567 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1568 break;
1569
1570 case WM_NOTIFY:
1571 lppsn = (LPPSHNOTIFY)lParam;
1572 if (lppsn->hdr.code == PSN_APPLY)
1573 {
1574 /* Set mouse speed */
1575 if (pOptionData->ulOrigMouseSpeed != pOptionData->ulMouseSpeed)
1576 {
1577 SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulMouseSpeed), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1578 pOptionData->ulOrigMouseSpeed = pOptionData->ulMouseSpeed;
1579 }
1580
1581 if (pOptionData->OrigMouseAccel.nAcceleration != pOptionData->MouseAccel.nAcceleration)
1582 {
1583 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1584 pOptionData->OrigMouseAccel.nAcceleration = pOptionData->MouseAccel.nAcceleration;
1585 pOptionData->OrigMouseAccel.nThreshold1 = pOptionData->MouseAccel.nThreshold1;
1586 pOptionData->OrigMouseAccel.nThreshold2 = pOptionData->MouseAccel.nThreshold2;
1587 }
1588
1589
1590 /* set snap to default button */
1591 if (pOptionData->bOrigSnapToDefaultButton != pOptionData->bSnapToDefaultButton)
1592 {
1593 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1594 pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton;
1595 }
1596
1597 /* Set mouse trails setting */
1598 if (pOptionData->uOrigMouseTrails != pOptionData->uMouseTrails)
1599 {
1600 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1601 pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails;
1602 }
1603
1604 /* hide pointer while typing */
1605 if (pOptionData->bOrigMouseVanish != pOptionData->bMouseVanish)
1606 {
1607 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bMouseVanish), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1608 pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish;
1609 }
1610
1611 /* show pointer with Ctrl-Key */
1612 if (pOptionData->bOrigMouseSonar != pOptionData->bMouseSonar)
1613 {
1614 SystemParametersInfo(SPI_SETMOUSESONAR, 0, IntToPtr(pOptionData->bMouseSonar), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1615 pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar;
1616 }
1617 return TRUE;
1618 }
1619 else if (lppsn->hdr.code == PSN_RESET)
1620 {
1621 /* Set the original mouse speed */
1622 SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulOrigMouseSpeed), 0);
1623 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->OrigMouseAccel, 0);
1624 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bOrigSnapToDefaultButton, 0, 0);
1625 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uOrigMouseTrails, 0, 0);
1626 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bOrigMouseVanish), 0);
1627 SystemParametersInfo(SPI_SETMOUSESONAR, 0,IntToPtr(pOptionData->bOrigMouseSonar), 0);
1628 }
1629 break;
1630
1631 case WM_HSCROLL:
1632 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED))
1633 {
1634 switch (LOWORD(wParam))
1635 {
1636 case TB_LINEUP:
1637 case TB_LINEDOWN:
1638 case TB_PAGEUP:
1639 case TB_PAGEDOWN:
1640 case TB_TOP:
1641 case TB_BOTTOM:
1642 case TB_ENDTRACK:
1643 pOptionData->ulMouseSpeed = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_MOUSE_SPEED, TBM_GETPOS, 0, 0) + 1;
1644 SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulMouseSpeed), SPIF_SENDCHANGE);
1645 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1646 break;
1647 #if 0
1648 case TB_THUMBTRACK:
1649 pOptionData->ulMouseSpeed = (ULONG)HIWORD(wParam) + 1;
1650 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSpeed, SPIF_SENDCHANGE);
1651 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1652 break;
1653 #endif
1654 }
1655 }
1656 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL))
1657 {
1658 switch (LOWORD(wParam))
1659 {
1660 case TB_LINEUP:
1661 case TB_LINEDOWN:
1662 case TB_PAGEUP:
1663 case TB_PAGEDOWN:
1664 case TB_TOP:
1665 case TB_BOTTOM:
1666 case TB_ENDTRACK:
1667 pOptionData->uMouseTrails = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_POINTER_TRAIL, TBM_GETPOS, 0, 0) + 2;
1668 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE);
1669 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1670 break;
1671
1672 case TB_THUMBTRACK:
1673 pOptionData->uMouseTrails = (ULONG)HIWORD(wParam) + 2;
1674 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE);
1675 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1676 break;
1677 }
1678 }
1679 break;
1680 }
1681
1682 return FALSE;
1683 }
1684
1685
1686 static VOID
1687 ShowDialogWheelControls(HWND hwndDlg, UINT uWheelScrollLines, BOOL bInit)
1688 {
1689 HWND hDlgCtrl;
1690
1691 if (uWheelScrollLines != WHEEL_PAGESCROLL)
1692 {
1693 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1694 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1695
1696 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1697 EnableWindow(hDlgCtrl, TRUE);
1698
1699 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1700 EnableWindow(hDlgCtrl, TRUE);
1701
1702 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1703 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1704 }
1705 else
1706 {
1707 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1708 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1709
1710 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1711 EnableWindow(hDlgCtrl, FALSE);
1712
1713 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1714 EnableWindow(hDlgCtrl, FALSE);
1715
1716 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1717 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1718
1719 /* Set the default scroll lines value */
1720 if (bInit == TRUE)
1721 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, DEFAULT_WHEEL_SCROLL_LINES, FALSE);
1722 }
1723 }
1724
1725
1726 static INT_PTR CALLBACK
1727 WheelProc(IN HWND hwndDlg,
1728 IN UINT uMsg,
1729 IN WPARAM wParam,
1730 IN LPARAM lParam)
1731 {
1732 LPPSHNOTIFY lppsn;
1733 PWHEEL_DATA pWheelData;
1734
1735 pWheelData = (PWHEEL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1736
1737 switch (uMsg)
1738 {
1739 case WM_INITDIALOG:
1740 pWheelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WHEEL_DATA));
1741 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pWheelData);
1742
1743 /* Get wheel scroll lines */
1744 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pWheelData->uWheelScrollLines, 0);
1745
1746 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, TRUE);
1747 SendDlgItemMessage(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES, UDM_SETRANGE, 0, MAKELONG((short)100, (short)0));
1748 if (pWheelData->uWheelScrollLines != WHEEL_PAGESCROLL)
1749 {
1750 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, pWheelData->uWheelScrollLines, FALSE);
1751 }
1752 return TRUE;
1753
1754 case WM_DESTROY:
1755 HeapFree(GetProcessHeap(), 0, pWheelData);
1756 break;
1757
1758 case WM_COMMAND:
1759 switch (LOWORD(wParam))
1760 {
1761 case IDC_RADIO_WHEEL_SCROLL_LINES:
1762 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1763 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1764 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1765 break;
1766
1767 case IDC_RADIO_WHEEL_SCROLL_PAGE:
1768 pWheelData->uWheelScrollLines = WHEEL_PAGESCROLL;
1769 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1770 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1771 break;
1772
1773 case IDC_EDIT_WHEEL_SCROLL_LINES:
1774 if (pWheelData && HIWORD(wParam) == EN_CHANGE)
1775 {
1776 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1777 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1778 }
1779 break;
1780 }
1781 break;
1782
1783 case WM_NOTIFY:
1784 lppsn = (LPPSHNOTIFY)lParam;
1785 if (lppsn->hdr.code == PSN_APPLY)
1786 {
1787 SystemParametersInfo(SPI_SETWHEELSCROLLLINES, pWheelData->uWheelScrollLines,
1788 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1789 return TRUE;
1790 }
1791 break;
1792 }
1793
1794 return FALSE;
1795 }
1796
1797 static const struct
1798 {
1799 WORD idDlg;
1800 DLGPROC DlgProc;
1801 UINT uiReplaceWith;
1802 } PropPages[] =
1803 {
1804 { IDD_PAGE_BUTTON, ButtonProc, CPLPAGE_MOUSE_BUTTONS },
1805 { IDD_PAGE_POINTER, PointerProc, 0 },
1806 { IDD_PAGE_OPTION, OptionProc, CPLPAGE_MOUSE_PTRMOTION },
1807 { IDD_PAGE_WHEEL, WheelProc, CPLPAGE_MOUSE_WHEEL },
1808 { IDD_HARDWARE, MouseHardwareProc, 0 },
1809 };
1810
1811 LONG APIENTRY
1812 MouseApplet(HWND hwnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
1813 {
1814 HPROPSHEETPAGE hpsp[MAX_CPL_PAGES];
1815 PROPSHEETHEADER psh;
1816 HPSXA hpsxa;
1817 TCHAR Caption[256];
1818 UINT i;
1819 LONG ret;
1820
1821 UNREFERENCED_PARAMETER(lParam1);
1822 UNREFERENCED_PARAMETER(lParam2);
1823 UNREFERENCED_PARAMETER(uMsg);
1824 UNREFERENCED_PARAMETER(hwnd);
1825
1826 LoadString(hApplet, IDS_CPLNAME_1, Caption, sizeof(Caption) / sizeof(TCHAR));
1827
1828 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
1829 psh.dwSize = sizeof(PROPSHEETHEADER);
1830 psh.dwFlags = PSH_PROPTITLE;
1831 psh.hwndParent = hwnd;
1832 psh.hInstance = hApplet;
1833 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_1));
1834 psh.pszCaption = Caption;
1835 psh.nStartPage = 0;
1836 psh.phpage = hpsp;
1837
1838 /* Load additional pages provided by shell extensions */
1839 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Mouse"), MAX_CPL_PAGES - psh.nPages);
1840
1841 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
1842 {
1843 /* Override the background page if requested by a shell extension */
1844 if (PropPages[i].uiReplaceWith != 0 && hpsxa != NULL &&
1845 SHReplaceFromPropSheetExtArray(hpsxa, PropPages[i].uiReplaceWith, PropSheetAddPage, (LPARAM)&psh) != 0)
1846 {
1847 /* The shell extension added one or more pages to replace a page.
1848 Don't create the built-in page anymore! */
1849 continue;
1850 }
1851
1852 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc);
1853 }
1854
1855 if (hpsxa != NULL)
1856 SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh);
1857
1858 ret = (LONG)(PropertySheet(&psh) != -1);
1859
1860 if (hpsxa != NULL)
1861 SHDestroyPropSheetExtArray(hpsxa);
1862
1863 return ret;
1864 }
1865
1866 /* EOF */