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