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