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