- Fix a bug in EnumerateCursorSchemes that caused the selection of the wrong cursor...
[reactos.git] / reactos / dll / cpl / main / mouse.c
1 /*
2 * ReactOS
3 * Copyright (C) 2004, 2007 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS Main Control Panel
22 * FILE: lib/cpl/main/mouse.c
23 * PURPOSE: Mouse Control Panel
24 * PROGRAMMER: Eric Kohl
25 * Johannes Anderwald
26 */
27
28 //TODO:
29 //detect slider changes - for apply stuff
30 // cursor icon shows - may need overriden items
31 // implement Pointer-APPLY
32 // implement Pointer-Browser
33 // add missing icons
34 // Options- pointer precision
35
36 #define WINVER 0x0501
37
38 #include <windows.h>
39 #include <winuser.h>
40 #include <devguid.h>
41 #include <commctrl.h>
42 #include <cpl.h>
43 #include <tchar.h>
44 #include <math.h>
45 #include <limits.h>
46
47 #include <stdio.h>
48
49 #include "main.h"
50 #include "resource.h"
51
52 #define DEFAULT_DOUBLE_CLICK_SPEED 500
53 #define DEFAULT_CLICK_LOCK_TIME 2200
54 #define DEFAULT_MOUSE_SENSITIVITY 16
55 #define DEFAULT_MOUSE_THRESHOLD1 6
56 #define DEFAULT_MOUSE_THRESHOLD2 10
57 #define MIN_DOUBLE_CLICK_SPEED 200
58 #define MAX_DOUBLE_CLICK_SPEED 900
59 #define DEFAULT_WHEEL_SCROLL_LINES 3
60
61
62 typedef struct _BUTTON_DATA
63 {
64 ULONG g_SwapMouseButtons;
65 ULONG g_OrigSwapMouseButtons;
66 ULONG g_DoubleClickSpeed; // = DEFAULT_DOUBLE_CLICK_SPEED;
67 ULONG g_OrigDoubleClickSpeed;
68 BOOL g_ClickLockEnabled; // = 0;
69 DWORD g_ClickLockTime; // = DEFAULT_CLICK_LOCK_TIME;
70
71 HICON hButtonLeft;
72 HICON hButtonRight;
73
74 HICON hIcon1;
75 HICON hIcon2;
76 BOOL bClicked;
77 } BUTTON_DATA, *PBUTTON_DATA;
78
79
80 typedef struct _POINTER_DATA
81 {
82 BOOL bDropShadow;
83 BOOL bOrigDropShadow;
84
85 } POINTER_DATA, *PPOINTER_DATA;
86
87
88 typedef struct _OPTION_DATA
89 {
90 ULONG ulMouseSensitivity;
91 ULONG ulOrigMouseSensitivity;
92
93 ULONG ulMouseSpeed; // = 1;
94 ULONG ulMouseThreshold1; // = DEFAULT_MOUSE_THRESHOLD1;
95 ULONG ulMouseThreshold2; // = DEFAULT_MOUSE_THRESHOLD2;
96
97 ULONG ulSnapToDefaultButton;
98 ULONG ulMouseTrails;
99 ULONG ulShowPointer;
100 ULONG ulHidePointer;
101 } OPTION_DATA, *POPTION_DATA;
102
103
104 typedef struct _WHEEL_DATA
105 {
106 UINT uWheelScrollLines;
107 } WHEEL_DATA, *PWHEEL_DATA;
108
109
110 typedef struct _CURSOR_DATA
111 {
112 UINT uStringId;
113 LPWSTR uDefaultCursorId;
114 HCURSOR hCursor;
115 TCHAR szCursorName[MAX_PATH];
116 TCHAR szCursorPath[MAX_PATH];
117 } CURSOR_DATA, *PCURSOR_DATA;
118
119
120 CURSOR_DATA g_CursorData[] =
121 {{IDS_ARROW, IDC_ARROW, 0, _T(""), _T("")},
122 {IDS_HELP, IDC_HELP, 0, _T(""), _T("")},
123 {IDS_APPSTARTING, IDC_APPSTARTING, 0, _T(""), _T("")},
124 {IDS_WAIT, IDC_WAIT, 0, _T(""), _T("")},
125 {IDS_CROSSHAIR, IDC_CROSS, 0, _T(""), _T("")},
126 {IDS_IBEAM, IDC_IBEAM, 0, _T(""), _T("")},
127 {IDS_NWPEN, 0/*IDC_NWPEN*/, 0, _T(""), _T("")}, /* FIXME */
128 {IDS_NO, IDC_NO, 0, _T(""), _T("")},
129 {IDS_SIZENS, IDC_SIZENS, 0, _T(""), _T("")},
130 {IDS_SIZEWE, IDC_SIZEWE, 0, _T(""), _T("")},
131 {IDS_SIZENWSE, IDC_SIZENWSE, 0, _T(""), _T("")},
132 {IDS_SIZENESW, IDC_SIZENESW, 0, _T(""), _T("")},
133 {IDS_SIZEALL, IDC_SIZEALL, 0, _T(""), _T("")},
134 {IDS_UPARROW, IDC_UPARROW, 0, _T(""), _T("")},
135 {IDS_HAND, IDC_HAND, 0, _T(""), _T("")}};
136
137
138 TCHAR g_szNewScheme[MAX_PATH];
139
140 #if 0
141 static VOID
142 DebugMsg(LPTSTR fmt, ...)
143 {
144 TCHAR szBuffer[2048];
145 va_list marker;
146
147 va_start(marker, fmt);
148 _vstprintf(szBuffer, fmt, marker);
149 va_end(marker);
150
151 MessageBox(NULL, szBuffer, _T("Debug message"), MB_OK);
152 }
153 #endif
154
155
156 /* Property page dialog callback */
157 static INT_PTR CALLBACK
158 MouseHardwareProc(IN HWND hwndDlg,
159 IN UINT uMsg,
160 IN WPARAM wParam,
161 IN LPARAM lParam)
162 {
163 GUID Guids[1];
164 Guids[0] = GUID_DEVCLASS_MOUSE;
165
166 UNREFERENCED_PARAMETER(lParam);
167 UNREFERENCED_PARAMETER(wParam);
168
169 switch(uMsg)
170 {
171 case WM_INITDIALOG:
172 /* create the hardware page */
173 DeviceCreateHardwarePageEx(hwndDlg,
174 Guids,
175 sizeof(Guids) / sizeof(Guids[0]),
176 HWPD_STANDARDLIST);
177 break;
178 }
179
180 return FALSE;
181 }
182
183
184 static INT_PTR CALLBACK
185 ClickLockProc(IN HWND hwndDlg,
186 IN UINT uMsg,
187 IN WPARAM wParam,
188 IN LPARAM lParam)
189 {
190 HWND hDlgCtrl;
191 int pos;
192
193 PBUTTON_DATA pButtonData;
194
195 pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
196
197 switch(uMsg)
198 {
199 case WM_INITDIALOG:
200 pButtonData = (PBUTTON_DATA)lParam;
201 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData);
202
203 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK);
204 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10));
205 pos = (pButtonData->g_ClickLockTime - 200) / 200;
206 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
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 }
216 else if (LOWORD(wParam) == IDCANCEL)
217 {
218 EndDialog(hwndDlg, FALSE);
219 }
220 break;
221 }
222
223 return FALSE;
224 }
225
226
227 static INT_PTR CALLBACK
228 ButtonProc(IN HWND hwndDlg,
229 IN UINT uMsg,
230 IN WPARAM wParam,
231 IN LPARAM lParam)
232 {
233 HWND hDlgCtrl;
234 LRESULT lResult;
235 LPPSHNOTIFY lppsn;
236
237 PBUTTON_DATA pButtonData;
238
239 pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
240
241 switch (uMsg)
242 {
243 case WM_INITDIALOG:
244 pButtonData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BUTTON_DATA));
245 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData);
246
247 pButtonData->g_SwapMouseButtons = GetSystemMetrics(SM_SWAPBUTTON);
248 pButtonData->g_OrigSwapMouseButtons = pButtonData->g_SwapMouseButtons;
249 pButtonData->g_DoubleClickSpeed = GetDoubleClickTime();
250 pButtonData->g_OrigDoubleClickSpeed = pButtonData->g_DoubleClickSpeed;
251
252 /* Click lock time */
253 SystemParametersInfo(SPI_GETMOUSECLICKLOCK, 0, &pButtonData->g_ClickLockEnabled, 0);
254 SystemParametersInfo(SPI_GETMOUSECLICKLOCKTIME, 0, &pButtonData->g_ClickLockTime, 0);
255
256 /* Load mouse button icons */
257 pButtonData->hButtonLeft = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_LEFT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
258 pButtonData->hButtonRight = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_RIGHT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
259
260 /* Load folder icons */
261 pButtonData->hIcon1 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_CLOSED), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
262 pButtonData->hIcon2 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_OPEN), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
263
264 if (pButtonData->g_SwapMouseButtons)
265 {
266 SendDlgItemMessage(hwndDlg, IDC_SWAP_MOUSE_BUTTONS, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
267 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight);
268 }
269 else
270 {
271 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft);
272 }
273
274 if (pButtonData->g_ClickLockEnabled)
275 {
276 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_CLICK_LOCK);
277 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
278 }
279 else
280 {
281 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK);
282 EnableWindow(hDlgCtrl, FALSE);
283 }
284
285 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED);
286 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 14));
287 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, 14 - ((pButtonData->g_DoubleClickSpeed - 200) / 50));
288
289
290 SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hIcon1);
291 pButtonData->bClicked = TRUE;
292 return TRUE;
293
294 case WM_DESTROY:
295 DestroyIcon(pButtonData->hButtonLeft);
296 DestroyIcon(pButtonData->hButtonRight);
297 DestroyIcon(pButtonData->hIcon1);
298 DestroyIcon(pButtonData->hIcon2);
299 HeapFree(GetProcessHeap(), 0, pButtonData);
300 break;
301
302 case WM_COMMAND:
303 switch(LOWORD(wParam))
304 {
305 case IDC_SWAP_MOUSE_BUTTONS:
306 lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
307 if (lResult == BST_CHECKED)
308 {
309 pButtonData->g_SwapMouseButtons = FALSE;
310 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
311 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft);
312 }
313 else if (lResult == BST_UNCHECKED)
314 {
315 pButtonData->g_SwapMouseButtons = TRUE;
316 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
317 SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight);
318 }
319 SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_SwapMouseButtons, NULL, SPIF_SENDCHANGE);
320 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
321 break;
322
323 case IDC_CHECK_CLICK_LOCK:
324 lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
325 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK);
326 if (lResult == BST_CHECKED)
327 {
328 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
329 pButtonData->g_ClickLockEnabled = FALSE;
330 EnableWindow(hDlgCtrl, FALSE);
331 }
332 else if (lResult == BST_UNCHECKED)
333 {
334 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
335 EnableWindow(hDlgCtrl, TRUE);
336 pButtonData->g_ClickLockEnabled = TRUE;
337 }
338 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
339 break;
340
341 case IDC_BUTTON_CLICK_LOCK:
342 DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CLICK_LOCK), hwndDlg, ClickLockProc, (LPARAM)pButtonData);
343 break;
344
345 case IDC_IMAGE_DOUBLE_CLICK_SPEED:
346 if (HIWORD(wParam) == STN_DBLCLK)
347 {
348 pButtonData->bClicked = !pButtonData->bClicked;
349 SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON,
350 (LPARAM)(pButtonData->bClicked ? pButtonData->hIcon1 : pButtonData->hIcon2));
351 }
352 break;
353 }
354 break;
355
356 case WM_NOTIFY:
357 lppsn = (LPPSHNOTIFY) lParam;
358 if (lppsn->hdr.code == PSN_APPLY)
359 {
360 #if (WINVER >= 0x0500)
361 SystemParametersInfo(SPI_SETMOUSECLICKLOCK, pButtonData->g_ClickLockEnabled, NULL, SPIF_SENDCHANGE);
362 if (pButtonData->g_ClickLockEnabled)
363 SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, pButtonData->g_ClickLockTime, NULL, SPIF_SENDCHANGE);
364 #endif
365 SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
366 }
367 else if (lppsn->hdr.code == PSN_RESET)
368 {
369 /* Reset swap mouse button setting */
370 SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_OrigSwapMouseButtons, NULL, SPIF_SENDCHANGE);
371
372 /* Reset double click speed setting */
373 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_OrigDoubleClickSpeed, NULL, SPIF_SENDCHANGE);
374 SetDoubleClickTime(pButtonData->g_OrigDoubleClickSpeed);
375 }
376 return TRUE;
377
378 case WM_HSCROLL:
379 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED))
380 {
381 switch (LOWORD(wParam))
382 {
383 case TB_LINEUP:
384 case TB_LINEDOWN:
385 case TB_PAGEUP:
386 case TB_PAGEDOWN:
387 case TB_TOP:
388 case TB_BOTTOM:
389 case TB_ENDTRACK:
390 lResult = SendDlgItemMessage(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED, TBM_GETPOS, 0, 0);
391 pButtonData->g_DoubleClickSpeed = (14 - (INT)lResult) * 50 + 200;
392 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE);
393 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
394 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
395 break;
396
397 case TB_THUMBTRACK:
398 pButtonData->g_DoubleClickSpeed = (14 - (INT)HIWORD(wParam)) * 50 + 200;
399 // SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE);
400 SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
401 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
402 break;
403 }
404 }
405 break;
406 }
407
408 return FALSE;
409 }
410
411
412 #if 0
413 static BOOL
414 ReadActiveCursorScheme(VOID)
415 {
416 HKEY hCuKey;
417 HKEY hCuCursorKey;
418 DWORD dwIndex;
419 TCHAR szValueName[MAX_PATH];
420 DWORD dwValueName;
421 TCHAR szValueData[2000];
422 DWORD dwValueData;
423 LONG dwResult;
424
425 if (RegOpenCurrentUser(KEY_READ, &hCuKey) != ERROR_SUCCESS)
426 return FALSE;
427
428 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors"), 0, KEY_READ, &hCuCursorKey) != ERROR_SUCCESS)
429 {
430 RegCloseKey(hCuKey);
431 return FALSE;
432 }
433
434 memset(g_szArrow, 0x0, sizeof(g_szArrow));
435 memset(g_szHelp, 0x0, sizeof(g_szHelp));
436 memset(g_szAppStarting, 0x0, sizeof(g_szAppStarting));
437 memset(g_szWait, 0x0, sizeof(g_szWait));
438 memset(g_szCrosshair, 0x0, sizeof(g_szCrosshair));
439 memset(g_szIBeam, 0x0, sizeof(g_szIBeam));
440 memset(g_szNWPen, 0x0, sizeof(g_szNWPen));
441 memset(g_szNo, 0x0, sizeof(g_szNo));
442 memset(g_szSizeNS, 0x0, sizeof(g_szSizeNS));
443 memset(g_szSizeWE, 0x0, sizeof(g_szSizeWE));
444 memset(g_szSizeNWSE, 0x0, sizeof(g_szSizeNWSE));
445 memset(g_szSizeNESW, 0x0, sizeof(g_szSizeNESW));
446 memset(g_szSizeAll, 0x0, sizeof(g_szSizeAll));
447 memset(g_szUpArrow, 0x0, sizeof(g_szUpArrow));
448 memset(g_szHand, 0x0, sizeof(g_szHand));
449
450 dwIndex = 0;
451 for (;;)
452 {
453 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
454 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
455 dwResult = RegEnumValue(hCuCursorKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (LPBYTE)szValueData, &dwValueData);
456 if (dwResult == ERROR_NO_MORE_ITEMS)
457 break;
458
459 if (_tcsicmp(_T("Arrow"), szValueName))
460 _tcsncpy(g_szArrow, szValueData, MAX_PATH);
461 else if (_tcsicmp(_T("Help"), szValueName))
462 _tcsncpy(g_szHelp, szValueData, MAX_PATH);
463 else if (_tcsicmp(_T("AppStarting"), szValueName))
464 _tcsncpy(g_szAppStarting, szValueData, MAX_PATH);
465 else if (_tcsicmp(_T("Wait"), szValueName))
466 _tcsncpy(g_szWait, szValueData, MAX_PATH);
467 else if (_tcsicmp(_T("Crosshair"), szValueName))
468 _tcsncpy(g_szCrosshair, szValueData, MAX_PATH);
469 else if (_tcsicmp(_T("IBeam"), szValueName))
470 _tcsncpy(g_szIBeam, szValueData, MAX_PATH);
471 else if (_tcsicmp(_T("NWPen"), szValueName))
472 _tcsncpy(g_szNWPen, szValueData, MAX_PATH);
473 else if (_tcscmp(_T("No"), szValueName))
474 _tcsncpy(g_szNo, szValueData, MAX_PATH);
475 else if (_tcsicmp(_T("SizeNS"), szValueName))
476 _tcsncpy(g_szSizeNS, szValueData, MAX_PATH);
477 else if (_tcsicmp(_T("SizeWE"), szValueName))
478 _tcsncpy(g_szSizeWE, szValueData, MAX_PATH);
479 else if (_tcsicmp(_T("SizeNWSE"), szValueName))
480 _tcsncpy(g_szSizeNWSE, szValueData, MAX_PATH);
481 else if (_tcsicmp(_T("SizeNESW"), szValueName))
482 _tcsncpy(g_szSizeNESW, szValueData, MAX_PATH);
483 else if (_tcsicmp(_T("SizeAll"), szValueName))
484 _tcsncpy(g_szSizeAll, szValueData, MAX_PATH);
485 else if (_tcsicmp(_T("UpArrow"), szValueName))
486 _tcsncpy(g_szUpArrow, szValueData, MAX_PATH);
487 else if (_tcsicmp(_T("Hand"), szValueName))
488 _tcsncpy(g_szHand, szValueData, MAX_PATH);
489
490 dwIndex++;
491 }
492
493 RegCloseKey(hCuCursorKey);
494 RegCloseKey(hCuKey);
495
496 return TRUE;
497 }
498 #endif
499
500
501 static BOOL
502 EnumerateCursorSchemes(HWND hwndDlg)
503 {
504 HKEY hCuKey;
505 HKEY hCuCursorKey;
506 DWORD dwIndex;
507 TCHAR szValueName[MAX_PATH];
508 DWORD dwValueName;
509 TCHAR szSystemScheme[MAX_PATH];
510 TCHAR szValueData[2000];
511 DWORD dwValueData;
512 LONG dwResult;
513 HWND hDlgCtrl;
514 LRESULT lResult;
515 BOOL ProcessedHKLM = FALSE;
516 TCHAR szCurrentScheme[MAX_PATH];
517 DWORD dwCurrentScheme;
518 INT nSchemeIndex;
519 INT i, nCount;
520 LPTSTR p;
521
522 if (RegOpenCurrentUser(KEY_READ, &hCuKey) != ERROR_SUCCESS)
523 return FALSE;
524
525 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ, &hCuCursorKey) != ERROR_SUCCESS)
526 {
527 RegCloseKey(hCuKey);
528 return FALSE;
529 }
530
531 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
532 SendMessage(hDlgCtrl, CB_RESETCONTENT, 0, 0);
533 dwIndex = 0;
534
535 for (;;)
536 {
537 dwValueName = sizeof(szValueName) / sizeof(TCHAR);
538 dwValueData = sizeof(szValueData) / sizeof(TCHAR);
539 dwResult = RegEnumValue(hCuCursorKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (LPBYTE)szValueData, &dwValueData);
540
541 if (dwResult == ERROR_NO_MORE_ITEMS)
542 {
543 if (!ProcessedHKLM)
544 {
545 RegCloseKey(hCuCursorKey);
546 dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
547 _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes"),
548 0, KEY_READ, &hCuCursorKey);
549 if (dwResult == ERROR_SUCCESS)
550 {
551 dwIndex = 0;
552 ProcessedHKLM = TRUE;
553 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
554 continue;
555 }
556 }
557 break;
558 }
559
560 if (_tcslen(szValueData) > 0)
561 {
562 TCHAR * copy = _tcsdup(szValueData);
563 if (ProcessedHKLM)
564 {
565 _tcscat(szValueName, TEXT(" "));
566 _tcscat(szValueName, szSystemScheme);
567 }
568 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName);
569 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)copy);
570 }
571
572 dwIndex++;
573 }
574
575 RegCloseKey(hCuCursorKey);
576 RegCloseKey(hCuKey);
577
578 /* Add the "(none)" entry */
579 LoadString(hApplet, IDS_NONE, szSystemScheme, MAX_PATH);
580 lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szSystemScheme);
581 SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)NULL);
582
583
584 /* Get the name of the current cursor scheme */
585 szCurrentScheme[0] = 0;
586 if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors"), 0, KEY_READ, &hCuCursorKey) == ERROR_SUCCESS)
587 {
588 dwCurrentScheme = sizeof(szCurrentScheme) / sizeof(TCHAR);
589 if (RegQueryValueEx(hCuCursorKey, NULL, NULL, NULL, (LPBYTE)szCurrentScheme, &dwCurrentScheme))
590 szCurrentScheme[0] = 0;
591 RegCloseKey(hCuCursorKey);
592 }
593
594 /* Search for the matching entry in the cursor scheme list */
595 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
596 nSchemeIndex = -1;
597 nCount = (INT)SendMessage(hDlgCtrl, CB_GETCOUNT, 0, 0);
598 for (i = 0; i < nCount; i++)
599 {
600 SendMessage(hDlgCtrl, CB_GETLBTEXT, i, (LPARAM)szValueName);
601
602 p = _tcsstr(szValueName, szSystemScheme);
603 if (p)
604 {
605 p -= 1;
606 *p = 0;
607 }
608
609 // DebugMsg(_T("szCurrentScheme: \"%s\"\nszValueName: \"%s\""), szCurrentScheme, szValueName);
610
611 if (_tcscmp(szValueName, szCurrentScheme) == 0)
612 {
613 nSchemeIndex = (INT)i;
614 break;
615 }
616 }
617
618 /* Select the matching entry */
619 if (nSchemeIndex != -1)
620 SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)nSchemeIndex, (LPARAM)0);
621 else
622 {
623 SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
624 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME);
625 EnableWindow(hDlgCtrl, FALSE);
626 }
627
628 return TRUE;
629 }
630
631
632 static VOID
633 RefreshCursorList(HWND hwndDlg, BOOL bInit)
634 {
635 INT index;
636 INT i;
637 INT nSel;
638
639 nSel = bInit ? 0 : SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0);
640
641 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_RESETCONTENT, 0, 0);
642 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
643 {
644 LoadString(hApplet, index, g_CursorData[i].szCursorName, MAX_PATH);
645 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_ADDSTRING, 0, (LPARAM)i);
646 }
647
648 SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_SETCURSEL, nSel, 0);
649 SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR,
650 (LPARAM)g_CursorData[nSel].hCursor);
651 }
652
653
654 static BOOL
655 DeleteUserCursorScheme(TCHAR * szScheme)
656 {
657 HKEY hCuKey;
658 HKEY hCuCursorKey;
659 LONG Result;
660
661 if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS)
662 return FALSE;
663
664 if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS)
665 {
666 RegCloseKey(hCuKey);
667 return FALSE;
668 }
669
670 Result = RegDeleteValue(hCuCursorKey, szScheme);
671
672 RegCloseKey(hCuCursorKey);
673 RegCloseKey(hCuKey);
674
675 return (Result == ERROR_SUCCESS);
676 }
677
678
679 static INT_PTR CALLBACK
680 SaveSchemeProc(IN HWND hwndDlg,
681 IN UINT uMsg,
682 IN WPARAM wParam,
683 IN LPARAM lParam)
684 {
685 HWND hDlgCtrl;
686 UNREFERENCED_PARAMETER(lParam);
687
688 switch(uMsg)
689 {
690 case WM_COMMAND:
691 if (LOWORD(wParam) == IDOK)
692 {
693 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_SCHEME_NAME);
694 SendMessage(hDlgCtrl, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)g_szNewScheme);
695 EndDialog(hwndDlg, TRUE);
696 }
697 else if (LOWORD(wParam) == IDCANCEL)
698 {
699 EndDialog(hwndDlg, FALSE);
700 }
701 break;
702 }
703
704 return FALSE;
705 }
706
707
708 static BOOL
709 BrowseCursor(TCHAR * szFileName, HWND hwndDlg)
710 {
711 //FIXME load text resources from string
712 OPENFILENAME ofn;
713 static TCHAR szFilter[] = _T("Cursors\0*.ani;*.cur\0Animated Cursors\0*.ani\0Static Cursors\0*.cur\0All Files\0*.*\0\0");
714
715 ZeroMemory(&ofn, sizeof(OPENFILENAME));
716
717 ofn.lStructSize = sizeof(OPENFILENAME);
718 ofn.hwndOwner = hwndDlg;
719 ofn.lpstrFilter = szFilter;
720 ofn.nFilterIndex = 1;
721 ofn.lpstrFile = szFileName;
722 ofn.nMaxFile = MAX_PATH;
723 ofn.lpstrInitialDir = _T("%WINDIR%\\Cursors");
724 ofn.lpstrTitle = _T("Browse");
725 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
726
727 if (GetOpenFileName(&ofn))
728 return TRUE;
729 else
730 return FALSE;
731 }
732
733
734 static VOID
735 LoadCurrentCursorScheme(LPTSTR lpName, BOOL bSystem)
736 {
737 UINT index, i;
738
739 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
740 {
741 if (g_CursorData[i].hCursor != NULL)
742 {
743 DestroyCursor(g_CursorData[i].hCursor);
744 g_CursorData[i].hCursor = 0;
745 }
746 g_CursorData[i].szCursorPath[0] = 0;
747 }
748
749 if (lpName == NULL)
750 {
751 // for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
752 // {
753 // g_CursorData[i].hCursor = LoadCursor(NULL, g_CursorData[i].uDefaultCursorId);
754 // }
755 }
756 else
757 {
758 LPTSTR pStart = lpName;
759 LPTSTR pEnd = pStart;
760 INT nLength;
761
762 i = 0;
763 while (pEnd)
764 {
765 pEnd = _tcschr(pStart, _T(','));
766 if (pEnd)
767 nLength = ((INT_PTR)pEnd - (INT_PTR)pStart) / sizeof(TCHAR);
768 else
769 nLength = _tcslen(pStart);
770
771 _tcsncpy(g_CursorData[i].szCursorPath, pStart, nLength);
772 g_CursorData[i].szCursorPath[nLength] = 0;
773
774 pStart = pStart + (nLength + 1);
775 i++;
776 }
777
778 }
779
780 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
781 {
782 if (g_CursorData[i].szCursorPath[0] == 0)
783 g_CursorData[i].hCursor = LoadCursor(NULL, g_CursorData[i].uDefaultCursorId);
784 else
785 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
786 IMAGE_CURSOR, 0, 0,
787 LR_LOADFROMFILE | LR_DEFAULTSIZE);
788 }
789 }
790
791
792 static VOID
793 ReloadCurrentCursorScheme(VOID)
794 {
795 UINT index, i;
796
797 for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++)
798 {
799 if (g_CursorData[i].hCursor != NULL)
800 DestroyCursor(g_CursorData[i].hCursor);
801
802 if (g_CursorData[i].szCursorPath[0] == 0)
803 g_CursorData[i].hCursor = LoadCursor(NULL, g_CursorData[i].uDefaultCursorId);
804 else
805 g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath,
806 IMAGE_CURSOR, 0, 0,
807 LR_LOADFROMFILE | LR_DEFAULTSIZE);
808 }
809 }
810
811
812 static VOID
813 OnDrawItem(UINT idCtl,
814 LPDRAWITEMSTRUCT lpdis)
815 {
816 RECT rc;
817
818 if (lpdis->itemState & ODS_SELECTED)
819 {
820 FillRect(lpdis->hDC,
821 &lpdis->rcItem,
822 (HBRUSH)(COLOR_HIGHLIGHT + 1));
823 SetBkColor(lpdis->hDC,
824 GetSysColor(COLOR_HIGHLIGHT));
825 SetTextColor(lpdis->hDC,
826 GetSysColor(COLOR_HIGHLIGHTTEXT));
827 }
828 else
829 {
830 FillRect(lpdis->hDC,
831 &lpdis->rcItem,
832 (HBRUSH)(COLOR_WINDOW + 1));
833 SetBkColor(lpdis->hDC,
834 GetSysColor(COLOR_WINDOW));
835 SetTextColor(lpdis->hDC,
836 GetSysColor(COLOR_WINDOWTEXT));
837 }
838
839 if (lpdis->itemID != -1)
840 {
841 CopyRect(&rc, &lpdis->rcItem);
842 rc.left += 5;
843 DrawText(lpdis->hDC,
844 g_CursorData[lpdis->itemData].szCursorName,
845 -1,
846 &rc,
847 DT_SINGLELINE | DT_VCENTER | DT_LEFT);
848
849 if (g_CursorData[lpdis->itemData].hCursor != NULL)
850 {
851 DrawIcon(lpdis->hDC,
852 lpdis->rcItem.right - 32 - 4,
853 lpdis->rcItem.top + 2,
854 g_CursorData[lpdis->itemData].hCursor);
855 }
856 }
857
858 if (lpdis->itemState & ODS_FOCUS)
859 {
860 CopyRect(&rc, &lpdis->rcItem);
861 InflateRect(&rc, -1, -1);
862 DrawFocusRect(lpdis->hDC, &rc);
863 }
864 }
865
866
867 static INT_PTR CALLBACK
868 PointerProc(IN HWND hwndDlg,
869 IN UINT uMsg,
870 IN WPARAM wParam,
871 IN LPARAM lParam)
872 {
873 LPPSHNOTIFY lppsn;
874 TCHAR buffer[MAX_PATH];
875 TCHAR szSystemScheme[MAX_PATH];
876 HWND hDlgCtrl;
877 LRESULT lResult;
878
879 PPOINTER_DATA pPointerData;
880
881 pPointerData = (PPOINTER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
882
883 switch(uMsg)
884 {
885 case WM_INITDIALOG:
886 pPointerData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(POINTER_DATA));
887 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pPointerData);
888
889 EnumerateCursorSchemes(hwndDlg);
890 LoadCurrentCursorScheme(NULL, FALSE);
891 RefreshCursorList(hwndDlg, TRUE);
892
893 /* Get drop shadow setting */
894 if (!SystemParametersInfo(SPI_GETDROPSHADOW, 0, &pPointerData->bDropShadow, 0))
895 pPointerData->bDropShadow = FALSE;
896
897 pPointerData->bOrigDropShadow = pPointerData->bDropShadow;
898
899 if (pPointerData->bDropShadow)
900 {
901 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_DROP_SHADOW);
902 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
903 }
904
905 if ((INT)wParam == IDC_LISTBOX_CURSOR)
906 return TRUE;
907 else
908 return FALSE;
909
910 case WM_MEASUREITEM:
911 ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = 32 + 4;
912 break;
913
914 case WM_DRAWITEM:
915 if (wParam == IDC_LISTBOX_CURSOR)
916 OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
917 return TRUE;
918
919 case WM_DESTROY:
920 HeapFree(GetProcessHeap(), 0, pPointerData);
921 break;
922
923 case WM_NOTIFY:
924 lppsn = (LPPSHNOTIFY) lParam;
925 if (lppsn->hdr.code == PSN_APPLY)
926 {
927 #if (WINVER >= 0x0500)
928 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bDropShadow, SPIF_SENDCHANGE);
929 #endif
930 // SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
931 return TRUE;
932 }
933 else if (lppsn->hdr.code == PSN_RESET)
934 {
935 #if (WINVER >= 0x0500)
936 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bOrigDropShadow, SPIF_SENDCHANGE);
937 #endif
938 }
939 break;
940
941 case WM_COMMAND:
942 switch (LOWORD(wParam))
943 {
944 case IDC_COMBO_CURSOR_SCHEME:
945 if (HIWORD(wParam) == CBN_SELENDOK)
946 {
947 BOOL bEnable;
948 LPTSTR lpName;
949
950 wParam = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0);
951 if(wParam == CB_ERR)
952 break;
953
954 SendMessage((HWND)lParam, CB_GETLBTEXT, wParam, (LPARAM)buffer);
955 LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH);
956 if(_tcsstr(buffer, szSystemScheme) || wParam == 0) //avoid the default scheme can be deleted
957 bEnable = FALSE;
958 else
959 bEnable = TRUE;
960
961 /* delete button */
962 hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME);
963 EnableWindow(hDlgCtrl, bEnable);
964
965 lpName = (LPTSTR)SendMessage((HWND)lParam, CB_GETITEMDATA, wParam, 0);
966 LoadCurrentCursorScheme(lpName, !bEnable);
967 RefreshCursorList(hwndDlg, FALSE);
968 }
969 break;
970
971 case IDC_LISTBOX_CURSOR:
972 if (HIWORD(wParam) == LBN_SELCHANGE)
973 {
974 UINT uSel, uIndex;
975 uSel = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
976 uIndex = (UINT)SendMessage((HWND)lParam, LB_GETITEMDATA, (WPARAM)uSel, 0);
977 SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR,
978 (LPARAM)g_CursorData[uIndex].hCursor);
979 }
980 break;
981
982 case IDC_BUTTON_SAVEAS_SCHEME:
983 if (DialogBox(hApplet, MAKEINTRESOURCE(IDD_CURSOR_SCHEME_SAVEAS), hwndDlg, SaveSchemeProc))
984 {
985 /* FIXME: save the cursor scheme */
986 }
987 break;
988
989 case IDC_BUTTON_USE_DEFAULT_CURSOR:
990 hDlgCtrl = GetDlgItem(hwndDlg, IDC_LISTBOX_CURSOR);
991 lResult = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
992 if (lResult != CB_ERR)
993 {
994 UINT uIndex;
995
996 /* FIXME */
997 uIndex = (UINT)SendMessage(hDlgCtrl, LB_GETITEMDATA, (WPARAM)lResult, 0);
998
999 /* Clean the path of the currently selected cursor */
1000 memset(g_CursorData[uIndex].szCursorPath, 0x0, MAX_PATH * sizeof(TCHAR));
1001
1002 ReloadCurrentCursorScheme();
1003 RefreshCursorList(hwndDlg, FALSE);
1004 }
1005 break;
1006
1007 case IDC_BUTTON_BROWSE_CURSOR:
1008 memset(buffer, 0x0, sizeof(buffer));
1009 hDlgCtrl = GetDlgItem(hwndDlg, IDC_LISTBOX_CURSOR);
1010 lResult = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
1011 if (lResult == CB_ERR)
1012 MessageBox(hwndDlg, _T("CB_ERR"), _T(""),MB_ICONERROR);
1013 if (BrowseCursor(buffer, hwndDlg))
1014 {
1015 UINT uIndex;
1016
1017 /* FIXME */
1018 uIndex = (UINT)SendMessage(hDlgCtrl, LB_GETITEMDATA, (WPARAM)lResult, 0);
1019
1020 /* Store the new cursor file path */
1021 _tcsncpy(g_CursorData[uIndex].szCursorPath, buffer, MAX_PATH);
1022
1023 ReloadCurrentCursorScheme();
1024 RefreshCursorList(hwndDlg, FALSE);
1025 }
1026 break;
1027
1028 case IDC_BUTTON_DELETE_SCHEME:
1029 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME);
1030 wParam = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0);
1031 if(wParam == CB_ERR)
1032 break;
1033 SendMessage(hDlgCtrl, CB_GETLBTEXT, wParam, (LPARAM)buffer);
1034 if (DeleteUserCursorScheme(buffer))
1035 {
1036 SendMessage(hDlgCtrl, CB_DELETESTRING, wParam, 0);
1037 SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
1038 }
1039 break;
1040
1041 case IDC_CHECK_DROP_SHADOW:
1042 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_DROP_SHADOW))
1043 {
1044 pPointerData->bDropShadow = FALSE;
1045 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1046 #if (WINVER >= 0x0500)
1047 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bDropShadow, SPIF_SENDCHANGE);
1048 #endif
1049 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1050 }
1051 else
1052 {
1053 pPointerData->bDropShadow = TRUE;
1054 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1055 #if (WINVER >= 0x0500)
1056 SystemParametersInfo(SPI_SETDROPSHADOW, 0, (PVOID)pPointerData->bDropShadow, SPIF_SENDCHANGE);
1057 #endif
1058 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1059 }
1060 break;
1061 }
1062 break;
1063 }
1064
1065 return FALSE;
1066 }
1067
1068
1069 static BOOL
1070 InitializeMouse(POPTION_DATA pOptionData)
1071 {
1072 //FIXME
1073 //pointer precision
1074 // SPI_GETMOUSE?
1075
1076 /* Get mouse sensitivity */
1077 if (!SystemParametersInfo(SPI_GETMOUSESPEED, 0, &pOptionData->ulMouseSensitivity, 0))
1078 pOptionData->ulMouseSensitivity = DEFAULT_MOUSE_SENSITIVITY;
1079 pOptionData->ulOrigMouseSensitivity = pOptionData->ulMouseSensitivity;
1080
1081 pOptionData->ulMouseSpeed = 1;
1082 pOptionData->ulMouseThreshold1 = DEFAULT_MOUSE_THRESHOLD1;
1083 pOptionData->ulMouseThreshold2 = DEFAULT_MOUSE_THRESHOLD2;
1084
1085 /* snap to default button */
1086 if (SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &pOptionData->ulSnapToDefaultButton, 0))
1087 pOptionData->ulSnapToDefaultButton = 0;
1088
1089 /* mouse trails */
1090 if (!SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &pOptionData->ulMouseTrails, 0))
1091 pOptionData->ulMouseTrails = 0;
1092
1093 /* hide pointer while typing */
1094 if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &pOptionData->ulHidePointer, 0))
1095 pOptionData->ulHidePointer = 0;
1096
1097 /* show pointer with Ctrl-Key */
1098 if (!SystemParametersInfo(SPI_GETMOUSESONAR, 0, &pOptionData->ulShowPointer, 0))
1099 pOptionData->ulShowPointer = 0;
1100
1101 return TRUE;
1102 }
1103
1104
1105 static INT_PTR CALLBACK
1106 OptionProc(IN HWND hwndDlg,
1107 IN UINT uMsg,
1108 IN WPARAM wParam,
1109 IN LPARAM lParam)
1110 {
1111 HWND hDlgCtrl;
1112 LPPSHNOTIFY lppsn;
1113 LRESULT lResult;
1114 POPTION_DATA pOptionData;
1115
1116 pOptionData = (POPTION_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1117
1118 switch(uMsg)
1119 {
1120 case WM_INITDIALOG:
1121 pOptionData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPTION_DATA));
1122 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pOptionData);
1123
1124 InitializeMouse(pOptionData);
1125
1126 /* set mouse sensitivity */
1127 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY);
1128 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 19));
1129 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->ulMouseSensitivity - 1);
1130
1131 if (pOptionData->ulMouseSpeed)
1132 {
1133 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_POINTER_PRECISION);
1134 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1135 }
1136
1137 if (pOptionData->ulSnapToDefaultButton)
1138 {
1139 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SNAP_TO);
1140 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1141 }
1142
1143 /* set mouse trail */
1144 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1145 SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 5));
1146 if (pOptionData->ulMouseTrails < 2)
1147 EnableWindow(hDlgCtrl, FALSE);
1148 else
1149 SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->ulMouseTrails - 2);
1150
1151 if (pOptionData->ulShowPointer)
1152 {
1153 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SHOW_POINTER);
1154 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1155 }
1156
1157 if (pOptionData->ulHidePointer)
1158 {
1159 hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_HIDE_POINTER);
1160 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1161 }
1162 break;
1163
1164 case WM_DESTROY:
1165 HeapFree(GetProcessHeap(), 0, pOptionData);
1166 break;
1167
1168 case WM_COMMAND:
1169 switch(LOWORD(wParam))
1170 {
1171 case IDC_CHECK_POINTER_PRECISION:
1172 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_PRECISION))
1173 {
1174 pOptionData->ulMouseSpeed = 0;
1175 pOptionData->ulMouseThreshold1 = 0;
1176 pOptionData->ulMouseThreshold2 = 0;
1177 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1178 }
1179 else
1180 {
1181 pOptionData->ulMouseSpeed = 1;
1182 pOptionData->ulMouseThreshold1 = 6;
1183 pOptionData->ulMouseThreshold2 = 10;
1184 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1185 }
1186 break;
1187
1188 case IDC_CHECK_SNAP_TO:
1189 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SNAP_TO))
1190 {
1191 pOptionData->ulSnapToDefaultButton = 0;
1192 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1193 }
1194 else
1195 {
1196 pOptionData->ulSnapToDefaultButton = 1;
1197 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1198 }
1199 break;
1200
1201 case IDC_CHECK_POINTER_TRAIL:
1202 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1203 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL))
1204 {
1205 pOptionData->ulMouseTrails = 0;
1206 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1207 EnableWindow(hDlgCtrl, FALSE);
1208 }
1209 else
1210 {
1211 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1212 EnableWindow(hDlgCtrl, TRUE);
1213 pOptionData->ulMouseTrails = (ULONG)SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2;
1214 }
1215 break;
1216
1217 case IDC_CHECK_SHOW_POINTER:
1218 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHOW_POINTER))
1219 {
1220 pOptionData->ulShowPointer = 0;
1221 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1222 }
1223 else
1224 {
1225 pOptionData->ulShowPointer = 1;
1226 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1227 }
1228 break;
1229
1230 case IDC_CHECK_HIDE_POINTER:
1231 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_HIDE_POINTER))
1232 {
1233 pOptionData->ulHidePointer = 0;
1234 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1235 }
1236 else
1237 {
1238 pOptionData->ulHidePointer = 1;
1239 SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1240 }
1241 break;
1242 }
1243 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1244 break;
1245
1246 case WM_NOTIFY:
1247 lppsn = (LPPSHNOTIFY)lParam;
1248 if (lppsn->hdr.code == PSN_APPLY)
1249 {
1250 /* set snap to default button */
1251 SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, pOptionData->ulSnapToDefaultButton, 0, SPIF_SENDCHANGE);
1252
1253 #if 0
1254 /* set mouse trails */
1255 if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL))
1256 {
1257 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL);
1258 lResult = SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2;
1259 }
1260 else
1261 {
1262 lResult = 0;
1263 }
1264
1265 SystemParametersInfo(SPI_SETMOUSETRAILS, (UINT) lResult, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1266 #endif
1267
1268 //FIXME
1269 //pointer precision
1270 //SPI_SETMOUSE?
1271
1272 /* calc pos and set mouse sensitivity */
1273 hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY);
1274 lResult = SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 1;
1275 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSensitivity, SPIF_SENDCHANGE);
1276
1277 /* hide pointer while typing */
1278 SystemParametersInfo(SPI_SETMOUSEVANISH, 0, (PVOID)pOptionData->ulHidePointer, SPIF_SENDCHANGE);
1279
1280 /* show pointer with Ctrl-Key */
1281 SystemParametersInfo(SPI_SETMOUSESONAR, 0, (PVOID)pOptionData->ulShowPointer, SPIF_SENDCHANGE);
1282
1283 SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
1284 return TRUE;
1285 }
1286 else if (lppsn->hdr.code == PSN_RESET)
1287 {
1288 /* Set the original mouse speed */
1289 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulOrigMouseSensitivity, SPIF_SENDCHANGE);
1290 }
1291 break;
1292
1293 case WM_HSCROLL:
1294 if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY))
1295 {
1296 switch (LOWORD(wParam))
1297 {
1298 case TB_LINEUP:
1299 case TB_LINEDOWN:
1300 case TB_PAGEUP:
1301 case TB_PAGEDOWN:
1302 case TB_TOP:
1303 case TB_BOTTOM:
1304 case TB_ENDTRACK:
1305 pOptionData->ulMouseSensitivity = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_MOUSE_SENSITIVITY, TBM_GETPOS, 0, 0) + 1;
1306 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSensitivity, SPIF_SENDCHANGE);
1307 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1308 break;
1309 #if 0
1310 case TB_THUMBTRACK:
1311 pOptionData->ulMouseSensitivity = (ULONG)HIWORD(wParam) + 1;
1312 SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSensitivity, SPIF_SENDCHANGE);
1313 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1314 break;
1315 #endif
1316 }
1317 }
1318 else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL))
1319 {
1320 switch (LOWORD(wParam))
1321 {
1322 case TB_LINEUP:
1323 case TB_LINEDOWN:
1324 case TB_PAGEUP:
1325 case TB_PAGEDOWN:
1326 case TB_TOP:
1327 case TB_BOTTOM:
1328 case TB_ENDTRACK:
1329 pOptionData->ulMouseTrails = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_POINTER_TRAIL, TBM_GETPOS, 0, 0) + 2;
1330 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->ulMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1331 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1332 break;
1333
1334 case TB_THUMBTRACK:
1335 pOptionData->ulMouseTrails = (ULONG)HIWORD(wParam) + 2;
1336 SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->ulMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1337 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1338 break;
1339 }
1340 }
1341 break;
1342 }
1343
1344 return FALSE;
1345 }
1346
1347
1348 static VOID
1349 ShowDialogWheelControls(HWND hwndDlg, UINT uWheelScrollLines, BOOL bInit)
1350 {
1351 HWND hDlgCtrl;
1352
1353 if (uWheelScrollLines != WHEEL_PAGESCROLL)
1354 {
1355 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1356 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1357
1358 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1359 EnableWindow(hDlgCtrl, TRUE);
1360
1361 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1362 EnableWindow(hDlgCtrl, TRUE);
1363
1364 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1365 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1366 }
1367 else
1368 {
1369 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES);
1370 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0);
1371
1372 hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES);
1373 EnableWindow(hDlgCtrl, FALSE);
1374
1375 hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES);
1376 EnableWindow(hDlgCtrl, FALSE);
1377
1378 hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE);
1379 SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
1380
1381 /* Set the default scroll lines value */
1382 if (bInit == TRUE)
1383 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, DEFAULT_WHEEL_SCROLL_LINES, FALSE);
1384 }
1385 }
1386
1387
1388 static INT_PTR CALLBACK
1389 WheelProc(IN HWND hwndDlg,
1390 IN UINT uMsg,
1391 IN WPARAM wParam,
1392 IN LPARAM lParam)
1393 {
1394 LPPSHNOTIFY lppsn;
1395 PWHEEL_DATA pWheelData;
1396
1397 pWheelData = (PWHEEL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
1398
1399 switch (uMsg)
1400 {
1401 case WM_INITDIALOG:
1402 pWheelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WHEEL_DATA));
1403 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pWheelData);
1404
1405 /* Get wheel scroll lines */
1406 if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pWheelData->uWheelScrollLines, 0))
1407 {
1408 pWheelData->uWheelScrollLines = DEFAULT_WHEEL_SCROLL_LINES;
1409 }
1410
1411 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, TRUE);
1412 SendDlgItemMessage(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES, UDM_SETRANGE, 0, MAKELONG((short)100, (short)0));
1413 if (pWheelData->uWheelScrollLines != WHEEL_PAGESCROLL)
1414 {
1415 SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, pWheelData->uWheelScrollLines, FALSE);
1416 }
1417 return TRUE;
1418
1419 case WM_DESTROY:
1420 HeapFree(GetProcessHeap(), 0, pWheelData);
1421 break;
1422
1423 case WM_COMMAND:
1424 switch (LOWORD(wParam))
1425 {
1426 case IDC_RADIO_WHEEL_SCROLL_LINES:
1427 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1428 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1429 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1430 break;
1431
1432 case IDC_RADIO_WHEEL_SCROLL_PAGE:
1433 pWheelData->uWheelScrollLines = WHEEL_PAGESCROLL;
1434 ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE);
1435 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1436 break;
1437
1438 case IDC_EDIT_WHEEL_SCROLL_LINES:
1439 if (pWheelData && HIWORD(wParam) == EN_CHANGE)
1440 {
1441 pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE);
1442 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1443 }
1444 break;
1445 }
1446 break;
1447
1448 case WM_NOTIFY:
1449 lppsn = (LPPSHNOTIFY)lParam;
1450 if (lppsn->hdr.code == PSN_APPLY)
1451 {
1452 SystemParametersInfo(SPI_SETWHEELSCROLLLINES, pWheelData->uWheelScrollLines,
1453 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1454 return TRUE;
1455 }
1456 break;
1457 }
1458
1459 return FALSE;
1460 }
1461
1462
1463 LONG APIENTRY
1464 MouseApplet(HWND hwnd, UINT uMsg, LONG lParam1, LONG lParam2)
1465 {
1466 PROPSHEETPAGE psp[5];
1467 PROPSHEETHEADER psh;
1468 TCHAR Caption[256];
1469
1470 UNREFERENCED_PARAMETER(lParam1);
1471 UNREFERENCED_PARAMETER(lParam2);
1472 UNREFERENCED_PARAMETER(uMsg);
1473 UNREFERENCED_PARAMETER(hwnd);
1474
1475 LoadString(hApplet, IDS_CPLNAME_1, Caption, sizeof(Caption) / sizeof(TCHAR));
1476
1477 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
1478 psh.dwSize = sizeof(PROPSHEETHEADER);
1479 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE;
1480 psh.hwndParent = NULL;
1481 psh.hInstance = hApplet;
1482 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_1));
1483 psh.pszCaption = Caption;
1484 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
1485 psh.nStartPage = 0;
1486 psh.ppsp = psp;
1487
1488 InitPropSheetPage(&psp[0], IDD_PAGE_BUTTON, ButtonProc);
1489 InitPropSheetPage(&psp[1], IDD_PAGE_POINTER, PointerProc);
1490 InitPropSheetPage(&psp[2], IDD_PAGE_OPTION, OptionProc);
1491 InitPropSheetPage(&psp[3], IDD_PAGE_WHEEL, WheelProc);
1492 InitPropSheetPage(&psp[4], IDD_HARDWARE, MouseHardwareProc);
1493 return (LONG)(PropertySheet(&psh) != -1);
1494 }
1495
1496 /* EOF */