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