- Add icons for dialogs
[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 static HICON hIcon;
205
206 PBUTTON_DATA pButtonData;
207
208 pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
209
210 switch(uMsg)
211 {
212 case WM_INITDIALOG:
213 pButtonData = (PBUTTON_DATA)lParam;
214 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData);
215
216 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK);
217 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10));
218 pos = (pButtonData->g_ClickLockTime - 200) / 200;
219 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
220
221 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_LOOK_KEY),
222 IMAGE_ICON, 16, 16, 0);
223 SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
224 return TRUE;
225
226 case WM_COMMAND:
227 if (LOWORD(wParam) == IDOK)
228 {
229 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK);
230 pButtonData->g_ClickLockTime = (DWORD) (SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) * 200) + 200;
231 EndDialog(hwndDlg, TRUE);
232 }
233 else if (LOWORD(wParam) == IDCANCEL)
234 {
235 EndDialog(hwndDlg, FALSE);
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
384 #if (WINVER >= 0x0500)
385 SystemParametersInfo(SPI_SETMOUSECLICKLOCK, pButtonData->g_ClickLockEnabled, NULL, SPIF_SENDCHANGE);
386 if (pButtonData->g_ClickLockEnabled)
387 SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, pButtonData->g_ClickLockTime, NULL, SPIF_SENDCHANGE);
388 #endif
389 }
390 else if (lppsn->hdr.code == PSN_RESET)
391 {
392 /* Reset swap mouse button setting */
393 SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_OrigSwapMouseButtons, NULL, 0);
394
395 /* Reset double click speed setting */
396 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_OrigDoubleClickSpeed, NULL, 0);
397 SetDoubleClickTime(pButtonData->g_OrigDoubleClickSpeed);
398 }
399 return TRUE;
400
401 case WM_HSCROLL:
402 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED))
403 {
404 switch (LOWORD(wParam))
405 {
406 case TB_LINEUP:
407 case TB_LINEDOWN:
408 case TB_PAGEUP:
409 case TB_PAGEDOWN:
410 case TB_TOP:
411 case TB_BOTTOM:
412 case TB_ENDTRACK:
413 lResult = SendDlgItemMessage(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED, TBM_GETPOS, 0, 0);
414 pButtonData->g_DoubleClickSpeed = (14 - (INT)lResult) * 50 + 200;
415 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, 0);
416 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
417 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
418 break;
419
420 case TB_THUMBTRACK:
421 pButtonData->g_DoubleClickSpeed = (14 - (INT)HIWORD(wParam)) * 50 + 200;
422 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, 0);
423 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
424 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
425 break;
426 }
427 }
428 break;
429 }
430
431 return FALSE;
432 }
433
434
435 static VOID
436 CompressPath(LPTSTR lpShortPath, LPTSTR lpPath)
437 {
438 TCHAR szUserProfile[MAX_PATH];
439 TCHAR szSystemRoot[MAX_PATH];
440 TCHAR szProgramFiles[MAX_PATH];
441 DWORD dwUserProfile;
442 DWORD dwSystemRoot;
443 DWORD dwProgramFiles;
444
445 dwUserProfile = GetEnvironmentVariable(_T("USERPROFILE"), szUserProfile, MAX_PATH);
446 dwSystemRoot = GetEnvironmentVariable(_T("SystemRoot"), szSystemRoot, MAX_PATH);
447 dwProgramFiles = GetEnvironmentVariable(_T("ProgramFiles"), szProgramFiles, MAX_PATH);
448
449 if (dwUserProfile > 0 && _tcsncmp(lpPath, szUserProfile, dwUserProfile) == 0)
450 {
451 _tcscpy(lpShortPath, _T("%USERPROFILE%"));
452 _tcscat(lpShortPath, &lpPath[dwUserProfile]);
453 }
454 else if (dwSystemRoot > 0 && _tcsncmp(lpPath, szSystemRoot, dwSystemRoot) == 0)
455 {
456 _tcscpy(lpShortPath, _T("%SystemRoot%"));
457 _tcscat(lpShortPath, &lpPath[dwSystemRoot]);
458 }
459 else if (dwProgramFiles > 0 && _tcsncmp(lpPath, szProgramFiles, dwProgramFiles) == 0)
460 {
461 _tcscpy(lpShortPath, _T("%ProgramFiles%"));
462 _tcscat(lpShortPath, &lpPath[dwProgramFiles]);
463 }
464 else
465 {
466 _tcscpy(lpShortPath, lpPath);
467 }
468 }
469
470
471 static BOOL
472 EnumerateCursorSchemes(HWND hwndDlg)
473 {
474 HKEY hCursorKey;
475 DWORD dwIndex;
476 TCHAR szValueName[MAX_PATH];
477 DWORD dwValueName;
478 TCHAR szSystemScheme[MAX_PATH];
479 TCHAR szValueData[2000];
480 TCHAR szTempData[2000];
481 DWORD dwValueData;
482 LONG lError;
483 HWND hDlgCtrl;
484 LRESULT lResult;
485
486 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
487 SendMessage(hDlgCtrl, CB_RESETCONTENT, 0, 0);
488
489 /* Read the users cursor schemes */
490 lError = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors\\Schemes"),
491 0, KEY_READ | KEY_QUERY_VALUE , &hCursorKey);
492 if (lError == ERROR_SUCCESS)
493 {
494 for (dwIndex = 0;; dwIndex++)
495 {
496 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
497 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
498 lError = RegEnumValue(hCursorKey, dwIndex, szValueName, &dwValueName,
499 NULL, NULL, (LPBYTE)szValueData, &dwValueData);
500 if (lError == ERROR_NO_MORE_ITEMS)
501 break;
502
503 ExpandEnvironmentStrings(szValueData, szTempData, 2000);
504
505 if (_tcslen(szTempData) > 0)
506 {
507 LPTSTR lpCopy, lpStart;
508
509 /* Remove quotation marks */
510 if (szTempData[0] == _T('"'))
511 {
512 lpStart = szValueData + 1;
513 szTempData[_tcslen(szTempData) - 1] = 0;
514 }
515 else
516 {
517 lpStart = szTempData;
518 }
519
520 lpCopy = _tcsdup(lpStart);
521
522 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName);
523 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)lpCopy);
524 }
525 }
526
527 RegCloseKey(hCursorKey);
528 }
529
530 /* Read the system cursor schemes */
531 lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
532 _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes"),
533 0, KEY_READ | KEY_QUERY_VALUE , &hCursorKey);
534 if (lError == ERROR_SUCCESS)
535 {
536 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
537
538 for (dwIndex = 0;; dwIndex++)
539 {
540 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
541 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
542 lError = RegEnumValue(hCursorKey, dwIndex, szValueName, &dwValueName,
543 NULL, NULL, (LPBYTE)szValueData, &dwValueData);
544 if (lError == ERROR_NO_MORE_ITEMS)
545 break;
546
547 if (_tcslen(szValueData) > 0)
548 {
549 LPTSTR lpCopy, lpStart;
550
551 /* Remove quotation marks */
552 if (szValueData[0] == _T('"'))
553 {
554 lpStart = szValueData + 1;
555 szValueData[_tcslen(szValueData) - 1] = 0;
556 }
557 else
558 {
559 lpStart = szValueData;
560 }
561
562 lpCopy = _tcsdup(lpStart);
563
564 _tcscat(szValueName, TEXT(" "));
565 _tcscat(szValueName, szSystemScheme);
566
567 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName);
568 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)lpCopy);
569 }
570 }
571
572 RegCloseKey(hCursorKey);
573 }
574
575 /* Add the "(none)" entry */
576 LoadString(hApplet, IDS_NONE, szSystemScheme, MAX_PATH);
577 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szSystemScheme);
578 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)NULL);
579
580 return TRUE;
581 }
582
583
584 static VOID
585 RefreshCursorList(HWND hwndDlg, BOOL bInit)
586 {
587 INT index;
588 INT i;
589 INT nSel;
590
591 nSel = bInit ? 0 : SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
592
593 if (bInit)
594 {
595 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_RESETCONTENT, 0, 0);
596 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
597 {
598 LoadString(hApplet, index, g_CursorData[i].szCursorName, MAX_PATH);
599 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_ADDSTRING, 0, (LPARAM)i);
600 }
601
602 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_SETCURSEL, nSel, 0);
603 }
604 else
605 {
606 InvalidateRect(GetDlgItem(hwndDlg, IDC_LISTBOX_CURSOR), NULL, FALSE);
607 }
608
609 SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR,
610 (LPARAM)g_CursorData[nSel].hCursor);
611
612 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), (g_CursorData[nSel].szCursorPath[0] != 0));
613 }
614
615
616 static BOOL
617 DeleteUserCursorScheme(HWND hwndDlg)
618 {
619 TCHAR szSchemeName[MAX_PATH];
620 TCHAR szTitle[128];
621 TCHAR szRawText[256];
622 TCHAR szText[256];
623 HWND hDlgCtrl;
624 HKEY hCuKey;
625 HKEY hCuCursorKey;
626 LONG lResult;
627 INT nSel;
628
629 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
630 nSel = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
631 if (nSel == CB_ERR)
632 return FALSE;
633
634 SendMessage(hDlgCtrl, CB_GETLBTEXT, nSel, (LPARAM)szSchemeName);
635
636 LoadString(hApplet, IDS_REMOVE_TITLE, szTitle, 128);
637 LoadString(hApplet, IDS_REMOVE_TEXT, szRawText, 256);
638
639 _stprintf(szText, szRawText, szSchemeName);
640
641 /* Confirm scheme removal */
642 if (MessageBox(hwndDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO)
643 return TRUE;
644
645 if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS)
646 return FALSE;
647
648 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS)
649 {
650 RegCloseKey(hCuKey);
651 return FALSE;
652 }
653
654 lResult = RegDeleteValue(hCuCursorKey, szSchemeName);
655
656 RegCloseKey(hCuCursorKey);
657 RegCloseKey(hCuKey);
658
659 if (lResult == ERROR_SUCCESS)
660 {
661 SendMessage(hDlgCtrl, CB_DELETESTRING, nSel, 0);
662 SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
663 }
664
665 return (lResult == ERROR_SUCCESS);
666 }
667
668
669 static INT_PTR CALLBACK
670 SaveSchemeProc(IN HWND hwndDlg,
671 IN UINT uMsg,
672 IN WPARAM wParam,
673 IN LPARAM lParam)
674 {
675 LPTSTR pSchemeName;
676
677 switch (uMsg)
678 {
679 case WM_INITDIALOG:
680 pSchemeName = (LPTSTR)lParam;
681 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSchemeName);
682 SendDlgItemMessage(hwndDlg, IDC_EDIT_SCHEME_NAME, WM_SETTEXT,
683 0, (LPARAM)pSchemeName);
684 break;
685
686 case WM_COMMAND:
687 if (LOWORD(wParam) == IDOK)
688 {
689 pSchemeName = (LPTSTR)GetWindowLongPtr(hwndDlg, DWLP_USER);
690 SendDlgItemMessage(hwndDlg, IDC_EDIT_SCHEME_NAME, WM_GETTEXT,
691 (WPARAM)MAX_PATH, (LPARAM)pSchemeName);
692 EndDialog(hwndDlg, TRUE);
693 }
694 else if (LOWORD(wParam) == IDCANCEL)
695 {
696 EndDialog(hwndDlg, FALSE);
697 }
698 break;
699 }
700
701 return FALSE;
702 }
703
704
705 static BOOL
706 SaveCursorScheme(HWND hwndDlg)
707 {
708 TCHAR szSystemScheme[MAX_PATH];
709 TCHAR szSchemeName[MAX_PATH];
710 TCHAR szNewSchemeName[MAX_PATH];
711 TCHAR szTempPath[MAX_PATH];
712 TCHAR szTitle[128];
713 TCHAR szText[256];
714 INT nSel;
715 INT index, i, nLength;
716 LPTSTR lpSchemeData;
717 HKEY hCuKey;
718 HKEY hCuCursorKey;
719 LONG lError = ERROR_SUCCESS;
720 BOOL bSchemeExists;
721
722 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
723
724 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
725 if (nSel == CB_ERR)
726 return FALSE;
727
728 if (nSel == 0)
729 {
730 szSchemeName[0] = 0;
731 }
732 else
733 {
734 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szNewSchemeName);
735
736 if (_tcsstr(szNewSchemeName, szSystemScheme))
737 {
738 szNewSchemeName[_tcslen(szNewSchemeName) - _tcslen(szSystemScheme) - 1] = 0;
739 }
740 }
741
742 /* Ask for a name for the new cursor scheme */
743 if (!DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CURSOR_SCHEME_SAVEAS),
744 hwndDlg, SaveSchemeProc, (LPARAM)szNewSchemeName))
745 return TRUE;
746
747 /* Check all non-system schemes for the new name */
748 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCOUNT, 0, 0);
749 if (nSel == CB_ERR)
750 return FALSE;
751
752 bSchemeExists = FALSE;
753 for (i = 0; i < nSel; i++)
754 {
755 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, i, (LPARAM)szSchemeName);
756 if (_tcsstr(szSchemeName, szSystemScheme) == NULL)
757 {
758 if (_tcscmp(szSchemeName, szNewSchemeName) == 0)
759 {
760 bSchemeExists = TRUE;
761 break;
762 }
763 }
764 }
765
766 if (bSchemeExists)
767 {
768 LoadString(hApplet, IDS_OVERWRITE_TITLE, szTitle, 128);
769 LoadString(hApplet, IDS_OVERWRITE_TEXT, szText, 256);
770
771 /* Confirm scheme overwrite */
772 if (MessageBox(hwndDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO)
773 return TRUE;
774 }
775
776 /* Save the cursor scheme */
777 nLength = 0;
778 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
779 {
780 if (i > 0)
781 nLength++;
782 nLength += _tcslen(g_CursorData[i].szCursorPath);
783 }
784 nLength++;
785
786 lpSchemeData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(TCHAR));
787
788 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
789 {
790 CompressPath(szTempPath, g_CursorData[i].szCursorPath);
791 if (i > 0)
792 _tcscat(lpSchemeData, _T(","));
793 _tcscat(lpSchemeData, szTempPath);
794 }
795
796 if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS)
797 return FALSE;
798
799 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS)
800 {
801 RegCloseKey(hCuKey);
802 return FALSE;
803 }
804
805 lError = RegSetValueEx(hCuCursorKey, szNewSchemeName, 0,
806 REG_EXPAND_SZ, (LPBYTE)lpSchemeData,
807 (_tcslen(lpSchemeData) + 1) * sizeof(TCHAR));
808
809 RegCloseKey(hCuCursorKey);
810 RegCloseKey(hCuKey);
811
812 /* Add the new scheme to the scheme list and select it */
813 if (lError == ERROR_SUCCESS)
814 {
815 LPTSTR copy = _tcsdup(lpSchemeData);
816
817 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_ADDSTRING, (WPARAM)0, (LPARAM)szNewSchemeName);
818 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETITEMDATA, (WPARAM)nSel, (LPARAM)copy);
819 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0);
820 }
821
822 HeapFree(GetProcessHeap(), 0, lpSchemeData);
823
824 return (lError == ERROR_SUCCESS);
825 }
826
827
828 static BOOL
829 BrowseCursor(HWND hwndDlg)
830 {
831 TCHAR szFileName[MAX_PATH];
832 TCHAR szFilter[MAX_PATH];
833 TCHAR szTitle[MAX_PATH];
834 OPENFILENAME ofn;
835 INT nSel;
836
837 LoadString(hApplet, IDS_BROWSE_FILTER, szFilter, MAX_PATH);
838 LoadString(hApplet, IDS_BROWSE_TITLE, szTitle, MAX_PATH);
839
840 memset(szFileName, 0x0, sizeof(szFileName));
841 nSel = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
842 if (nSel == LB_ERR)
843 {
844 MessageBox(hwndDlg, _T("LB_ERR"), _T(""), MB_ICONERROR);
845 return FALSE;
846 }
847
848 ZeroMemory(&ofn, sizeof(OPENFILENAME));
849 ofn.lStructSize = sizeof(OPENFILENAME);
850 ofn.hwndOwner = hwndDlg;
851 ofn.lpstrFilter = szFilter;
852 ofn.nFilterIndex = 1;
853 ofn.lpstrFile = szFileName;
854 ofn.nMaxFile = MAX_PATH;
855 ofn.lpstrInitialDir = _T("%WINDIR%\\Cursors");
856 ofn.lpstrTitle = szTitle;
857 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
858
859 if (!GetOpenFileName(&ofn))
860 return FALSE;
861
862 /* Store the new cursor file path */
863 _tcsncpy(g_CursorData[nSel].szCursorPath, szFileName, MAX_PATH);
864
865 return TRUE;
866 }
867
868
869 static VOID
870 LoadCursorScheme(LPTSTR lpName, BOOL bSystem)
871 {
872 UINT index, i;
873
874 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
875 {
876 if (g_CursorData[i].hCursor != NULL)
877 {
878 DestroyCursor(g_CursorData[i].hCursor);
879 g_CursorData[i].hCursor = 0;
880 }
881 g_CursorData[i].szCursorPath[0] = 0;
882 }
883
884 if (lpName != NULL)
885 {
886 LPTSTR pStart = lpName;
887 LPTSTR pEnd = pStart;
888 INT nLength;
889
890 i = 0;
891 while (pEnd)
892 {
893 pEnd = _tcschr(pStart, _T(','));
894 if (pEnd)
895 nLength = ((INT_PTR)pEnd - (INT_PTR)pStart) / sizeof(TCHAR);
896 else
897 nLength = _tcslen(pStart);
898
899 _tcsncpy(g_CursorData[i].szCursorPath, pStart, nLength);
900 g_CursorData[i].szCursorPath[nLength] = 0;
901
902 pStart = pStart + (nLength + 1);
903 i++;
904 }
905
906 }
907
908 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
909 {
910 if (g_CursorData[i].szCursorPath[0] == 0)
911 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId),
912 IMAGE_CURSOR, 0, 0,
913 LR_DEFAULTSIZE | LR_SHARED);
914 else
915 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
916 IMAGE_CURSOR, 0, 0,
917 LR_LOADFROMFILE | LR_DEFAULTSIZE);
918 }
919 }
920
921
922 static VOID
923 ReloadCurrentCursorScheme(VOID)
924 {
925 UINT index, i;
926
927 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
928 {
929 if (g_CursorData[i].hCursor != NULL)
930 DestroyCursor(g_CursorData[i].hCursor);
931
932 if (g_CursorData[i].szCursorPath[0] == 0)
933 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId),
934 IMAGE_CURSOR, 0, 0,
935 LR_DEFAULTSIZE | LR_SHARED);
936 else
937 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
938 IMAGE_CURSOR, 0, 0,
939 LR_LOADFROMFILE | LR_DEFAULTSIZE);
940 }
941 }
942
943
944 static VOID
945 OnDrawItem(UINT idCtl,
946 LPDRAWITEMSTRUCT lpdis,
947 PPOINTER_DATA pPointerData)
948 {
949 RECT rc;
950
951 if (lpdis->itemState & ODS_SELECTED)
952 {
953 FillRect(lpdis->hDC,
954 &lpdis->rcItem,
955 (HBRUSH)(COLOR_HIGHLIGHT + 1));
956 SetBkColor(lpdis->hDC,
957 GetSysColor(COLOR_HIGHLIGHT));
958 SetTextColor(lpdis->hDC,
959 GetSysColor(COLOR_HIGHLIGHTTEXT));
960 }
961 else
962 {
963 FillRect(lpdis->hDC,
964 &lpdis->rcItem,
965 (HBRUSH)(COLOR_WINDOW + 1));
966 SetBkColor(lpdis->hDC,
967 GetSysColor(COLOR_WINDOW));
968 SetTextColor(lpdis->hDC,
969 GetSysColor(COLOR_WINDOWTEXT));
970 }
971
972 if (lpdis->itemID != -1)
973 {
974 CopyRect(&rc, &lpdis->rcItem);
975 rc.left += 5;
976 DrawText(lpdis->hDC,
977 g_CursorData[lpdis->itemData].szCursorName,
978 -1,
979 &rc,
980 DT_SINGLELINE | DT_VCENTER | DT_LEFT);
981
982 if (g_CursorData[lpdis->itemData].hCursor != NULL)
983 {
984 DrawIcon(lpdis->hDC,
985 lpdis->rcItem.right - pPointerData->cxCursor - 4,
986 lpdis->rcItem.top + 2,
987 g_CursorData[lpdis->itemData].hCursor);
988 }
989 }
990
991 if (lpdis->itemState & ODS_FOCUS)
992 {
993 CopyRect(&rc, &lpdis->rcItem);
994 InflateRect(&rc, -1, -1);
995 DrawFocusRect(lpdis->hDC, &rc);
996 }
997 }
998
999
1000 static VOID
1001 LoadNewCursorScheme(HWND hwndDlg)
1002 {
1003 TCHAR buffer[MAX_PATH];
1004 TCHAR szSystemScheme[MAX_PATH];
1005 HWND hDlgCtrl;
1006 BOOL bEnable;
1007 LPTSTR lpName;
1008 INT nSel;
1009
1010 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
1011 if (nSel == CB_ERR)
1012 return;
1013
1014 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)buffer);
1015
1016 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1017 if (_tcsstr(buffer, szSystemScheme) || nSel == 0) //avoid the default scheme can be deleted
1018 bEnable = FALSE;
1019 else
1020 bEnable = TRUE;
1021
1022 /* delete button */
1023 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME);
1024 EnableWindow(hDlgCtrl, bEnable);
1025
1026 lpName = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0);
1027 LoadCursorScheme(lpName, !bEnable);
1028 RefreshCursorList(hwndDlg, FALSE);
1029 }
1030
1031
1032 static VOID
1033 LoadInitialCursorScheme(HWND hwndDlg)
1034 {
1035 TCHAR szSchemeName[256];
1036 TCHAR szSystemScheme[256];
1037 TCHAR szCursorPath[256];
1038 HKEY hCursorKey;
1039 LONG lError;
1040 DWORD dwDataSize;
1041 DWORD dwSchemeSource = 0;
1042 UINT index, i;
1043 DWORD dwType;
1044 INT nSel;
1045
1046 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1047 {
1048 g_CursorData[i].hCursor = 0;
1049 g_CursorData[i].szCursorPath[0] = 0;
1050 }
1051
1052 lError = RegOpenKeyEx(HKEY_CURRENT_USER,
1053 _T("Control Panel\\Cursors"),
1054 0,
1055 KEY_READ | KEY_QUERY_VALUE,
1056 &hCursorKey);
1057 if (lError != ERROR_SUCCESS)
1058 return;
1059
1060 dwDataSize = sizeof(DWORD);
1061 lError = RegQueryValueEx(hCursorKey,
1062 _T("Scheme Source"),
1063 NULL,
1064 NULL,
1065 (LPBYTE)&dwSchemeSource,
1066 &dwDataSize);
1067
1068 if (dwSchemeSource != 0)
1069 {
1070 dwDataSize = 256 * sizeof(TCHAR);
1071 lError = RegQueryValueEx(hCursorKey,
1072 NULL,
1073 NULL,
1074 NULL,
1075 (LPBYTE)szSchemeName,
1076 &dwDataSize);
1077
1078 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1079 {
1080 dwDataSize = MAX_PATH * sizeof(TCHAR);
1081 lError = RegQueryValueEx(hCursorKey,
1082 g_CursorData[i].lpValueName,
1083 NULL,
1084 &dwType,
1085 (LPBYTE)szCursorPath,
1086 &dwDataSize);
1087 if (lError == ERROR_SUCCESS)
1088 {
1089 if (dwType == REG_EXPAND_SZ)
1090 {
1091 ExpandEnvironmentStrings(szCursorPath, g_CursorData[i].szCursorPath, MAX_PATH);
1092 }
1093 else
1094 {
1095 _tcscpy(g_CursorData[i].szCursorPath, szCursorPath);
1096 }
1097 }
1098 }
1099 }
1100
1101 RegCloseKey(hCursorKey);
1102
1103 ReloadCurrentCursorScheme();
1104 RefreshCursorList(hwndDlg, TRUE);
1105
1106 /* Build the full scheme name */
1107 if (dwSchemeSource == 0)
1108 {
1109 LoadString(hApplet, IDS_NONE, szSchemeName, MAX_PATH);
1110 }
1111 else if (dwSchemeSource == 2)
1112 {
1113 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1114 _tcscat(szSchemeName, _T(" "));
1115 _tcscat(szSchemeName, szSystemScheme);
1116 }
1117
1118 /* Search and select the curent scheme name from the scheme list */
1119 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_FINDSTRINGEXACT, -1, (LPARAM)szSchemeName);
1120 if (nSel != CB_ERR)
1121 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0);
1122
1123 /* Enable /disable delete button */
1124 EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME), (dwSchemeSource == 1));
1125 }
1126
1127
1128 static BOOL
1129 ApplyCursorScheme(HWND hwndDlg)
1130 {
1131 TCHAR szSchemeName[MAX_PATH];
1132 TCHAR szSystemScheme[MAX_PATH];
1133 TCHAR szTempPath[MAX_PATH];
1134 LPTSTR lpSchemeData;
1135 DWORD dwNameLength;
1136 DWORD dwSchemeSource;
1137 UINT index, i;
1138 HKEY hCursorKey;
1139 INT nSel;
1140
1141 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
1142 if (nSel == CB_ERR)
1143 return FALSE;
1144
1145 lpSchemeData = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0);
1146 if (lpSchemeData == NULL)
1147 {
1148 /* "None" cursor scheme */
1149 dwSchemeSource = 0;
1150 szSchemeName[0] = 0;
1151 dwNameLength = 0;
1152 }
1153 else
1154 {
1155 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szSchemeName);
1156 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1157
1158 if (_tcsstr(szSchemeName, szSystemScheme))
1159 {
1160 /* System scheme */
1161 dwSchemeSource = 2;
1162 szSchemeName[_tcslen(szSchemeName) - _tcslen(szSystemScheme) - 1] = 0;
1163 }
1164 else
1165 {
1166 /* User scheme */
1167 dwSchemeSource = 1;
1168 }
1169
1170 dwNameLength = (_tcslen(szSchemeName) + 1) * sizeof(TCHAR);
1171 }
1172
1173 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors"), 0,
1174 KEY_READ | KEY_SET_VALUE, &hCursorKey) != ERROR_SUCCESS)
1175 return FALSE;
1176
1177 RegSetValueEx(hCursorKey, NULL, 0, REG_SZ,
1178 (LPBYTE)szSchemeName, dwNameLength);
1179
1180 RegSetValueEx(hCursorKey, _T("Scheme Source"), 0, REG_DWORD,
1181 (LPBYTE)&dwSchemeSource, sizeof(DWORD));
1182
1183 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1184 {
1185 CompressPath(szTempPath, g_CursorData[i].szCursorPath);
1186 RegSetValueEx(hCursorKey, g_CursorData[i].lpValueName, 0,
1187 REG_EXPAND_SZ, (LPBYTE)szTempPath,
1188 (_tcslen(szTempPath) + 1) * sizeof(TCHAR));
1189 }
1190
1191 RegCloseKey(hCursorKey);
1192
1193 /* Force the system to reload its cursors */
1194 SystemParametersInfo(SPI_SETCURSORS, 0, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1195
1196 return TRUE;
1197 }
1198
1199
1200 static INT_PTR CALLBACK
1201 PointerProc(IN HWND hwndDlg,
1202 IN UINT uMsg,
1203 IN WPARAM wParam,
1204 IN LPARAM lParam)
1205 {
1206 PPOINTER_DATA pPointerData;
1207 LPPSHNOTIFY lppsn;
1208 INT nSel;
1209
1210 pPointerData = (PPOINTER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1211
1212 switch (uMsg)
1213 {
1214 case WM_INITDIALOG:
1215 pPointerData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(POINTER_DATA));
1216 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pPointerData);
1217
1218 pPointerData->cxCursor = GetSystemMetrics(SM_CXCURSOR);
1219 pPointerData->cyCursor = GetSystemMetrics(SM_CYCURSOR);
1220
1221 EnumerateCursorSchemes(hwndDlg);
1222 LoadInitialCursorScheme(hwndDlg);
1223
1224 /* Get drop shadow setting */
1225 if (!SystemParametersInfo(SPI_GETDROPSHADOW, 0, &pPointerData->bDropShadow, 0))
1226 pPointerData->bDropShadow = FALSE;
1227
1228 pPointerData->bOrigDropShadow = pPointerData->bDropShadow;
1229
1230 if (pPointerData->bDropShadow)
1231 {
1232 SendDlgItemMessage(hwndDlg, IDC_CHECK_DROP_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->bOrigDropShadow != pPointerData->bDropShadow)
1260 {
1261 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bDropShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1262 pPointerData->bOrigDropShadow = pPointerData->bDropShadow;
1263 }
1264 //#endif
1265 return TRUE;
1266 }
1267 else if (lppsn->hdr.code == PSN_RESET)
1268 {
1269 //#if (WINVER >= 0x0500)
1270 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bOrigDropShadow, 0);
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_DROP_SHADOW:
1354 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_DROP_SHADOW))
1355 {
1356 pPointerData->bDropShadow = FALSE;
1357 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1358 //#if (WINVER >= 0x0500)
1359 // SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bDropShadow, 0);
1360 //#endif
1361 // PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1362 }
1363 else
1364 {
1365 pPointerData->bDropShadow = TRUE;
1366 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1367 }
1368 //#if (WINVER >= 0x0500)
1369 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bDropShadow, 0);
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 if (SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &pOptionData->bSnapToDefaultButton, 0))
1417 pOptionData->bSnapToDefaultButton = FALSE;
1418 pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton;
1419
1420 /* mouse trails */
1421 if (!SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &pOptionData->uMouseTrails, 0))
1422 pOptionData->uMouseTrails = 0;
1423 pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails;
1424
1425 /* hide pointer while typing */
1426 if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &pOptionData->bMouseVanish, 0))
1427 pOptionData->bMouseVanish = FALSE;
1428 pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish;
1429
1430 /* show pointer with Ctrl-Key */
1431 if (!SystemParametersInfo(SPI_GETMOUSESONAR, 0, &pOptionData->bMouseSonar, 0))
1432 pOptionData->bMouseSonar = FALSE;
1433 pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar;
1434
1435 /* Set mouse speed */
1436 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED);
1437 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 19));
1438 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->ulMouseSpeed - 1);
1439
1440 if (pOptionData->MouseAccel.nAcceleration)
1441 {
1442 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_POINTER_PRECISION);
1443 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1444 }
1445
1446 if (pOptionData->bSnapToDefaultButton)
1447 {
1448 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SNAP_TO);
1449 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1450 }
1451
1452 /* set mouse trail */
1453 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1454 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 5));
1455 if (pOptionData->uMouseTrails < 2)
1456 {
1457 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)5);
1458 EnableWindow(hDlgCtrl, FALSE);
1459 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE);
1460 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE);
1461 }
1462 else
1463 {
1464 SendDlgItemMessage(hwndDlg, IDC_CHECK_POINTER_TRAIL, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1465 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->uMouseTrails - 2);
1466 }
1467
1468 if (pOptionData->bMouseVanish)
1469 {
1470 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_HIDE_POINTER);
1471 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1472 }
1473
1474 if (pOptionData->bMouseSonar)
1475 {
1476 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SHOW_POINTER);
1477 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1478 }
1479
1480 break;
1481
1482 case WM_DESTROY:
1483 HeapFree(GetProcessHeap(), 0, pOptionData);
1484 break;
1485
1486 case WM_COMMAND:
1487 switch(LOWORD(wParam))
1488 {
1489 case IDC_CHECK_POINTER_PRECISION:
1490 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_PRECISION))
1491 {
1492 pOptionData->MouseAccel.nAcceleration = 0;
1493 pOptionData->MouseAccel.nThreshold1 = 0;
1494 pOptionData->MouseAccel.nThreshold2 = 0;
1495 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1496 }
1497 else
1498 {
1499 pOptionData->MouseAccel.nAcceleration = 1;
1500 pOptionData->MouseAccel.nThreshold1 = 6;
1501 pOptionData->MouseAccel.nThreshold2 = 10;
1502 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1503 }
1504 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, 0);
1505 break;
1506
1507 case IDC_CHECK_SNAP_TO:
1508 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SNAP_TO))
1509 {
1510 pOptionData->bSnapToDefaultButton = 0;
1511 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1512 }
1513 else
1514 {
1515 pOptionData->bSnapToDefaultButton = 1;
1516 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1517 }
1518 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, 0);
1519 break;
1520
1521 case IDC_CHECK_POINTER_TRAIL:
1522 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1523 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL))
1524 {
1525 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1526 EnableWindow(hDlgCtrl, FALSE);
1527 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE);
1528 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE);
1529 pOptionData->uMouseTrails = 0;
1530 }
1531 else
1532 {
1533 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1534 EnableWindow(hDlgCtrl, TRUE);
1535 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), TRUE);
1536 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), TRUE);
1537 pOptionData->uMouseTrails = (UINT)SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2;
1538 }
1539 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, 0);
1540 break;
1541
1542 case IDC_CHECK_HIDE_POINTER:
1543 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_HIDE_POINTER))
1544 {
1545 pOptionData->bMouseVanish = FALSE;
1546 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1547 }
1548 else
1549 {
1550 pOptionData->bMouseVanish = TRUE;
1551 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1552 }
1553 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, (PVOID)pOptionData->bMouseVanish, 0);
1554 break;
1555
1556 case IDC_CHECK_SHOW_POINTER:
1557 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHOW_POINTER))
1558 {
1559 pOptionData->bMouseSonar = FALSE;
1560 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1561 }
1562 else
1563 {
1564 pOptionData->bMouseSonar = TRUE;
1565 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1566 }
1567 SystemParametersInfo(SPI_SETMOUSESONAR, 0, (PVOID)pOptionData->bMouseSonar, 0);
1568 break;
1569
1570 }
1571 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1572 break;
1573
1574 case WM_NOTIFY:
1575 lppsn = (LPPSHNOTIFY)lParam;
1576 if (lppsn->hdr.code == PSN_APPLY)
1577 {
1578 /* Set mouse speed */
1579 if (pOptionData->ulOrigMouseSpeed != pOptionData->ulMouseSpeed)
1580 {
1581 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSpeed, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1582 pOptionData->ulOrigMouseSpeed = pOptionData->ulMouseSpeed;
1583 }
1584
1585 if (pOptionData->OrigMouseAccel.nAcceleration != pOptionData->MouseAccel.nAcceleration)
1586 {
1587 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1588 pOptionData->OrigMouseAccel.nAcceleration = pOptionData->MouseAccel.nAcceleration;
1589 pOptionData->OrigMouseAccel.nThreshold1 = pOptionData->MouseAccel.nThreshold1;
1590 pOptionData->OrigMouseAccel.nThreshold2 = pOptionData->MouseAccel.nThreshold2;
1591 }
1592
1593
1594 /* set snap to default button */
1595 if (pOptionData->bOrigSnapToDefaultButton != pOptionData->bSnapToDefaultButton)
1596 {
1597 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1598 pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton;
1599 }
1600
1601 /* Set mouse trails setting */
1602 if (pOptionData->uOrigMouseTrails != pOptionData->uMouseTrails)
1603 {
1604 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1605 pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails;
1606 }
1607
1608 /* hide pointer while typing */
1609 if (pOptionData->bOrigMouseVanish != pOptionData->bMouseVanish)
1610 {
1611 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, (PVOID)pOptionData->bMouseVanish, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1612 pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish;
1613 }
1614
1615 /* show pointer with Ctrl-Key */
1616 if (pOptionData->bOrigMouseSonar != pOptionData->bMouseSonar)
1617 {
1618 SystemParametersInfo(SPI_SETMOUSESONAR, 0, (PVOID)pOptionData->bMouseSonar, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1619 pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar;
1620 }
1621 return TRUE;
1622 }
1623 else if (lppsn->hdr.code == PSN_RESET)
1624 {
1625 /* Set the original mouse speed */
1626 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulOrigMouseSpeed, 0);
1627 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->OrigMouseAccel, 0);
1628 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bOrigSnapToDefaultButton, 0, 0);
1629 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uOrigMouseTrails, 0, 0);
1630 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, (PVOID)pOptionData->bOrigMouseVanish, 0);
1631 SystemParametersInfo(SPI_SETMOUSESONAR, 0, (PVOID)pOptionData->bOrigMouseSonar, 0);
1632 }
1633 break;
1634
1635 case WM_HSCROLL:
1636 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED))
1637 {
1638 switch (LOWORD(wParam))
1639 {
1640 case TB_LINEUP:
1641 case TB_LINEDOWN:
1642 case TB_PAGEUP:
1643 case TB_PAGEDOWN:
1644 case TB_TOP:
1645 case TB_BOTTOM:
1646 case TB_ENDTRACK:
1647 pOptionData->ulMouseSpeed = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_MOUSE_SPEED, TBM_GETPOS, 0, 0) + 1;
1648 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSpeed, SPIF_SENDCHANGE);
1649 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1650 break;
1651 #if 0
1652 case TB_THUMBTRACK:
1653 pOptionData->ulMouseSpeed = (ULONG)HIWORD(wParam) + 1;
1654 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSpeed, SPIF_SENDCHANGE);
1655 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1656 break;
1657 #endif
1658 }
1659 }
1660 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL))
1661 {
1662 switch (LOWORD(wParam))
1663 {
1664 case TB_LINEUP:
1665 case TB_LINEDOWN:
1666 case TB_PAGEUP:
1667 case TB_PAGEDOWN:
1668 case TB_TOP:
1669 case TB_BOTTOM:
1670 case TB_ENDTRACK:
1671 pOptionData->uMouseTrails = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_POINTER_TRAIL, TBM_GETPOS, 0, 0) + 2;
1672 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE);
1673 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1674 break;
1675
1676 case TB_THUMBTRACK:
1677 pOptionData->uMouseTrails = (ULONG)HIWORD(wParam) + 2;
1678 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE);
1679 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1680 break;
1681 }
1682 }
1683 break;
1684 }
1685
1686 return FALSE;
1687 }
1688
1689
1690 static VOID
1691 ShowDialogWheelControls(HWND hwndDlg, UINT uWheelScrollLines, BOOL bInit)
1692 {
1693 HWND hDlgCtrl;
1694
1695 if (uWheelScrollLines != WHEEL_PAGESCROLL)
1696 {
1697 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1698 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1699
1700 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1701 EnableWindow(hDlgCtrl, TRUE);
1702
1703 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1704 EnableWindow(hDlgCtrl, TRUE);
1705
1706 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1707 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1708 }
1709 else
1710 {
1711 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1712 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1713
1714 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1715 EnableWindow(hDlgCtrl, FALSE);
1716
1717 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1718 EnableWindow(hDlgCtrl, FALSE);
1719
1720 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1721 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1722
1723 /* Set the default scroll lines value */
1724 if (bInit == TRUE)
1725 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, DEFAULT_WHEEL_SCROLL_LINES, FALSE);
1726 }
1727 }
1728
1729
1730 static INT_PTR CALLBACK
1731 WheelProc(IN HWND hwndDlg,
1732 IN UINT uMsg,
1733 IN WPARAM wParam,
1734 IN LPARAM lParam)
1735 {
1736 LPPSHNOTIFY lppsn;
1737 PWHEEL_DATA pWheelData;
1738
1739 pWheelData = (PWHEEL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1740
1741 switch (uMsg)
1742 {
1743 case WM_INITDIALOG:
1744 pWheelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WHEEL_DATA));
1745 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pWheelData);
1746
1747 /* Get wheel scroll lines */
1748 if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pWheelData->uWheelScrollLines, 0))
1749 {
1750 pWheelData->uWheelScrollLines = DEFAULT_WHEEL_SCROLL_LINES;
1751 }
1752
1753 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, TRUE);
1754 SendDlgItemMessage(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES, UDM_SETRANGE, 0, MAKELONG((short)100, (short)0));
1755 if (pWheelData->uWheelScrollLines != WHEEL_PAGESCROLL)
1756 {
1757 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, pWheelData->uWheelScrollLines, FALSE);
1758 }
1759 return TRUE;
1760
1761 case WM_DESTROY:
1762 HeapFree(GetProcessHeap(), 0, pWheelData);
1763 break;
1764
1765 case WM_COMMAND:
1766 switch (LOWORD(wParam))
1767 {
1768 case IDC_RADIO_WHEEL_SCROLL_LINES:
1769 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1770 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1771 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1772 break;
1773
1774 case IDC_RADIO_WHEEL_SCROLL_PAGE:
1775 pWheelData->uWheelScrollLines = WHEEL_PAGESCROLL;
1776 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1777 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1778 break;
1779
1780 case IDC_EDIT_WHEEL_SCROLL_LINES:
1781 if (pWheelData && HIWORD(wParam) == EN_CHANGE)
1782 {
1783 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1784 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1785 }
1786 break;
1787 }
1788 break;
1789
1790 case WM_NOTIFY:
1791 lppsn = (LPPSHNOTIFY)lParam;
1792 if (lppsn->hdr.code == PSN_APPLY)
1793 {
1794 SystemParametersInfo(SPI_SETWHEELSCROLLLINES, pWheelData->uWheelScrollLines,
1795 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1796 return TRUE;
1797 }
1798 break;
1799 }
1800
1801 return FALSE;
1802 }
1803
1804 static const struct
1805 {
1806 WORD idDlg;
1807 DLGPROC DlgProc;
1808 UINT uiReplaceWith;
1809 } PropPages[] =
1810 {
1811 { IDD_PAGE_BUTTON, ButtonProc, CPLPAGE_MOUSE_BUTTONS },
1812 { IDD_PAGE_POINTER, PointerProc, 0 },
1813 { IDD_PAGE_OPTION, OptionProc, CPLPAGE_MOUSE_PTRMOTION },
1814 { IDD_PAGE_WHEEL, WheelProc, CPLPAGE_MOUSE_WHEEL },
1815 { IDD_HARDWARE, MouseHardwareProc, 0 },
1816 };
1817
1818 LONG APIENTRY
1819 MouseApplet(HWND hwnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
1820 {
1821 HPROPSHEETPAGE hpsp[MAX_CPL_PAGES];
1822 PROPSHEETHEADER psh;
1823 HPSXA hpsxa;
1824 TCHAR Caption[256];
1825 UINT i;
1826 LONG ret;
1827
1828 UNREFERENCED_PARAMETER(lParam1);
1829 UNREFERENCED_PARAMETER(lParam2);
1830 UNREFERENCED_PARAMETER(uMsg);
1831 UNREFERENCED_PARAMETER(hwnd);
1832
1833 LoadString(hApplet, IDS_CPLNAME_1, Caption, sizeof(Caption) / sizeof(TCHAR));
1834
1835 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
1836 psh.dwSize = sizeof(PROPSHEETHEADER);
1837 psh.dwFlags = PSH_PROPTITLE;
1838 psh.hwndParent = NULL;
1839 psh.hInstance = hApplet;
1840 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_1));
1841 psh.pszCaption = Caption;
1842 psh.nStartPage = 0;
1843 psh.phpage = hpsp;
1844
1845 /* Load additional pages provided by shell extensions */
1846 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Mouse"), MAX_CPL_PAGES - psh.nPages);
1847
1848 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
1849 {
1850 /* Override the background page if requested by a shell extension */
1851 if (PropPages[i].uiReplaceWith != 0 && hpsxa != NULL &&
1852 SHReplaceFromPropSheetExtArray(hpsxa, PropPages[i].uiReplaceWith, PropSheetAddPage, (LPARAM)&psh) != 0)
1853 {
1854 /* The shell extension added one or more pages to replace a page.
1855 Don't create the built-in page anymore! */
1856 continue;
1857 }
1858
1859 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc);
1860 }
1861
1862 if (hpsxa != NULL)
1863 SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh);
1864
1865 ret = (LONG)(PropertySheet(&psh) != -1);
1866
1867 if (hpsxa != NULL)
1868 SHDestroyPropSheetExtArray(hpsxa);
1869
1870 return ret;
1871 }
1872
1873 /* EOF */