0b8914a6a2f6a799dc209fa994663586501923c7
[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 = szTempData + 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 szNewSchemeName[0] = 0;
722 }
723 else
724 {
725 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szNewSchemeName);
726
727 if (_tcsstr(szNewSchemeName, szSystemScheme))
728 {
729 szNewSchemeName[_tcslen(szNewSchemeName) - _tcslen(szSystemScheme) - 1] = 0;
730 }
731 }
732
733 /* Ask for a name for the new cursor scheme */
734 if (!DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CURSOR_SCHEME_SAVEAS),
735 hwndDlg, SaveSchemeProc, (LPARAM)szNewSchemeName))
736 return TRUE;
737
738 /* Check all non-system schemes for the new name */
739 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCOUNT, 0, 0);
740 if (nSel == CB_ERR)
741 return FALSE;
742
743 bSchemeExists = FALSE;
744 for (i = 0; i < nSel; i++)
745 {
746 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, i, (LPARAM)szSchemeName);
747 if (_tcsstr(szSchemeName, szSystemScheme) == NULL)
748 {
749 if (_tcscmp(szSchemeName, szNewSchemeName) == 0)
750 {
751 bSchemeExists = TRUE;
752 break;
753 }
754 }
755 }
756
757 if (bSchemeExists)
758 {
759 LoadString(hApplet, IDS_OVERWRITE_TITLE, szTitle, 128);
760 LoadString(hApplet, IDS_OVERWRITE_TEXT, szText, 256);
761
762 /* Confirm scheme overwrite */
763 if (MessageBox(hwndDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO)
764 return TRUE;
765 }
766
767 /* Save the cursor scheme */
768 nLength = 0;
769 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
770 {
771 if (i > 0)
772 nLength++;
773 nLength += _tcslen(g_CursorData[i].szCursorPath);
774 }
775 nLength++;
776
777 lpSchemeData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(TCHAR));
778
779 if(!lpSchemeData)
780 return FALSE;
781
782 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
783 {
784 CompressPath(szTempPath, g_CursorData[i].szCursorPath);
785 if (i > 0)
786 _tcscat(lpSchemeData, _T(","));
787 _tcscat(lpSchemeData, szTempPath);
788 }
789
790 if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS)
791 {
792 HeapFree(GetProcessHeap(), 0, lpSchemeData);
793 return FALSE;
794 }
795
796 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS)
797 {
798 RegCloseKey(hCuKey);
799 HeapFree(GetProcessHeap(), 0, lpSchemeData);
800 return FALSE;
801 }
802
803 lError = RegSetValueEx(hCuCursorKey, szNewSchemeName, 0,
804 REG_EXPAND_SZ, (LPBYTE)lpSchemeData,
805 (_tcslen(lpSchemeData) + 1) * sizeof(TCHAR));
806
807 RegCloseKey(hCuCursorKey);
808 RegCloseKey(hCuKey);
809
810 /* Add the new scheme to the scheme list and select it */
811 if (lError == ERROR_SUCCESS)
812 {
813 LPTSTR copy = _tcsdup(lpSchemeData);
814
815 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_ADDSTRING, (WPARAM)0, (LPARAM)szNewSchemeName);
816 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETITEMDATA, (WPARAM)nSel, (LPARAM)copy);
817 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0);
818 }
819
820 HeapFree(GetProcessHeap(), 0, lpSchemeData);
821
822 return (lError == ERROR_SUCCESS);
823 }
824
825
826 static BOOL
827 BrowseCursor(HWND hwndDlg)
828 {
829 TCHAR szFileName[MAX_PATH];
830 TCHAR szFilter[MAX_PATH];
831 TCHAR szTitle[MAX_PATH];
832 OPENFILENAME ofn;
833 INT nSel;
834
835 LoadString(hApplet, IDS_BROWSE_FILTER, szFilter, MAX_PATH);
836 LoadString(hApplet, IDS_BROWSE_TITLE, szTitle, MAX_PATH);
837
838 memset(szFileName, 0x0, sizeof(szFileName));
839 nSel = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
840 if (nSel == LB_ERR)
841 {
842 MessageBox(hwndDlg, _T("LB_ERR"), _T(""), MB_ICONERROR);
843 return FALSE;
844 }
845
846 ZeroMemory(&ofn, sizeof(OPENFILENAME));
847 ofn.lStructSize = sizeof(OPENFILENAME);
848 ofn.hwndOwner = hwndDlg;
849 ofn.lpstrFilter = szFilter;
850 ofn.nFilterIndex = 1;
851 ofn.lpstrFile = szFileName;
852 ofn.nMaxFile = MAX_PATH;
853 ofn.lpstrInitialDir = _T("%WINDIR%\\Cursors");
854 ofn.lpstrTitle = szTitle;
855 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
856
857 if (!GetOpenFileName(&ofn))
858 return FALSE;
859
860 /* Store the new cursor file path */
861 _tcsncpy(g_CursorData[nSel].szCursorPath, szFileName, MAX_PATH);
862
863 return TRUE;
864 }
865
866
867 static VOID
868 LoadCursorScheme(LPTSTR lpName, BOOL bSystem)
869 {
870 UINT index, i;
871
872 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
873 {
874 if (g_CursorData[i].hCursor != NULL)
875 {
876 DestroyCursor(g_CursorData[i].hCursor);
877 g_CursorData[i].hCursor = 0;
878 }
879 g_CursorData[i].szCursorPath[0] = 0;
880 }
881
882 if (lpName != NULL)
883 {
884 LPTSTR pStart = lpName;
885 LPTSTR pEnd = pStart;
886 INT nLength;
887
888 i = 0;
889 while (pEnd)
890 {
891 pEnd = _tcschr(pStart, _T(','));
892 if (pEnd)
893 nLength = ((INT_PTR)pEnd - (INT_PTR)pStart) / sizeof(TCHAR);
894 else
895 nLength = _tcslen(pStart);
896
897 _tcsncpy(g_CursorData[i].szCursorPath, pStart, nLength);
898 g_CursorData[i].szCursorPath[nLength] = 0;
899
900 pStart = pStart + (nLength + 1);
901 i++;
902 }
903
904 }
905
906 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
907 {
908 if (g_CursorData[i].szCursorPath[0] == 0)
909 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId),
910 IMAGE_CURSOR, 0, 0,
911 LR_DEFAULTSIZE | LR_SHARED);
912 else
913 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
914 IMAGE_CURSOR, 0, 0,
915 LR_LOADFROMFILE | LR_DEFAULTSIZE);
916 }
917 }
918
919
920 static VOID
921 ReloadCurrentCursorScheme(VOID)
922 {
923 UINT index, i;
924
925 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
926 {
927 if (g_CursorData[i].hCursor != NULL)
928 DestroyCursor(g_CursorData[i].hCursor);
929
930 if (g_CursorData[i].szCursorPath[0] == 0)
931 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId),
932 IMAGE_CURSOR, 0, 0,
933 LR_DEFAULTSIZE | LR_SHARED);
934 else
935 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
936 IMAGE_CURSOR, 0, 0,
937 LR_LOADFROMFILE | LR_DEFAULTSIZE);
938 }
939 }
940
941
942 static VOID
943 OnDrawItem(UINT idCtl,
944 LPDRAWITEMSTRUCT lpdis,
945 PPOINTER_DATA pPointerData)
946 {
947 RECT rc;
948
949 if (lpdis->itemState & ODS_SELECTED)
950 {
951 FillRect(lpdis->hDC,
952 &lpdis->rcItem,
953 (HBRUSH)(COLOR_HIGHLIGHT + 1));
954 SetBkColor(lpdis->hDC,
955 GetSysColor(COLOR_HIGHLIGHT));
956 SetTextColor(lpdis->hDC,
957 GetSysColor(COLOR_HIGHLIGHTTEXT));
958 }
959 else
960 {
961 FillRect(lpdis->hDC,
962 &lpdis->rcItem,
963 (HBRUSH)(COLOR_WINDOW + 1));
964 SetBkColor(lpdis->hDC,
965 GetSysColor(COLOR_WINDOW));
966 SetTextColor(lpdis->hDC,
967 GetSysColor(COLOR_WINDOWTEXT));
968 }
969
970 if (lpdis->itemID != (UINT)-1)
971 {
972 CopyRect(&rc, &lpdis->rcItem);
973 rc.left += 5;
974 DrawText(lpdis->hDC,
975 g_CursorData[lpdis->itemData].szCursorName,
976 -1,
977 &rc,
978 DT_SINGLELINE | DT_VCENTER | DT_LEFT);
979
980 if (g_CursorData[lpdis->itemData].hCursor != NULL)
981 {
982 DrawIcon(lpdis->hDC,
983 lpdis->rcItem.right - pPointerData->cxCursor - 4,
984 lpdis->rcItem.top + 2,
985 g_CursorData[lpdis->itemData].hCursor);
986 }
987 }
988
989 if (lpdis->itemState & ODS_FOCUS)
990 {
991 CopyRect(&rc, &lpdis->rcItem);
992 InflateRect(&rc, -1, -1);
993 DrawFocusRect(lpdis->hDC, &rc);
994 }
995 }
996
997
998 static VOID
999 LoadNewCursorScheme(HWND hwndDlg)
1000 {
1001 TCHAR buffer[MAX_PATH];
1002 TCHAR szSystemScheme[MAX_PATH];
1003 HWND hDlgCtrl;
1004 BOOL bEnable;
1005 LPTSTR lpName;
1006 INT nSel;
1007
1008 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
1009 if (nSel == CB_ERR)
1010 return;
1011
1012 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)buffer);
1013
1014 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1015 if (_tcsstr(buffer, szSystemScheme) || nSel == 0) // Avoid the default scheme - Can be deleted
1016 bEnable = FALSE;
1017 else
1018 bEnable = TRUE;
1019
1020 /* Delete button */
1021 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME);
1022 EnableWindow(hDlgCtrl, bEnable);
1023
1024 lpName = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0);
1025 LoadCursorScheme(lpName, !bEnable);
1026 RefreshCursorList(hwndDlg, FALSE);
1027 }
1028
1029
1030 static VOID
1031 LoadInitialCursorScheme(HWND hwndDlg)
1032 {
1033 TCHAR szSchemeName[MAX_PATH];
1034 TCHAR szSystemScheme[MAX_PATH];
1035 TCHAR szCursorPath[MAX_PATH];
1036 HKEY hCursorKey;
1037 LONG lError;
1038 DWORD dwDataSize;
1039 DWORD dwSchemeSource = 0;
1040 UINT index, i;
1041 DWORD dwType;
1042 INT nSel;
1043
1044 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1045 {
1046 g_CursorData[i].hCursor = 0;
1047 g_CursorData[i].szCursorPath[0] = 0;
1048 }
1049
1050 lError = RegOpenKeyEx(HKEY_CURRENT_USER,
1051 _T("Control Panel\\Cursors"),
1052 0,
1053 KEY_READ | KEY_QUERY_VALUE,
1054 &hCursorKey);
1055 if (lError != ERROR_SUCCESS)
1056 return;
1057
1058 dwDataSize = sizeof(DWORD);
1059 lError = RegQueryValueEx(hCursorKey,
1060 _T("Scheme Source"),
1061 NULL,
1062 NULL,
1063 (LPBYTE)&dwSchemeSource,
1064 &dwDataSize);
1065
1066 if (dwSchemeSource != 0)
1067 {
1068 dwDataSize = MAX_PATH * sizeof(TCHAR);
1069 lError = RegQueryValueEx(hCursorKey,
1070 NULL,
1071 NULL,
1072 NULL,
1073 (LPBYTE)szSchemeName,
1074 &dwDataSize);
1075
1076 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1077 {
1078 dwDataSize = MAX_PATH * sizeof(TCHAR);
1079 lError = RegQueryValueEx(hCursorKey,
1080 g_CursorData[i].lpValueName,
1081 NULL,
1082 &dwType,
1083 (LPBYTE)szCursorPath,
1084 &dwDataSize);
1085 if (lError == ERROR_SUCCESS)
1086 {
1087 if (dwType == REG_EXPAND_SZ)
1088 {
1089 ExpandEnvironmentStrings(szCursorPath, g_CursorData[i].szCursorPath, MAX_PATH);
1090 }
1091 else
1092 {
1093 _tcscpy(g_CursorData[i].szCursorPath, szCursorPath);
1094 }
1095 }
1096 }
1097 }
1098
1099 RegCloseKey(hCursorKey);
1100
1101 ReloadCurrentCursorScheme();
1102 RefreshCursorList(hwndDlg, TRUE);
1103
1104 /* Build the full scheme name */
1105 if (dwSchemeSource == 0)
1106 {
1107 LoadString(hApplet, IDS_NONE, szSchemeName, MAX_PATH);
1108 }
1109 else if (dwSchemeSource == 2)
1110 {
1111 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1112 _tcsncat(szSchemeName, _T(" "), MAX_PATH - _tcslen(szSchemeName) - 1);
1113 _tcsncat(szSchemeName, szSystemScheme, MAX_PATH - _tcslen(szSchemeName) - 1);
1114 }
1115
1116 /* Search and select the curent scheme name from the scheme list */
1117 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_FINDSTRINGEXACT, -1, (LPARAM)szSchemeName);
1118 if (nSel != CB_ERR)
1119 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0);
1120
1121 /* Enable /disable delete button */
1122 EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME), (dwSchemeSource == 1));
1123 }
1124
1125
1126 static BOOL
1127 ApplyCursorScheme(HWND hwndDlg)
1128 {
1129 TCHAR szSchemeName[MAX_PATH];
1130 TCHAR szSystemScheme[MAX_PATH];
1131 TCHAR szTempPath[MAX_PATH];
1132 LPTSTR lpSchemeData;
1133 DWORD dwNameLength;
1134 DWORD dwSchemeSource;
1135 UINT index, i;
1136 HKEY hCursorKey;
1137 INT nSel;
1138
1139 nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0);
1140 if (nSel == CB_ERR)
1141 return FALSE;
1142
1143 lpSchemeData = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0);
1144 if (lpSchemeData == NULL)
1145 {
1146 /* "None" cursor scheme */
1147 dwSchemeSource = 0;
1148 szSchemeName[0] = 0;
1149 dwNameLength = 0;
1150 }
1151 else
1152 {
1153 SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szSchemeName);
1154 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
1155
1156 if (_tcsstr(szSchemeName, szSystemScheme))
1157 {
1158 /* System scheme */
1159 dwSchemeSource = 2;
1160 szSchemeName[_tcslen(szSchemeName) - _tcslen(szSystemScheme) - 1] = 0;
1161 }
1162 else
1163 {
1164 /* User scheme */
1165 dwSchemeSource = 1;
1166 }
1167
1168 dwNameLength = (_tcslen(szSchemeName) + 1) * sizeof(TCHAR);
1169 }
1170
1171 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors"), 0,
1172 KEY_READ | KEY_SET_VALUE, &hCursorKey) != ERROR_SUCCESS)
1173 return FALSE;
1174
1175 RegSetValueEx(hCursorKey, NULL, 0, REG_SZ,
1176 (LPBYTE)szSchemeName, dwNameLength);
1177
1178 RegSetValueEx(hCursorKey, _T("Scheme Source"), 0, REG_DWORD,
1179 (LPBYTE)&dwSchemeSource, sizeof(DWORD));
1180
1181 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
1182 {
1183 CompressPath(szTempPath, g_CursorData[i].szCursorPath);
1184 RegSetValueEx(hCursorKey, g_CursorData[i].lpValueName, 0,
1185 REG_EXPAND_SZ, (LPBYTE)szTempPath,
1186 (_tcslen(szTempPath) + 1) * sizeof(TCHAR));
1187 }
1188
1189 RegCloseKey(hCursorKey);
1190
1191 /* Force the system to reload its cursors */
1192 SystemParametersInfo(SPI_SETCURSORS, 0, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1193
1194 return TRUE;
1195 }
1196
1197
1198 static INT_PTR CALLBACK
1199 PointerProc(IN HWND hwndDlg,
1200 IN UINT uMsg,
1201 IN WPARAM wParam,
1202 IN LPARAM lParam)
1203 {
1204 PPOINTER_DATA pPointerData;
1205 LPPSHNOTIFY lppsn;
1206 INT nSel;
1207
1208 pPointerData = (PPOINTER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1209
1210 switch (uMsg)
1211 {
1212 case WM_INITDIALOG:
1213 pPointerData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(POINTER_DATA));
1214 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pPointerData);
1215
1216 pPointerData->cxCursor = GetSystemMetrics(SM_CXCURSOR);
1217 pPointerData->cyCursor = GetSystemMetrics(SM_CYCURSOR);
1218
1219 EnumerateCursorSchemes(hwndDlg);
1220 LoadInitialCursorScheme(hwndDlg);
1221
1222 /* Get cursor shadow setting */
1223 SystemParametersInfo(SPI_GETCURSORSHADOW, 0, &pPointerData->bCursorShadow, 0);
1224 pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow;
1225
1226 if (pPointerData->bCursorShadow)
1227 {
1228 SendDlgItemMessage(hwndDlg, IDC_CHECK_CURSOR_SHADOW, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1229 }
1230
1231 if ((INT)wParam == IDC_LISTBOX_CURSOR)
1232 return TRUE;
1233 else
1234 return FALSE;
1235
1236 case WM_MEASUREITEM:
1237 ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = GetSystemMetrics(SM_CYCURSOR) + 4;
1238 break;
1239
1240 case WM_DRAWITEM:
1241 if (wParam == IDC_LISTBOX_CURSOR)
1242 OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam, pPointerData);
1243 return TRUE;
1244
1245 case WM_DESTROY:
1246 HeapFree(GetProcessHeap(), 0, pPointerData);
1247 break;
1248
1249 case WM_NOTIFY:
1250 lppsn = (LPPSHNOTIFY) lParam;
1251 if (lppsn->hdr.code == PSN_APPLY)
1252 {
1253 ApplyCursorScheme(hwndDlg);
1254 //#if (WINVER >= 0x0500)
1255 if (pPointerData->bOrigCursorShadow != pPointerData->bCursorShadow)
1256 {
1257 SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1258 pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow;
1259 }
1260 //#endif
1261 return TRUE;
1262 }
1263 else if (lppsn->hdr.code == PSN_RESET)
1264 {
1265 //#if (WINVER >= 0x0500)
1266 SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bOrigCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1267 //#endif
1268 }
1269 break;
1270
1271 case WM_COMMAND:
1272 switch (LOWORD(wParam))
1273 {
1274 case IDC_COMBO_CURSOR_SCHEME:
1275 if (HIWORD(wParam) == CBN_SELENDOK)
1276 {
1277 LoadNewCursorScheme(hwndDlg);
1278 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1279 }
1280 break;
1281
1282 case IDC_LISTBOX_CURSOR:
1283 switch (HIWORD(wParam))
1284 {
1285 case LBN_SELCHANGE:
1286 nSel = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
1287
1288 if(nSel == LB_ERR)
1289 break;
1290
1291 SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR,
1292 (LPARAM)g_CursorData[nSel].hCursor);
1293 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR),
1294 (g_CursorData[nSel].szCursorPath[0] != 0));
1295 break;
1296
1297 case LBN_DBLCLK:
1298 if (BrowseCursor(hwndDlg))
1299 {
1300 /* Update cursor list and preview */
1301 ReloadCurrentCursorScheme();
1302 RefreshCursorList(hwndDlg, FALSE);
1303
1304 /* Enable the "Set Default" button */
1305 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), TRUE);
1306
1307 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1308 }
1309 break;
1310 }
1311 break;
1312
1313 case IDC_BUTTON_SAVEAS_SCHEME:
1314 SaveCursorScheme(hwndDlg);
1315 break;
1316
1317 case IDC_BUTTON_USE_DEFAULT_CURSOR:
1318 nSel = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
1319 if (nSel != LB_ERR)
1320 {
1321 /* Clean the path of the currently selected cursor */
1322 memset(g_CursorData[nSel].szCursorPath, 0x0, MAX_PATH * sizeof(TCHAR));
1323
1324 /* Update cursor list and preview */
1325 ReloadCurrentCursorScheme();
1326 RefreshCursorList(hwndDlg, FALSE);
1327
1328 /* Disable the "Set Default" button */
1329 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), FALSE);
1330
1331 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1332 }
1333 break;
1334
1335 case IDC_BUTTON_BROWSE_CURSOR:
1336 if (BrowseCursor(hwndDlg))
1337 {
1338 /* Update cursor list and preview */
1339 ReloadCurrentCursorScheme();
1340 RefreshCursorList(hwndDlg, FALSE);
1341
1342 /* Enable the "Set Default" button */
1343 EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), TRUE);
1344
1345 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1346 }
1347 break;
1348
1349 case IDC_BUTTON_DELETE_SCHEME:
1350 DeleteUserCursorScheme(hwndDlg);
1351 break;
1352
1353 case IDC_CHECK_CURSOR_SHADOW:
1354 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_CURSOR_SHADOW))
1355 {
1356 pPointerData->bCursorShadow = FALSE;
1357 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1358 //#if (WINVER >= 0x0500)
1359 // SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, 0);
1360 //#endif
1361 // PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1362 }
1363 else
1364 {
1365 pPointerData->bCursorShadow = TRUE;
1366 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1367 }
1368 //#if (WINVER >= 0x0500)
1369 //SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1370 //#endif
1371 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1372 break;
1373 }
1374 break;
1375 }
1376
1377 return FALSE;
1378 }
1379
1380
1381 static INT_PTR CALLBACK
1382 OptionProc(IN HWND hwndDlg,
1383 IN UINT uMsg,
1384 IN WPARAM wParam,
1385 IN LPARAM lParam)
1386 {
1387 POPTION_DATA pOptionData;
1388 HWND hDlgCtrl;
1389 LPPSHNOTIFY lppsn;
1390
1391 pOptionData = (POPTION_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1392
1393 switch(uMsg)
1394 {
1395 case WM_INITDIALOG:
1396 pOptionData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPTION_DATA));
1397 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pOptionData);
1398
1399 /* Get mouse sensitivity */
1400 if (!SystemParametersInfo(SPI_GETMOUSESPEED, 0, &pOptionData->ulMouseSpeed, 0))
1401 pOptionData->ulMouseSpeed = DEFAULT_MOUSE_SPEED;
1402 pOptionData->ulOrigMouseSpeed = pOptionData->ulMouseSpeed;
1403
1404
1405 if (!SystemParametersInfo(SPI_GETMOUSE, 0, &pOptionData->MouseAccel, 0))
1406 {
1407 pOptionData->MouseAccel.nAcceleration = DEFAULT_MOUSE_ACCELERATION;
1408 pOptionData->MouseAccel.nThreshold1 = DEFAULT_MOUSE_THRESHOLD1;
1409 pOptionData->MouseAccel.nThreshold2 = DEFAULT_MOUSE_THRESHOLD2;
1410 }
1411 pOptionData->OrigMouseAccel.nAcceleration = pOptionData->MouseAccel.nAcceleration;
1412 pOptionData->OrigMouseAccel.nThreshold1 = pOptionData->MouseAccel.nThreshold1;
1413 pOptionData->OrigMouseAccel.nThreshold2 = pOptionData->MouseAccel.nThreshold2;
1414
1415 /* Snap to default button */
1416 SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &pOptionData->bSnapToDefaultButton, 0);
1417 pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton;
1418
1419 /* Mouse trails */
1420 SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &pOptionData->uMouseTrails, 0);
1421 pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails;
1422
1423 /* Hide pointer while typing */
1424 SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &pOptionData->bMouseVanish, 0);
1425 pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish;
1426
1427 /* Show pointer with Ctrl-Key */
1428 SystemParametersInfo(SPI_GETMOUSESONAR, 0, &pOptionData->bMouseSonar, 0);
1429 pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar;
1430
1431 /* Set mouse speed */
1432 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED);
1433 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(1, 20));
1434 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->ulMouseSpeed);
1435
1436 if (pOptionData->MouseAccel.nAcceleration)
1437 {
1438 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_POINTER_PRECISION);
1439 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1440 }
1441
1442 if (pOptionData->bSnapToDefaultButton)
1443 {
1444 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SNAP_TO);
1445 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1446 }
1447
1448 /* Set mouse trail */
1449 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1450 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 5));
1451 if (pOptionData->uMouseTrails < 2)
1452 {
1453 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)5);
1454 EnableWindow(hDlgCtrl, FALSE);
1455 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE);
1456 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE);
1457 }
1458 else
1459 {
1460 SendDlgItemMessage(hwndDlg, IDC_CHECK_POINTER_TRAIL, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1461 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->uMouseTrails - 2);
1462 }
1463
1464 if (pOptionData->bMouseVanish)
1465 {
1466 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_HIDE_POINTER);
1467 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1468 }
1469
1470 if (pOptionData->bMouseSonar)
1471 {
1472 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SHOW_POINTER);
1473 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1474 }
1475
1476 break;
1477
1478 case WM_DESTROY:
1479 HeapFree(GetProcessHeap(), 0, pOptionData);
1480 break;
1481
1482 case WM_COMMAND:
1483 switch(LOWORD(wParam))
1484 {
1485 case IDC_CHECK_POINTER_PRECISION:
1486 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_PRECISION))
1487 {
1488 pOptionData->MouseAccel.nAcceleration = 0;
1489 pOptionData->MouseAccel.nThreshold1 = 0;
1490 pOptionData->MouseAccel.nThreshold2 = 0;
1491 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1492 }
1493 else
1494 {
1495 pOptionData->MouseAccel.nAcceleration = 1;
1496 pOptionData->MouseAccel.nThreshold1 = 6;
1497 pOptionData->MouseAccel.nThreshold2 = 10;
1498 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1499 }
1500 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, 0);
1501 break;
1502
1503 case IDC_CHECK_SNAP_TO:
1504 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SNAP_TO))
1505 {
1506 pOptionData->bSnapToDefaultButton = 0;
1507 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1508 }
1509 else
1510 {
1511 pOptionData->bSnapToDefaultButton = 1;
1512 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1513 }
1514 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, 0);
1515 break;
1516
1517 case IDC_CHECK_POINTER_TRAIL:
1518 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1519 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL))
1520 {
1521 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1522 EnableWindow(hDlgCtrl, FALSE);
1523 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE);
1524 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE);
1525 pOptionData->uMouseTrails = 0;
1526 }
1527 else
1528 {
1529 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1530 EnableWindow(hDlgCtrl, TRUE);
1531 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), TRUE);
1532 EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), TRUE);
1533 pOptionData->uMouseTrails = (UINT)SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2;
1534 }
1535 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, 0);
1536 break;
1537
1538 case IDC_CHECK_HIDE_POINTER:
1539 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_HIDE_POINTER))
1540 {
1541 pOptionData->bMouseVanish = FALSE;
1542 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1543 }
1544 else
1545 {
1546 pOptionData->bMouseVanish = TRUE;
1547 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1548 }
1549 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bMouseVanish), 0);
1550 break;
1551
1552 case IDC_CHECK_SHOW_POINTER:
1553 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHOW_POINTER))
1554 {
1555 pOptionData->bMouseSonar = FALSE;
1556 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1557 }
1558 else
1559 {
1560 pOptionData->bMouseSonar = TRUE;
1561 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1562 }
1563 SystemParametersInfo(SPI_SETMOUSESONAR, 0, IntToPtr(pOptionData->bMouseSonar), 0);
1564 break;
1565
1566 }
1567 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1568 break;
1569
1570 case WM_NOTIFY:
1571 lppsn = (LPPSHNOTIFY)lParam;
1572 if (lppsn->hdr.code == PSN_APPLY)
1573 {
1574 /* Set mouse speed */
1575 if (pOptionData->ulOrigMouseSpeed != pOptionData->ulMouseSpeed)
1576 {
1577 SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulMouseSpeed), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1578 pOptionData->ulOrigMouseSpeed = pOptionData->ulMouseSpeed;
1579 }
1580
1581 if (pOptionData->OrigMouseAccel.nAcceleration != pOptionData->MouseAccel.nAcceleration)
1582 {
1583 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1584 pOptionData->OrigMouseAccel.nAcceleration = pOptionData->MouseAccel.nAcceleration;
1585 pOptionData->OrigMouseAccel.nThreshold1 = pOptionData->MouseAccel.nThreshold1;
1586 pOptionData->OrigMouseAccel.nThreshold2 = pOptionData->MouseAccel.nThreshold2;
1587 }
1588
1589
1590 /* Set snap to default button */
1591 if (pOptionData->bOrigSnapToDefaultButton != pOptionData->bSnapToDefaultButton)
1592 {
1593 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1594 pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton;
1595 }
1596
1597 /* Set mouse trails setting */
1598 if (pOptionData->uOrigMouseTrails != pOptionData->uMouseTrails)
1599 {
1600 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1601 pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails;
1602 }
1603
1604 /* Hide pointer while typing */
1605 if (pOptionData->bOrigMouseVanish != pOptionData->bMouseVanish)
1606 {
1607 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bMouseVanish), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1608 pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish;
1609 }
1610
1611 /* Show pointer with Ctrl-Key */
1612 if (pOptionData->bOrigMouseSonar != pOptionData->bMouseSonar)
1613 {
1614 SystemParametersInfo(SPI_SETMOUSESONAR, 0, IntToPtr(pOptionData->bMouseSonar), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1615 pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar;
1616 }
1617 return TRUE;
1618 }
1619 else if (lppsn->hdr.code == PSN_RESET)
1620 {
1621 /* Set the original mouse speed */
1622 SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulOrigMouseSpeed), 0);
1623 SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->OrigMouseAccel, 0);
1624 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bOrigSnapToDefaultButton, 0, 0);
1625 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uOrigMouseTrails, 0, 0);
1626 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bOrigMouseVanish), 0);
1627 SystemParametersInfo(SPI_SETMOUSESONAR, 0,IntToPtr(pOptionData->bOrigMouseSonar), 0);
1628 }
1629 break;
1630
1631 case WM_HSCROLL:
1632 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED))
1633 {
1634 switch (LOWORD(wParam))
1635 {
1636 case TB_LINEUP:
1637 case TB_LINEDOWN:
1638 case TB_PAGEUP:
1639 case TB_PAGEDOWN:
1640 case TB_TOP:
1641 case TB_BOTTOM:
1642 case TB_ENDTRACK:
1643 pOptionData->ulMouseSpeed = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_MOUSE_SPEED, TBM_GETPOS, 0, 0);
1644 SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulMouseSpeed), SPIF_SENDCHANGE);
1645 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1646 break;
1647 #if 0
1648 case TB_THUMBTRACK:
1649 pOptionData->ulMouseSpeed = (ULONG)HIWORD(wParam) + 1;
1650 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSpeed, SPIF_SENDCHANGE);
1651 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1652 break;
1653 #endif
1654 }
1655 }
1656 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL))
1657 {
1658 switch (LOWORD(wParam))
1659 {
1660 case TB_LINEUP:
1661 case TB_LINEDOWN:
1662 case TB_PAGEUP:
1663 case TB_PAGEDOWN:
1664 case TB_TOP:
1665 case TB_BOTTOM:
1666 case TB_ENDTRACK:
1667 pOptionData->uMouseTrails = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_POINTER_TRAIL, TBM_GETPOS, 0, 0) + 2;
1668 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE);
1669 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1670 break;
1671
1672 case TB_THUMBTRACK:
1673 pOptionData->uMouseTrails = (ULONG)HIWORD(wParam) + 2;
1674 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE);
1675 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1676 break;
1677 }
1678 }
1679 break;
1680 }
1681
1682 return FALSE;
1683 }
1684
1685
1686 static VOID
1687 ShowDialogWheelControls(HWND hwndDlg, UINT uWheelScrollLines, BOOL bInit)
1688 {
1689 HWND hDlgCtrl;
1690
1691 if (uWheelScrollLines != WHEEL_PAGESCROLL)
1692 {
1693 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1694 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1695
1696 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1697 EnableWindow(hDlgCtrl, TRUE);
1698
1699 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1700 EnableWindow(hDlgCtrl, TRUE);
1701
1702 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1703 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1704 }
1705 else
1706 {
1707 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1708 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1709
1710 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1711 EnableWindow(hDlgCtrl, FALSE);
1712
1713 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1714 EnableWindow(hDlgCtrl, FALSE);
1715
1716 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1717 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1718
1719 /* Set the default scroll lines value */
1720 if (bInit == TRUE)
1721 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, DEFAULT_WHEEL_SCROLL_LINES, FALSE);
1722 }
1723 }
1724
1725
1726 static INT_PTR CALLBACK
1727 WheelProc(IN HWND hwndDlg,
1728 IN UINT uMsg,
1729 IN WPARAM wParam,
1730 IN LPARAM lParam)
1731 {
1732 LPPSHNOTIFY lppsn;
1733 PWHEEL_DATA pWheelData;
1734
1735 pWheelData = (PWHEEL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1736
1737 switch (uMsg)
1738 {
1739 case WM_INITDIALOG:
1740 pWheelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WHEEL_DATA));
1741 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pWheelData);
1742
1743 /* Get wheel scroll lines */
1744 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pWheelData->uWheelScrollLines, 0);
1745
1746 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, TRUE);
1747 SendDlgItemMessage(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES, UDM_SETRANGE, 0, MAKELONG((short)100, (short)0));
1748 if (pWheelData->uWheelScrollLines != WHEEL_PAGESCROLL)
1749 {
1750 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, pWheelData->uWheelScrollLines, FALSE);
1751 }
1752 return TRUE;
1753
1754 case WM_DESTROY:
1755 HeapFree(GetProcessHeap(), 0, pWheelData);
1756 break;
1757
1758 case WM_COMMAND:
1759 switch (LOWORD(wParam))
1760 {
1761 case IDC_RADIO_WHEEL_SCROLL_LINES:
1762 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1763 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1764 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1765 break;
1766
1767 case IDC_RADIO_WHEEL_SCROLL_PAGE:
1768 pWheelData->uWheelScrollLines = WHEEL_PAGESCROLL;
1769 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1770 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1771 break;
1772
1773 case IDC_EDIT_WHEEL_SCROLL_LINES:
1774 if (pWheelData && HIWORD(wParam) == EN_CHANGE)
1775 {
1776 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1777 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1778 }
1779 break;
1780 }
1781 break;
1782
1783 case WM_NOTIFY:
1784 lppsn = (LPPSHNOTIFY)lParam;
1785 if (lppsn->hdr.code == PSN_APPLY)
1786 {
1787 SystemParametersInfo(SPI_SETWHEELSCROLLLINES, pWheelData->uWheelScrollLines,
1788 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1789 return TRUE;
1790 }
1791 break;
1792 }
1793
1794 return FALSE;
1795 }
1796
1797 static const struct
1798 {
1799 WORD idDlg;
1800 DLGPROC DlgProc;
1801 UINT uiReplaceWith;
1802 } PropPages[] =
1803 {
1804 { IDD_PAGE_BUTTON, ButtonProc, CPLPAGE_MOUSE_BUTTONS },
1805 { IDD_PAGE_POINTER, PointerProc, 0 },
1806 { IDD_PAGE_OPTION, OptionProc, CPLPAGE_MOUSE_PTRMOTION },
1807 { IDD_PAGE_WHEEL, WheelProc, CPLPAGE_MOUSE_WHEEL },
1808 { IDD_HARDWARE, MouseHardwareProc, 0 },
1809 };
1810
1811 LONG APIENTRY
1812 MouseApplet(HWND hwnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
1813 {
1814 HPROPSHEETPAGE hpsp[MAX_CPL_PAGES];
1815 PROPSHEETHEADER psh;
1816 HPSXA hpsxa;
1817 TCHAR Caption[256];
1818 UINT i;
1819 LONG ret;
1820
1821 UNREFERENCED_PARAMETER(lParam1);
1822 UNREFERENCED_PARAMETER(lParam2);
1823 UNREFERENCED_PARAMETER(uMsg);
1824 UNREFERENCED_PARAMETER(hwnd);
1825
1826 LoadString(hApplet, IDS_CPLNAME_1, Caption, sizeof(Caption) / sizeof(TCHAR));
1827
1828 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
1829 psh.dwSize = sizeof(PROPSHEETHEADER);
1830 psh.dwFlags = PSH_PROPTITLE;
1831 psh.hwndParent = hwnd;
1832 psh.hInstance = hApplet;
1833 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_1));
1834 psh.pszCaption = Caption;
1835 psh.nStartPage = 0;
1836 psh.phpage = hpsp;
1837
1838 /* Load additional pages provided by shell extensions */
1839 hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Mouse"), MAX_CPL_PAGES - psh.nPages);
1840
1841 for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++)
1842 {
1843 /* Override the background page if requested by a shell extension */
1844 if (PropPages[i].uiReplaceWith != 0 && hpsxa != NULL &&
1845 SHReplaceFromPropSheetExtArray(hpsxa, PropPages[i].uiReplaceWith, PropSheetAddPage, (LPARAM)&psh) != 0)
1846 {
1847 /* The shell extension added one or more pages to replace a page.
1848 Don't create the built-in page anymore! */
1849 continue;
1850 }
1851
1852 InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc);
1853 }
1854
1855 if (hpsxa != NULL)
1856 SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh);
1857
1858 ret = (LONG)(PropertySheet(&psh) != -1);
1859
1860 if (hpsxa != NULL)
1861 SHDestroyPropSheetExtArray(hpsxa);
1862
1863 return ret;
1864 }
1865
1866 /* EOF */