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