/* * ReactOS * Copyright (C) 2004, 2007 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * PROJECT: ReactOS Main Control Panel * FILE: dll/cpl/main/mouse.c * PURPOSE: Mouse Control Panel * PROGRAMMER: Eric Kohl * Johannes Anderwald */ // TODO: // Add missing icons #include "main.h" #include #include #include #define DEFAULT_DOUBLE_CLICK_SPEED 500 #define DEFAULT_CLICK_LOCK_TIME 2200 #define DEFAULT_MOUSE_SPEED 10 #define DEFAULT_MOUSE_ACCELERATION 1 #define DEFAULT_MOUSE_THRESHOLD1 6 #define DEFAULT_MOUSE_THRESHOLD2 10 #define MIN_DOUBLE_CLICK_SPEED 200 #define MAX_DOUBLE_CLICK_SPEED 900 #define DEFAULT_WHEEL_SCROLL_LINES 3 typedef struct _BUTTON_DATA { ULONG g_SwapMouseButtons; ULONG g_OrigSwapMouseButtons; ULONG g_DoubleClickSpeed; // = DEFAULT_DOUBLE_CLICK_SPEED; ULONG g_OrigDoubleClickSpeed; BOOL g_ClickLockEnabled; // = 0; DWORD g_ClickLockTime; // = DEFAULT_CLICK_LOCK_TIME; HICON hButtonLeft; HICON hButtonRight; HICON hIcon1; HICON hIcon2; BOOL bClicked; } BUTTON_DATA, *PBUTTON_DATA; typedef struct _POINTER_DATA { BOOL bCursorShadow; BOOL bOrigCursorShadow; INT cxCursor; INT cyCursor; } POINTER_DATA, *PPOINTER_DATA; typedef struct _MOUSE_ACCEL { INT nThreshold1; INT nThreshold2; INT nAcceleration; } MOUSE_ACCEL; typedef struct _OPTION_DATA { ULONG ulMouseSpeed; ULONG ulOrigMouseSpeed; MOUSE_ACCEL MouseAccel; MOUSE_ACCEL OrigMouseAccel; BOOL bSnapToDefaultButton; BOOL bOrigSnapToDefaultButton; UINT uMouseTrails; UINT uOrigMouseTrails; BOOL bMouseVanish; BOOL bOrigMouseVanish; BOOL bMouseSonar; BOOL bOrigMouseSonar; } OPTION_DATA, *POPTION_DATA; typedef struct _WHEEL_DATA { UINT uWheelScrollLines; } WHEEL_DATA, *PWHEEL_DATA; typedef struct _CURSOR_DATA { UINT uStringId; UINT uDefaultCursorId; LPTSTR lpValueName; HCURSOR hCursor; TCHAR szCursorName[MAX_PATH]; TCHAR szCursorPath[MAX_PATH]; } CURSOR_DATA, *PCURSOR_DATA; CURSOR_DATA g_CursorData[] = {{IDS_ARROW, 100/*OCR_NORMAL*/, _T("Arrow"), 0, _T(""), _T("")}, {IDS_HELP, 112/*OCR_HELP*/, _T("Help"), 0, _T(""), _T("")}, {IDS_APPSTARTING, 111/*OCR_APPSTARTING*/, _T("AppStarting"), 0, _T(""), _T("")}, {IDS_WAIT, 102/*OCR_WAIT*/, _T("Wait"), 0, _T(""), _T("")}, {IDS_CROSSHAIR, 103/*OCR_CROSS*/, _T("Crosshair"), 0, _T(""), _T("")}, {IDS_IBEAM, 101/*OCR_IBEAM*/, _T("IBeam"), 0, _T(""), _T("")}, {IDS_NWPEN, 113/*OCR_NWPEN*/, _T("NWPen"), 0, _T(""), _T("")}, {IDS_NO, 110/*OCR_NO*/, _T("No"), 0, _T(""), _T("")}, {IDS_SIZENS, 108/*OCR_SIZENS*/, _T("SizeNS"), 0, _T(""), _T("")}, {IDS_SIZEWE, 107/*OCR_SIZEWE*/, _T("SizeWE"), 0, _T(""), _T("")}, {IDS_SIZENWSE, 105/*OCR_SIZENWSE*/, _T("SizeNWSE"), 0, _T(""), _T("")}, {IDS_SIZENESW, 106/*OCR_SIZENESW*/, _T("SizeNESW"), 0, _T(""), _T("")}, {IDS_SIZEALL, 109/*OCR_SIZEALL*/, _T("SizeAll"), 0, _T(""), _T("")}, {IDS_UPARROW, 104/*OCR_UP*/, _T("UpArrow"), 0, _T(""), _T("")}, {IDS_HAND, 114/*OCR_HAND*/, _T("Hand"), 0, _T(""), _T("")}}; #if 0 static VOID DebugMsg(LPTSTR fmt, ...) { TCHAR szBuffer[2048]; va_list marker; va_start(marker, fmt); _vstprintf(szBuffer, fmt, marker); va_end(marker); MessageBox(NULL, szBuffer, _T("Debug message"), MB_OK); } #endif /* Property page dialog callback */ static INT_PTR CALLBACK MouseHardwareProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { GUID Guids[1]; Guids[0] = GUID_DEVCLASS_MOUSE; UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(wParam); switch(uMsg) { case WM_INITDIALOG: /* create the hardware page */ DeviceCreateHardwarePageEx(hwndDlg, Guids, sizeof(Guids) / sizeof(Guids[0]), HWPD_STANDARDLIST); break; } return FALSE; } static INT_PTR CALLBACK ClickLockProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { HWND hDlgCtrl; int pos; static HICON hIcon; PBUTTON_DATA pButtonData; pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); switch(uMsg) { case WM_INITDIALOG: pButtonData = (PBUTTON_DATA)lParam; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData); hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK); SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10)); pos = (pButtonData->g_ClickLockTime - 200) / 200; SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos); hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_LOOK_KEY), IMAGE_ICON, 16, 16, 0); SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK) { hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_CLICK_LOCK); pButtonData->g_ClickLockTime = (DWORD) (SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) * 200) + 200; EndDialog(hwndDlg, TRUE); if (hIcon) DestroyIcon(hIcon); } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hwndDlg, FALSE); if (hIcon) DestroyIcon(hIcon); } break; } return FALSE; } static INT_PTR CALLBACK ButtonProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { HWND hDlgCtrl; LRESULT lResult; LPPSHNOTIFY lppsn; PBUTTON_DATA pButtonData; pButtonData = (PBUTTON_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: pButtonData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BUTTON_DATA)); SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pButtonData); pButtonData->g_SwapMouseButtons = GetSystemMetrics(SM_SWAPBUTTON); pButtonData->g_OrigSwapMouseButtons = pButtonData->g_SwapMouseButtons; pButtonData->g_DoubleClickSpeed = GetDoubleClickTime(); pButtonData->g_OrigDoubleClickSpeed = pButtonData->g_DoubleClickSpeed; /* Click lock time */ SystemParametersInfo(SPI_GETMOUSECLICKLOCK, 0, &pButtonData->g_ClickLockEnabled, 0); SystemParametersInfo(SPI_GETMOUSECLICKLOCKTIME, 0, &pButtonData->g_ClickLockTime, 0); /* Load mouse button icons */ pButtonData->hButtonLeft = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_LEFT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR); pButtonData->hButtonRight = LoadImage(hApplet, MAKEINTRESOURCE(IDI_MOUSE_RIGHT), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR); /* Load folder icons */ pButtonData->hIcon1 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_CLOSED), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR); pButtonData->hIcon2 = LoadImage(hApplet, MAKEINTRESOURCE(IDI_FOLDER_OPEN), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR); if (pButtonData->g_SwapMouseButtons) { SendDlgItemMessage(hwndDlg, IDC_SWAP_MOUSE_BUTTONS, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight); } else { SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft); } if (pButtonData->g_ClickLockEnabled) { hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_CLICK_LOCK); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } else { hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK); EnableWindow(hDlgCtrl, FALSE); } hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED); SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 14)); SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, 14 - ((pButtonData->g_DoubleClickSpeed - 200) / 50)); SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hIcon1); pButtonData->bClicked = TRUE; return TRUE; case WM_DESTROY: DestroyIcon(pButtonData->hButtonLeft); DestroyIcon(pButtonData->hButtonRight); DestroyIcon(pButtonData->hIcon1); DestroyIcon(pButtonData->hIcon2); HeapFree(GetProcessHeap(), 0, pButtonData); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_SWAP_MOUSE_BUTTONS: lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0); if (lResult == BST_CHECKED) { pButtonData->g_SwapMouseButtons = FALSE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonLeft); } else if (lResult == BST_UNCHECKED) { pButtonData->g_SwapMouseButtons = TRUE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); SendDlgItemMessage(hwndDlg, IDC_IMAGE_SWAP_MOUSE, STM_SETIMAGE, IMAGE_ICON, (LPARAM)pButtonData->hButtonRight); } //SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_SwapMouseButtons, NULL, 0); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; case IDC_CHECK_CLICK_LOCK: lResult = SendMessage((HWND)lParam, BM_GETCHECK, (WPARAM)0, (LPARAM)0); hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_CLICK_LOCK); if (lResult == BST_CHECKED) { SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); pButtonData->g_ClickLockEnabled = FALSE; EnableWindow(hDlgCtrl, FALSE); } else if (lResult == BST_UNCHECKED) { SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); pButtonData->g_ClickLockEnabled = TRUE; EnableWindow(hDlgCtrl, TRUE); } PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; case IDC_BUTTON_CLICK_LOCK: DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CLICK_LOCK), hwndDlg, ClickLockProc, (LPARAM)pButtonData); break; case IDC_IMAGE_DOUBLE_CLICK_SPEED: if (HIWORD(wParam) == STN_DBLCLK) { pButtonData->bClicked = !pButtonData->bClicked; SendDlgItemMessage(hwndDlg, IDC_IMAGE_DOUBLE_CLICK_SPEED, STM_SETIMAGE, IMAGE_ICON, (LPARAM)(pButtonData->bClicked ? pButtonData->hIcon1 : pButtonData->hIcon2)); } break; } break; case WM_NOTIFY: lppsn = (LPPSHNOTIFY) lParam; if (lppsn->hdr.code == PSN_APPLY) { if (pButtonData->g_OrigSwapMouseButtons != pButtonData->g_SwapMouseButtons) { pButtonData->g_OrigSwapMouseButtons = pButtonData->g_SwapMouseButtons; SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_OrigSwapMouseButtons, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); } SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); //SetDoubleClickTime(pButtonData->g_DoubleClickSpeed); #if (WINVER >= 0x0500) SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, UlongToPtr(pButtonData->g_ClickLockEnabled), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); if (pButtonData->g_ClickLockEnabled) SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, pButtonData->g_ClickLockTime, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); #endif } else if (lppsn->hdr.code == PSN_RESET) { /* Reset swap mouse button setting */ SystemParametersInfo(SPI_SETMOUSEBUTTONSWAP, pButtonData->g_OrigSwapMouseButtons, NULL, 0); /* Reset double-click speed setting */ SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_OrigDoubleClickSpeed, NULL, 0); //SetDoubleClickTime(pButtonData->g_OrigDoubleClickSpeed); } return TRUE; case WM_HSCROLL: if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED)) { switch (LOWORD(wParam)) { case TB_LINEUP: case TB_LINEDOWN: case TB_PAGEUP: case TB_PAGEDOWN: case TB_TOP: case TB_BOTTOM: case TB_ENDTRACK: lResult = SendDlgItemMessage(hwndDlg, IDC_SLIDER_DOUBLE_CLICK_SPEED, TBM_GETPOS, 0, 0); pButtonData->g_DoubleClickSpeed = (14 - (INT)lResult) * 50 + 200; //SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); SetDoubleClickTime(pButtonData->g_DoubleClickSpeed); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; case TB_THUMBTRACK: pButtonData->g_DoubleClickSpeed = (14 - (INT)HIWORD(wParam)) * 50 + 200; //SystemParametersInfo(SPI_SETDOUBLECLICKTIME, pButtonData->g_DoubleClickSpeed, NULL, 0); SetDoubleClickTime(pButtonData->g_DoubleClickSpeed); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; } } break; } return FALSE; } static VOID CompressPath(LPTSTR lpShortPath, LPTSTR lpPath) { TCHAR szUserProfile[MAX_PATH]; TCHAR szSystemRoot[MAX_PATH]; TCHAR szProgramFiles[MAX_PATH]; DWORD dwUserProfile; DWORD dwSystemRoot; DWORD dwProgramFiles; dwUserProfile = GetEnvironmentVariable(_T("USERPROFILE"), szUserProfile, MAX_PATH); dwSystemRoot = GetEnvironmentVariable(_T("SystemRoot"), szSystemRoot, MAX_PATH); dwProgramFiles = GetEnvironmentVariable(_T("ProgramFiles"), szProgramFiles, MAX_PATH); if (dwUserProfile > 0 && _tcsncmp(lpPath, szUserProfile, dwUserProfile) == 0) { _tcscpy(lpShortPath, _T("%USERPROFILE%")); _tcscat(lpShortPath, &lpPath[dwUserProfile]); } else if (dwSystemRoot > 0 && _tcsncmp(lpPath, szSystemRoot, dwSystemRoot) == 0) { _tcscpy(lpShortPath, _T("%SystemRoot%")); _tcscat(lpShortPath, &lpPath[dwSystemRoot]); } else if (dwProgramFiles > 0 && _tcsncmp(lpPath, szProgramFiles, dwProgramFiles) == 0) { _tcscpy(lpShortPath, _T("%ProgramFiles%")); _tcscat(lpShortPath, &lpPath[dwProgramFiles]); } else { _tcscpy(lpShortPath, lpPath); } } static BOOL EnumerateCursorSchemes(HWND hwndDlg) { HKEY hCursorKey; DWORD dwIndex; TCHAR szValueName[MAX_PATH]; DWORD dwValueName; TCHAR szSystemScheme[MAX_PATH]; TCHAR szValueData[2000]; TCHAR szTempData[2000]; DWORD dwValueData; LONG lError; HWND hDlgCtrl; LRESULT lResult; hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME); SendMessage(hDlgCtrl, CB_RESETCONTENT, 0, 0); /* Read the users cursor schemes */ lError = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_QUERY_VALUE , &hCursorKey); if (lError == ERROR_SUCCESS) { for (dwIndex = 0;; dwIndex++) { dwValueName = sizeof(szValueName) / sizeof(TCHAR); dwValueData = sizeof(szValueData) / sizeof(TCHAR); lError = RegEnumValue(hCursorKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (LPBYTE)szValueData, &dwValueData); if (lError == ERROR_NO_MORE_ITEMS) break; ExpandEnvironmentStrings(szValueData, szTempData, 2000); if (_tcslen(szTempData) > 0) { LPTSTR lpCopy, lpStart; /* Remove quotation marks */ if (szTempData[0] == _T('"')) { lpStart = szTempData + 1; szTempData[_tcslen(szTempData) - 1] = 0; } else { lpStart = szTempData; } lpCopy = _tcsdup(lpStart); lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName); SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)lpCopy); } } RegCloseKey(hCursorKey); } /* Read the system cursor schemes */ lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_QUERY_VALUE , &hCursorKey); if (lError == ERROR_SUCCESS) { LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH); for (dwIndex = 0;; dwIndex++) { dwValueName = sizeof(szValueName) / sizeof(TCHAR); dwValueData = sizeof(szValueData) / sizeof(TCHAR); lError = RegEnumValue(hCursorKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (LPBYTE)szValueData, &dwValueData); if (lError == ERROR_NO_MORE_ITEMS) break; if (_tcslen(szValueData) > 0) { LPTSTR lpCopy, lpStart; /* Remove quotation marks */ if (szValueData[0] == _T('"')) { lpStart = szValueData + 1; szValueData[_tcslen(szValueData) - 1] = 0; } else { lpStart = szValueData; } lpCopy = _tcsdup(lpStart); _tcscat(szValueName, TEXT(" ")); _tcscat(szValueName, szSystemScheme); lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValueName); SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)lpCopy); } } RegCloseKey(hCursorKey); } /* Add the "(none)" entry */ LoadString(hApplet, IDS_NONE, szSystemScheme, MAX_PATH); lResult = SendMessage(hDlgCtrl, CB_ADDSTRING, (WPARAM)0, (LPARAM)szSystemScheme); SendMessage(hDlgCtrl, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)NULL); return TRUE; } static VOID RefreshCursorList(HWND hwndDlg, BOOL bInit) { INT index; INT i; INT nSel; nSel = bInit ? 0 : SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0); if (bInit) { SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_RESETCONTENT, 0, 0); for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { LoadString(hApplet, index, g_CursorData[i].szCursorName, MAX_PATH); SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_ADDSTRING, 0, (LPARAM)i); } SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_SETCURSEL, nSel, 0); } else { InvalidateRect(GetDlgItem(hwndDlg, IDC_LISTBOX_CURSOR), NULL, FALSE); } SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)g_CursorData[nSel].hCursor); EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), (g_CursorData[nSel].szCursorPath[0] != 0)); } static BOOL DeleteUserCursorScheme(HWND hwndDlg) { TCHAR szSchemeName[MAX_PATH]; TCHAR szTitle[128]; TCHAR szRawText[256]; TCHAR szText[256]; HWND hDlgCtrl; HKEY hCuKey; HKEY hCuCursorKey; LONG lResult; INT nSel; hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMBO_CURSOR_SCHEME); nSel = SendMessage(hDlgCtrl, CB_GETCURSEL, 0, 0); if (nSel == CB_ERR) return FALSE; SendMessage(hDlgCtrl, CB_GETLBTEXT, nSel, (LPARAM)szSchemeName); LoadString(hApplet, IDS_REMOVE_TITLE, szTitle, 128); LoadString(hApplet, IDS_REMOVE_TEXT, szRawText, 256); _stprintf(szText, szRawText, szSchemeName); /* Confirm scheme removal */ if (MessageBox(hwndDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO) return TRUE; if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS) return FALSE; if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS) { RegCloseKey(hCuKey); return FALSE; } lResult = RegDeleteValue(hCuCursorKey, szSchemeName); RegCloseKey(hCuCursorKey); RegCloseKey(hCuKey); if (lResult == ERROR_SUCCESS) { SendMessage(hDlgCtrl, CB_DELETESTRING, nSel, 0); SendMessage(hDlgCtrl, CB_SETCURSEL, (WPARAM)0, (LPARAM)0); } return (lResult == ERROR_SUCCESS); } static INT_PTR CALLBACK SaveSchemeProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { LPTSTR pSchemeName; switch (uMsg) { case WM_INITDIALOG: pSchemeName = (LPTSTR)lParam; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSchemeName); SendDlgItemMessage(hwndDlg, IDC_EDIT_SCHEME_NAME, WM_SETTEXT, 0, (LPARAM)pSchemeName); break; case WM_COMMAND: if (LOWORD(wParam) == IDOK) { pSchemeName = (LPTSTR)GetWindowLongPtr(hwndDlg, DWLP_USER); SendDlgItemMessage(hwndDlg, IDC_EDIT_SCHEME_NAME, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)pSchemeName); EndDialog(hwndDlg, TRUE); } else if (LOWORD(wParam) == IDCANCEL) { EndDialog(hwndDlg, FALSE); } break; } return FALSE; } static BOOL SaveCursorScheme(HWND hwndDlg) { TCHAR szSystemScheme[MAX_PATH]; TCHAR szSchemeName[MAX_PATH]; TCHAR szNewSchemeName[MAX_PATH]; TCHAR szTempPath[MAX_PATH]; TCHAR szTitle[128]; TCHAR szText[256]; INT nSel; INT index, i, nLength; LPTSTR lpSchemeData; HKEY hCuKey; HKEY hCuCursorKey; LONG lError = ERROR_SUCCESS; BOOL bSchemeExists; LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH); nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0); if (nSel == CB_ERR) return FALSE; if (nSel == 0) { szSchemeName[0] = 0; szNewSchemeName[0] = 0; } else { SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szNewSchemeName); if (_tcsstr(szNewSchemeName, szSystemScheme)) { szNewSchemeName[_tcslen(szNewSchemeName) - _tcslen(szSystemScheme) - 1] = 0; } } /* Ask for a name for the new cursor scheme */ if (!DialogBoxParam(hApplet, MAKEINTRESOURCE(IDD_CURSOR_SCHEME_SAVEAS), hwndDlg, SaveSchemeProc, (LPARAM)szNewSchemeName)) return TRUE; /* Check all non-system schemes for the new name */ nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCOUNT, 0, 0); if (nSel == CB_ERR) return FALSE; bSchemeExists = FALSE; for (i = 0; i < nSel; i++) { SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, i, (LPARAM)szSchemeName); if (_tcsstr(szSchemeName, szSystemScheme) == NULL) { if (_tcscmp(szSchemeName, szNewSchemeName) == 0) { bSchemeExists = TRUE; break; } } } if (bSchemeExists) { LoadString(hApplet, IDS_OVERWRITE_TITLE, szTitle, 128); LoadString(hApplet, IDS_OVERWRITE_TEXT, szText, 256); /* Confirm scheme overwrite */ if (MessageBox(hwndDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO) return TRUE; } /* Save the cursor scheme */ nLength = 0; for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { if (i > 0) nLength++; nLength += _tcslen(g_CursorData[i].szCursorPath); } nLength++; lpSchemeData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(TCHAR)); if(!lpSchemeData) return FALSE; for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { CompressPath(szTempPath, g_CursorData[i].szCursorPath); if (i > 0) _tcscat(lpSchemeData, _T(",")); _tcscat(lpSchemeData, szTempPath); } if (RegOpenCurrentUser(KEY_READ | KEY_SET_VALUE, &hCuKey) != ERROR_SUCCESS) { HeapFree(GetProcessHeap(), 0, lpSchemeData); return FALSE; } if (RegOpenKeyEx(hCuKey, _T("Control Panel\\Cursors\\Schemes"), 0, KEY_READ | KEY_SET_VALUE, &hCuCursorKey) != ERROR_SUCCESS) { RegCloseKey(hCuKey); HeapFree(GetProcessHeap(), 0, lpSchemeData); return FALSE; } lError = RegSetValueEx(hCuCursorKey, szNewSchemeName, 0, REG_EXPAND_SZ, (LPBYTE)lpSchemeData, (_tcslen(lpSchemeData) + 1) * sizeof(TCHAR)); RegCloseKey(hCuCursorKey); RegCloseKey(hCuKey); /* Add the new scheme to the scheme list and select it */ if (lError == ERROR_SUCCESS) { LPTSTR copy = _tcsdup(lpSchemeData); nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_ADDSTRING, (WPARAM)0, (LPARAM)szNewSchemeName); SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETITEMDATA, (WPARAM)nSel, (LPARAM)copy); SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0); } HeapFree(GetProcessHeap(), 0, lpSchemeData); return (lError == ERROR_SUCCESS); } static BOOL BrowseCursor(HWND hwndDlg) { TCHAR szFileName[MAX_PATH]; TCHAR szFilter[MAX_PATH]; TCHAR szTitle[MAX_PATH]; OPENFILENAME ofn; INT nSel; LoadString(hApplet, IDS_BROWSE_FILTER, szFilter, MAX_PATH); LoadString(hApplet, IDS_BROWSE_TITLE, szTitle, MAX_PATH); memset(szFileName, 0x0, sizeof(szFileName)); nSel = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0); if (nSel == LB_ERR) { MessageBox(hwndDlg, _T("LB_ERR"), _T(""), MB_ICONERROR); return FALSE; } ZeroMemory(&ofn, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwndDlg; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = 1; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrInitialDir = _T("%WINDIR%\\Cursors"); ofn.lpstrTitle = szTitle; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if (!GetOpenFileName(&ofn)) return FALSE; /* Store the new cursor file path */ _tcsncpy(g_CursorData[nSel].szCursorPath, szFileName, MAX_PATH); return TRUE; } static VOID LoadCursorScheme(LPTSTR lpName, BOOL bSystem) { UINT index, i; for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { if (g_CursorData[i].hCursor != NULL) { DestroyCursor(g_CursorData[i].hCursor); g_CursorData[i].hCursor = 0; } g_CursorData[i].szCursorPath[0] = 0; } if (lpName != NULL) { LPTSTR pStart = lpName; LPTSTR pEnd = pStart; INT nLength; i = 0; while (pEnd) { pEnd = _tcschr(pStart, _T(',')); if (pEnd) nLength = ((INT_PTR)pEnd - (INT_PTR)pStart) / sizeof(TCHAR); else nLength = _tcslen(pStart); _tcsncpy(g_CursorData[i].szCursorPath, pStart, nLength); g_CursorData[i].szCursorPath[nLength] = 0; pStart = pStart + (nLength + 1); i++; } } for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { if (g_CursorData[i].szCursorPath[0] == 0) g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); else g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); } } static VOID ReloadCurrentCursorScheme(VOID) { UINT index, i; for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { if (g_CursorData[i].hCursor != NULL) DestroyCursor(g_CursorData[i].hCursor); if (g_CursorData[i].szCursorPath[0] == 0) g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(g_CursorData[i].uDefaultCursorId), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); else g_CursorData[i].hCursor = (HCURSOR)LoadImage(NULL, g_CursorData[i].szCursorPath, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); } } static VOID OnDrawItem(UINT idCtl, LPDRAWITEMSTRUCT lpdis, PPOINTER_DATA pPointerData) { RECT rc; if (lpdis->itemState & ODS_SELECTED) { FillRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1)); SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); } else { FillRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)(COLOR_WINDOW + 1)); SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW)); SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT)); } if (lpdis->itemID != (UINT)-1) { CopyRect(&rc, &lpdis->rcItem); rc.left += 5; DrawText(lpdis->hDC, g_CursorData[lpdis->itemData].szCursorName, -1, &rc, DT_SINGLELINE | DT_VCENTER | DT_LEFT); if (g_CursorData[lpdis->itemData].hCursor != NULL) { DrawIcon(lpdis->hDC, lpdis->rcItem.right - pPointerData->cxCursor - 4, lpdis->rcItem.top + 2, g_CursorData[lpdis->itemData].hCursor); } } if (lpdis->itemState & ODS_FOCUS) { CopyRect(&rc, &lpdis->rcItem); InflateRect(&rc, -1, -1); DrawFocusRect(lpdis->hDC, &rc); } } static VOID LoadNewCursorScheme(HWND hwndDlg) { TCHAR buffer[MAX_PATH]; TCHAR szSystemScheme[MAX_PATH]; HWND hDlgCtrl; BOOL bEnable; LPTSTR lpName; INT nSel; nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0); if (nSel == CB_ERR) return; SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)buffer); LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH); if (_tcsstr(buffer, szSystemScheme) || nSel == 0) // Avoid the default scheme - Can be deleted bEnable = FALSE; else bEnable = TRUE; /* Delete button */ hDlgCtrl = GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME); EnableWindow(hDlgCtrl, bEnable); lpName = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0); LoadCursorScheme(lpName, !bEnable); RefreshCursorList(hwndDlg, FALSE); } static VOID LoadInitialCursorScheme(HWND hwndDlg) { TCHAR szSchemeName[MAX_PATH]; TCHAR szSystemScheme[MAX_PATH]; TCHAR szCursorPath[MAX_PATH]; HKEY hCursorKey; LONG lError; DWORD dwDataSize; DWORD dwSchemeSource = 0; UINT index, i; DWORD dwType; INT nSel; for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { g_CursorData[i].hCursor = 0; g_CursorData[i].szCursorPath[0] = 0; } lError = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors"), 0, KEY_READ | KEY_QUERY_VALUE, &hCursorKey); if (lError != ERROR_SUCCESS) return; dwDataSize = sizeof(DWORD); lError = RegQueryValueEx(hCursorKey, _T("Scheme Source"), NULL, NULL, (LPBYTE)&dwSchemeSource, &dwDataSize); if (dwSchemeSource != 0) { dwDataSize = MAX_PATH * sizeof(TCHAR); lError = RegQueryValueEx(hCursorKey, NULL, NULL, NULL, (LPBYTE)szSchemeName, &dwDataSize); for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { dwDataSize = MAX_PATH * sizeof(TCHAR); lError = RegQueryValueEx(hCursorKey, g_CursorData[i].lpValueName, NULL, &dwType, (LPBYTE)szCursorPath, &dwDataSize); if (lError == ERROR_SUCCESS) { if (dwType == REG_EXPAND_SZ) { ExpandEnvironmentStrings(szCursorPath, g_CursorData[i].szCursorPath, MAX_PATH); } else { _tcscpy(g_CursorData[i].szCursorPath, szCursorPath); } } } } RegCloseKey(hCursorKey); ReloadCurrentCursorScheme(); RefreshCursorList(hwndDlg, TRUE); /* Build the full scheme name */ if (dwSchemeSource == 0) { LoadString(hApplet, IDS_NONE, szSchemeName, MAX_PATH); } else if (dwSchemeSource == 2) { LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH); _tcsncat(szSchemeName, _T(" "), MAX_PATH - _tcslen(szSchemeName) - 1); _tcsncat(szSchemeName, szSystemScheme, MAX_PATH - _tcslen(szSchemeName) - 1); } /* Search and select the current scheme name from the scheme list */ nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_FINDSTRINGEXACT, -1, (LPARAM)szSchemeName); if (nSel != CB_ERR) SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_SETCURSEL, (WPARAM)nSel, (LPARAM)0); /* Enable /disable delete button */ EnableWindow(GetDlgItem(hwndDlg, IDC_BUTTON_DELETE_SCHEME), (dwSchemeSource == 1)); } static BOOL ApplyCursorScheme(HWND hwndDlg) { TCHAR szSchemeName[MAX_PATH]; TCHAR szSystemScheme[MAX_PATH]; TCHAR szTempPath[MAX_PATH]; LPTSTR lpSchemeData; DWORD dwNameLength; DWORD dwSchemeSource; UINT index, i; HKEY hCursorKey; INT nSel; nSel = SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETCURSEL, 0, 0); if (nSel == CB_ERR) return FALSE; lpSchemeData = (LPTSTR)SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETITEMDATA, nSel, 0); if (lpSchemeData == NULL) { /* "None" cursor scheme */ dwSchemeSource = 0; szSchemeName[0] = 0; dwNameLength = 0; } else { SendDlgItemMessage(hwndDlg, IDC_COMBO_CURSOR_SCHEME, CB_GETLBTEXT, nSel, (LPARAM)szSchemeName); LoadString(hApplet, IDS_SYSTEM_SCHEME, szSystemScheme, MAX_PATH); if (_tcsstr(szSchemeName, szSystemScheme)) { /* System scheme */ dwSchemeSource = 2; szSchemeName[_tcslen(szSchemeName) - _tcslen(szSystemScheme) - 1] = 0; } else { /* User scheme */ dwSchemeSource = 1; } dwNameLength = (_tcslen(szSchemeName) + 1) * sizeof(TCHAR); } if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Cursors"), 0, KEY_READ | KEY_SET_VALUE, &hCursorKey) != ERROR_SUCCESS) return FALSE; RegSetValueEx(hCursorKey, NULL, 0, REG_SZ, (LPBYTE)szSchemeName, dwNameLength); RegSetValueEx(hCursorKey, _T("Scheme Source"), 0, REG_DWORD, (LPBYTE)&dwSchemeSource, sizeof(DWORD)); for (index = IDS_ARROW, i = 0; index <= IDS_HAND; index++, i++) { CompressPath(szTempPath, g_CursorData[i].szCursorPath); RegSetValueEx(hCursorKey, g_CursorData[i].lpValueName, 0, REG_EXPAND_SZ, (LPBYTE)szTempPath, (_tcslen(szTempPath) + 1) * sizeof(TCHAR)); } RegCloseKey(hCursorKey); /* Force the system to reload its cursors */ SystemParametersInfo(SPI_SETCURSORS, 0, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); return TRUE; } static INT_PTR CALLBACK PointerProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { PPOINTER_DATA pPointerData; LPPSHNOTIFY lppsn; INT nSel; pPointerData = (PPOINTER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: pPointerData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(POINTER_DATA)); SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pPointerData); pPointerData->cxCursor = GetSystemMetrics(SM_CXCURSOR); pPointerData->cyCursor = GetSystemMetrics(SM_CYCURSOR); EnumerateCursorSchemes(hwndDlg); LoadInitialCursorScheme(hwndDlg); /* Get cursor shadow setting */ SystemParametersInfo(SPI_GETCURSORSHADOW, 0, &pPointerData->bCursorShadow, 0); pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow; if (pPointerData->bCursorShadow) { SendDlgItemMessage(hwndDlg, IDC_CHECK_CURSOR_SHADOW, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } if ((INT)wParam == IDC_LISTBOX_CURSOR) return TRUE; else return FALSE; case WM_MEASUREITEM: ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = GetSystemMetrics(SM_CYCURSOR) + 4; break; case WM_DRAWITEM: if (wParam == IDC_LISTBOX_CURSOR) OnDrawItem((UINT)wParam, (LPDRAWITEMSTRUCT)lParam, pPointerData); return TRUE; case WM_DESTROY: HeapFree(GetProcessHeap(), 0, pPointerData); break; case WM_NOTIFY: lppsn = (LPPSHNOTIFY) lParam; if (lppsn->hdr.code == PSN_APPLY) { ApplyCursorScheme(hwndDlg); //#if (WINVER >= 0x0500) if (pPointerData->bOrigCursorShadow != pPointerData->bCursorShadow) { SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow; } //#endif return TRUE; } else if (lppsn->hdr.code == PSN_RESET) { //#if (WINVER >= 0x0500) SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bOrigCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); //#endif } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_COMBO_CURSOR_SCHEME: if (HIWORD(wParam) == CBN_SELENDOK) { LoadNewCursorScheme(hwndDlg); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; case IDC_LISTBOX_CURSOR: switch (HIWORD(wParam)) { case LBN_SELCHANGE: nSel = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0); if(nSel == LB_ERR) break; SendDlgItemMessage(hwndDlg, IDC_IMAGE_CURRENT_CURSOR, STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)g_CursorData[nSel].hCursor); EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), (g_CursorData[nSel].szCursorPath[0] != 0)); break; case LBN_DBLCLK: if (BrowseCursor(hwndDlg)) { /* Update cursor list and preview */ ReloadCurrentCursorScheme(); RefreshCursorList(hwndDlg, FALSE); /* Enable the "Set Default" button */ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), TRUE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; } break; case IDC_BUTTON_SAVEAS_SCHEME: SaveCursorScheme(hwndDlg); break; case IDC_BUTTON_USE_DEFAULT_CURSOR: nSel = SendDlgItemMessage(hwndDlg, IDC_LISTBOX_CURSOR, LB_GETCURSEL, 0, 0); if (nSel != LB_ERR) { /* Clean the path of the currently selected cursor */ memset(g_CursorData[nSel].szCursorPath, 0x0, MAX_PATH * sizeof(TCHAR)); /* Update cursor list and preview */ ReloadCurrentCursorScheme(); RefreshCursorList(hwndDlg, FALSE); /* Disable the "Set Default" button */ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), FALSE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; case IDC_BUTTON_BROWSE_CURSOR: if (BrowseCursor(hwndDlg)) { /* Update cursor list and preview */ ReloadCurrentCursorScheme(); RefreshCursorList(hwndDlg, FALSE); /* Enable the "Set Default" button */ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_USE_DEFAULT_CURSOR), TRUE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; case IDC_BUTTON_DELETE_SCHEME: DeleteUserCursorScheme(hwndDlg); break; case IDC_CHECK_CURSOR_SHADOW: if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_CURSOR_SHADOW)) { pPointerData->bCursorShadow = FALSE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); //#if (WINVER >= 0x0500) // SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, 0); //#endif // PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } else { pPointerData->bCursorShadow = TRUE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } //#if (WINVER >= 0x0500) //SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); //#endif PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; } break; } return FALSE; } static INT_PTR CALLBACK OptionProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { POPTION_DATA pOptionData; HWND hDlgCtrl; LPPSHNOTIFY lppsn; pOptionData = (POPTION_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); switch(uMsg) { case WM_INITDIALOG: pOptionData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPTION_DATA)); SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pOptionData); /* Get mouse sensitivity */ if (!SystemParametersInfo(SPI_GETMOUSESPEED, 0, &pOptionData->ulMouseSpeed, 0)) pOptionData->ulMouseSpeed = DEFAULT_MOUSE_SPEED; pOptionData->ulOrigMouseSpeed = pOptionData->ulMouseSpeed; if (!SystemParametersInfo(SPI_GETMOUSE, 0, &pOptionData->MouseAccel, 0)) { pOptionData->MouseAccel.nAcceleration = DEFAULT_MOUSE_ACCELERATION; pOptionData->MouseAccel.nThreshold1 = DEFAULT_MOUSE_THRESHOLD1; pOptionData->MouseAccel.nThreshold2 = DEFAULT_MOUSE_THRESHOLD2; } pOptionData->OrigMouseAccel.nAcceleration = pOptionData->MouseAccel.nAcceleration; pOptionData->OrigMouseAccel.nThreshold1 = pOptionData->MouseAccel.nThreshold1; pOptionData->OrigMouseAccel.nThreshold2 = pOptionData->MouseAccel.nThreshold2; /* Snap to default button */ SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &pOptionData->bSnapToDefaultButton, 0); pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton; /* Mouse trails */ SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &pOptionData->uMouseTrails, 0); pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails; /* Hide pointer while typing */ SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &pOptionData->bMouseVanish, 0); pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish; /* Show pointer with Ctrl-Key */ SystemParametersInfo(SPI_GETMOUSESONAR, 0, &pOptionData->bMouseSonar, 0); pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar; /* Set mouse speed */ hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED); SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(1, 20)); SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->ulMouseSpeed); if (pOptionData->MouseAccel.nAcceleration) { hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_POINTER_PRECISION); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } if (pOptionData->bSnapToDefaultButton) { hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SNAP_TO); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } /* Set mouse trail */ hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL); SendMessage(hDlgCtrl, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 5)); if (pOptionData->uMouseTrails < 2) { SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)5); EnableWindow(hDlgCtrl, FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE); } else { SendDlgItemMessage(hwndDlg, IDC_CHECK_POINTER_TRAIL, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); SendMessage(hDlgCtrl, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pOptionData->uMouseTrails - 2); } if (pOptionData->bMouseVanish) { hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_HIDE_POINTER); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } if (pOptionData->bMouseSonar) { hDlgCtrl = GetDlgItem(hwndDlg, IDC_CHECK_SHOW_POINTER); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } break; case WM_DESTROY: HeapFree(GetProcessHeap(), 0, pOptionData); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_CHECK_POINTER_PRECISION: if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_PRECISION)) { pOptionData->MouseAccel.nAcceleration = 0; pOptionData->MouseAccel.nThreshold1 = 0; pOptionData->MouseAccel.nThreshold2 = 0; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); } else { pOptionData->MouseAccel.nAcceleration = 1; pOptionData->MouseAccel.nThreshold1 = 6; pOptionData->MouseAccel.nThreshold2 = 10; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, 0); break; case IDC_CHECK_SNAP_TO: if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SNAP_TO)) { pOptionData->bSnapToDefaultButton = 0; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); } else { pOptionData->bSnapToDefaultButton = 1; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, 0); break; case IDC_CHECK_POINTER_TRAIL: hDlgCtrl = GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL); if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_POINTER_TRAIL)) { SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); EnableWindow(hDlgCtrl, FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), FALSE); pOptionData->uMouseTrails = 0; } else { SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); EnableWindow(hDlgCtrl, TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_SHORT), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_TRAIL_LONG), TRUE); pOptionData->uMouseTrails = (UINT)SendMessage(hDlgCtrl, TBM_GETPOS, 0, 0) + 2; } SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, 0); break; case IDC_CHECK_HIDE_POINTER: if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_HIDE_POINTER)) { pOptionData->bMouseVanish = FALSE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); } else { pOptionData->bMouseVanish = TRUE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bMouseVanish), 0); break; case IDC_CHECK_SHOW_POINTER: if(IsDlgButtonChecked(hwndDlg, IDC_CHECK_SHOW_POINTER)) { pOptionData->bMouseSonar = FALSE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); } else { pOptionData->bMouseSonar = TRUE; SendMessage((HWND)lParam, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); } SystemParametersInfo(SPI_SETMOUSESONAR, 0, IntToPtr(pOptionData->bMouseSonar), 0); break; } PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; case WM_NOTIFY: lppsn = (LPPSHNOTIFY)lParam; if (lppsn->hdr.code == PSN_APPLY) { /* Set mouse speed */ if (pOptionData->ulOrigMouseSpeed != pOptionData->ulMouseSpeed) { SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulMouseSpeed), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); pOptionData->ulOrigMouseSpeed = pOptionData->ulMouseSpeed; } if (pOptionData->OrigMouseAccel.nAcceleration != pOptionData->MouseAccel.nAcceleration) { SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->MouseAccel, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); pOptionData->OrigMouseAccel.nAcceleration = pOptionData->MouseAccel.nAcceleration; pOptionData->OrigMouseAccel.nThreshold1 = pOptionData->MouseAccel.nThreshold1; pOptionData->OrigMouseAccel.nThreshold2 = pOptionData->MouseAccel.nThreshold2; } /* Set snap to default button */ if (pOptionData->bOrigSnapToDefaultButton != pOptionData->bSnapToDefaultButton) { SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bSnapToDefaultButton, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); pOptionData->bOrigSnapToDefaultButton = pOptionData->bSnapToDefaultButton; } /* Set mouse trails setting */ if (pOptionData->uOrigMouseTrails != pOptionData->uMouseTrails) { SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); pOptionData->uOrigMouseTrails = pOptionData->uMouseTrails; } /* Hide pointer while typing */ if (pOptionData->bOrigMouseVanish != pOptionData->bMouseVanish) { SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bMouseVanish), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); pOptionData->bOrigMouseVanish = pOptionData->bMouseVanish; } /* Show pointer with Ctrl-Key */ if (pOptionData->bOrigMouseSonar != pOptionData->bMouseSonar) { SystemParametersInfo(SPI_SETMOUSESONAR, 0, IntToPtr(pOptionData->bMouseSonar), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); pOptionData->bOrigMouseSonar = pOptionData->bMouseSonar; } return TRUE; } else if (lppsn->hdr.code == PSN_RESET) { /* Set the original mouse speed */ SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulOrigMouseSpeed), 0); SystemParametersInfo(SPI_SETMOUSE, 0, &pOptionData->OrigMouseAccel, 0); SystemParametersInfo(SPI_SETSNAPTODEFBUTTON, (UINT)pOptionData->bOrigSnapToDefaultButton, 0, 0); SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uOrigMouseTrails, 0, 0); SystemParametersInfo(SPI_SETMOUSEVANISH, 0, IntToPtr(pOptionData->bOrigMouseVanish), 0); SystemParametersInfo(SPI_SETMOUSESONAR, 0,IntToPtr(pOptionData->bOrigMouseSonar), 0); } break; case WM_HSCROLL: if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_MOUSE_SPEED)) { switch (LOWORD(wParam)) { case TB_LINEUP: case TB_LINEDOWN: case TB_PAGEUP: case TB_PAGEDOWN: case TB_TOP: case TB_BOTTOM: case TB_ENDTRACK: pOptionData->ulMouseSpeed = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_MOUSE_SPEED, TBM_GETPOS, 0, 0); SystemParametersInfo(SPI_SETMOUSESPEED, 0, IntToPtr(pOptionData->ulMouseSpeed), SPIF_SENDCHANGE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; #if 0 case TB_THUMBTRACK: pOptionData->ulMouseSpeed = (ULONG)HIWORD(wParam) + 1; SystemParametersInfo(SPI_SETMOUSESPEED, 0, (PVOID)pOptionData->ulMouseSpeed, SPIF_SENDCHANGE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; #endif } } else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_POINTER_TRAIL)) { switch (LOWORD(wParam)) { case TB_LINEUP: case TB_LINEDOWN: case TB_PAGEUP: case TB_PAGEDOWN: case TB_TOP: case TB_BOTTOM: case TB_ENDTRACK: pOptionData->uMouseTrails = (ULONG)SendDlgItemMessage(hwndDlg, IDC_SLIDER_POINTER_TRAIL, TBM_GETPOS, 0, 0) + 2; SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; case TB_THUMBTRACK: pOptionData->uMouseTrails = (ULONG)HIWORD(wParam) + 2; SystemParametersInfo(SPI_SETMOUSETRAILS, pOptionData->uMouseTrails, 0, SPIF_UPDATEINIFILE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; } } break; } return FALSE; } static VOID ShowDialogWheelControls(HWND hwndDlg, UINT uWheelScrollLines, BOOL bInit) { HWND hDlgCtrl; if (uWheelScrollLines != WHEEL_PAGESCROLL) { hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES); EnableWindow(hDlgCtrl, TRUE); hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES); EnableWindow(hDlgCtrl, TRUE); hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); } else { hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_LINES); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_UNCHECKED, (LPARAM)0); hDlgCtrl = GetDlgItem(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES); EnableWindow(hDlgCtrl, FALSE); hDlgCtrl = GetDlgItem(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES); EnableWindow(hDlgCtrl, FALSE); hDlgCtrl = GetDlgItem(hwndDlg, IDC_RADIO_WHEEL_SCROLL_PAGE); SendMessage(hDlgCtrl, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0); /* Set the default scroll lines value */ if (bInit != FALSE) SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, DEFAULT_WHEEL_SCROLL_LINES, FALSE); } } static INT_PTR CALLBACK WheelProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) { LPPSHNOTIFY lppsn; PWHEEL_DATA pWheelData; pWheelData = (PWHEEL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: pWheelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WHEEL_DATA)); SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pWheelData); /* Get wheel scroll lines */ SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &pWheelData->uWheelScrollLines, 0); ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, TRUE); SendDlgItemMessage(hwndDlg, IDC_UPDOWN_WHEEL_SCROLL_LINES, UDM_SETRANGE, 0, MAKELONG((short)100, (short)0)); if (pWheelData->uWheelScrollLines != WHEEL_PAGESCROLL) { SetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, pWheelData->uWheelScrollLines, FALSE); } return TRUE; case WM_DESTROY: HeapFree(GetProcessHeap(), 0, pWheelData); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_RADIO_WHEEL_SCROLL_LINES: pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE); ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; case IDC_RADIO_WHEEL_SCROLL_PAGE: pWheelData->uWheelScrollLines = WHEEL_PAGESCROLL; ShowDialogWheelControls(hwndDlg, pWheelData->uWheelScrollLines, FALSE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; case IDC_EDIT_WHEEL_SCROLL_LINES: if (pWheelData && HIWORD(wParam) == EN_CHANGE) { pWheelData->uWheelScrollLines = GetDlgItemInt(hwndDlg, IDC_EDIT_WHEEL_SCROLL_LINES, NULL, FALSE); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; } break; case WM_NOTIFY: lppsn = (LPPSHNOTIFY)lParam; if (lppsn->hdr.code == PSN_APPLY) { SystemParametersInfo(SPI_SETWHEELSCROLLLINES, pWheelData->uWheelScrollLines, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); return TRUE; } break; } return FALSE; } static int CALLBACK PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) { // NOTE: This callback is needed to set large icon correctly. HICON hIcon; switch (uMsg) { case PSCB_INITIALIZED: { hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_CPLICON_1)); SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); break; } } return 0; } static const struct { WORD idDlg; DLGPROC DlgProc; UINT uiReplaceWith; } PropPages[] = { { IDD_PAGE_BUTTON, ButtonProc, CPLPAGE_MOUSE_BUTTONS }, { IDD_PAGE_POINTER, PointerProc, 0 }, { IDD_PAGE_OPTION, OptionProc, CPLPAGE_MOUSE_PTRMOTION }, { IDD_PAGE_WHEEL, WheelProc, CPLPAGE_MOUSE_WHEEL }, { IDD_HARDWARE, MouseHardwareProc, 0 }, }; LONG APIENTRY MouseApplet(HWND hwnd, UINT uMsg, LPARAM lParam1, LPARAM lParam2) { HPROPSHEETPAGE hpsp[MAX_CPL_PAGES]; PROPSHEETHEADER psh; HPSXA hpsxa; UINT i; INT nPage = 0; LONG ret; UNREFERENCED_PARAMETER(lParam1); UNREFERENCED_PARAMETER(lParam2); UNREFERENCED_PARAMETER(uMsg); UNREFERENCED_PARAMETER(hwnd); if (uMsg == CPL_STARTWPARMSW && lParam2 != 0) nPage = _wtoi((PWSTR)lParam2); ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPTITLE | PSH_USEICONID | PSH_USECALLBACK; psh.hwndParent = hwnd; psh.hInstance = hApplet; psh.pszIcon = MAKEINTRESOURCEW(IDC_CPLICON_1); psh.pszCaption = MAKEINTRESOURCEW(IDS_CPLNAME_1); psh.nStartPage = 0; psh.phpage = hpsp; psh.pfnCallback = PropSheetProc; /* Load additional pages provided by shell extensions */ hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Mouse"), MAX_CPL_PAGES - psh.nPages); for (i = 0; i != sizeof(PropPages) / sizeof(PropPages[0]); i++) { /* Override the background page if requested by a shell extension */ if (PropPages[i].uiReplaceWith != 0 && hpsxa != NULL && SHReplaceFromPropSheetExtArray(hpsxa, PropPages[i].uiReplaceWith, PropSheetAddPage, (LPARAM)&psh) != 0) { /* The shell extension added one or more pages to replace a page. Don't create the built-in page anymore! */ continue; } InitPropSheetPage(&psh, PropPages[i].idDlg, PropPages[i].DlgProc); } if (hpsxa != NULL) SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh); if (nPage != 0 && nPage <= psh.nPages) psh.nStartPage = nPage; ret = (LONG)(PropertySheet(&psh) != -1); if (hpsxa != NULL) SHDestroyPropSheetExtArray(hpsxa); return ret; } /* EOF */