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