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