/*++ Copyright (c) 1994-1998, Microsoft Corporation All rights reserved. Module Name: mousebut.c Abstract: This module contains the routines for the Mouse Buttons Property Sheet page. Revision History: --*/ // // Include Files. // #include "main.h" #include "util.h" #include "rc.h" #include "mousectl.h" #include #include // needed for ERROR_SUCCESS value #include "mousehlp.h" // // Constant Declarations. // const TCHAR szYes[] = TEXT("yes"); const TCHAR szNo[] = TEXT("no"); const TCHAR szDblClkSpeed[] = TEXT("DoubleClickSpeed"); const TCHAR szRegStr_Mouse[] = REGSTR_PATH_MOUSE; #define SAFE_DESTROYICON(hicon) if (hicon) { DestroyIcon(hicon); hicon=NULL; } // // SwapMouseButtons takes: // TRUE to make it a right mouse // FALSE to make it a left mouse // #define RIGHT TRUE #define LEFT FALSE //Identifiers used for setting DoubleClick speed #define DBLCLICK_MIN 200 // milliseconds #define DBLCLICK_MAX 900 #define DBLCLICK_DEFAULT_TIME 500 #define DBLCLICK_TIME_SLIDER_MIN 0 #define DBLCLICK_TIME_SLIDER_MAX 10 #define DBLCLICK_RANGE (DBLCLICK_MAX - DBLCLICK_MIN) #define DBLCLICK_SLIDER_RANGE ( CLICKLOCK_TIME_SLIDER_MAX - CLICKLOCK_TIME_SLIDER_MIN) #define DBLCLICK_TICKMULT (DBLCLICK_RANGE / DBLCLICK_SLIDER_RANGE) #define DBLCLICK_TICKS_TO_TIME(ticks) (SHORT) (((DBLCLICK_TIME_SLIDER_MAX - ticks) * DBLCLICK_TICKMULT) + DBLCLICK_MIN) #define DBLCLICK_TIME_TO_TICKS(time) (SHORT) (DBLCLICK_TIME_SLIDER_MAX - ((time - DBLCLICK_MIN) / DBLCLICK_TICKMULT)) #define CLICKLOCK_TIME_SLIDER_MIN 1 //Minimum ClickLock Time setting for slider control #define CLICKLOCK_TIME_SLIDER_MAX 11 //Maximum ClickLock Time setting for slider control #define CLICKLOCK_TIME_FACTOR 200 //Multiplier for translating clicklock time slider units to milliseconds #define TICKS_PER_CLICK 1 //Size assumed as the default size for icons, used for scaling the icons #define ICON_SIZEX 32 #define ICON_SIZEY 32 //The font size used for scaling #define SMALLFONTSIZE 96 #define CLAPPER_CLASS TEXT("Clapper") // // From shell\inc\shsemip.h // #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) // // Typedef Declarations. // typedef struct tag_MouseGenStr { BOOL bSwap; BOOL bOrigSwap; short ClickSpeed; short OrigDblClkSpeed; HWND hWndDblClkScroll; HWND hDlg; HWND hWndDblClk_TestArea; RECT DblClkRect; HICON hIconDblClick[2]; #ifdef SHELL_SINGLE_CLICK BOOL bShellSingleClick, bOrigShellSingleClick ; HICON hIconSglClick, hIconDblClick ; #endif //SHELL_SINGLE_CLICK BOOL bClickLock; BOOL bOrigClickLock; DWORD dwClickLockTime; DWORD dwOrigClickLockTime; } MOUSEBUTSTR, *PMOUSEBUTSTR, *LPMOUSEBUTSTR; // // Context Help Ids. // const DWORD aMouseButHelpIds[] = { IDC_GROUPBOX_1, IDH_COMM_GROUPBOX, IDBTN_BUTTONSWAP, IDH_MOUSE_SWITCH, MOUSE_MOUSEBMP, IDH_MOUSE_SWITCH_PIC, IDC_GROUPBOX_2, IDH_COMM_GROUPBOX, IDC_GROUPBOX_4, IDH_COMM_GROUPBOX, MOUSE_CLICKSCROLL, IDH_MOUSE_DOUBLECLICK, IDC_DBLCLICK_TEXT, IDH_COMM_GROUPBOX, IDC_TEST_DOUBLE_CLICK, IDH_MOUSE_DCLICK_TEST_BOX, MOUSE_DBLCLK_TEST_AREA, IDH_MOUSE_DCLICK_TEST_BOX, IDC_GROUPBOX_6, IDH_COMM_GROUPBOX, IDCK_CLICKLOCK, IDH_MOUSE_CLKLCK_CHKBOX, IDBTN_CLICKLOCK_SETTINGS, IDH_MOUSE_CLKLCK_SETTINGS_BTN, IDC_CLICKLOCK_TEXT, IDH_COMM_GROUPBOX, IDC_CLICKLOCK_SETTINGS_TXT, IDH_COMM_GROUPBOX, IDT_CLICKLOCK_TIME_SETTINGS, IDH_MOUSE_CLKLCK_DIALOG, IDC_CLICKLOCK_SETTINGS_LEFT_TXT, IDH_MOUSE_CLKLCK_DIALOG, IDC_CLICKLOCK_SETTINGS_RIGHT_TXT, IDH_MOUSE_CLKLCK_DIALOG, #ifdef SHELL_SINGLE_CLICK MOUSE_SGLCLICK, IDH_MOUSE_SGLCLICK, MOUSE_DBLCLICK, IDH_MOUSE_DBLCLICK, #endif // SHELL_SINGLE_CLICK 0,0 }; // // helper function prototypes // void ShellClick_UpdateUI( HWND hDlg, PMOUSEBUTSTR pMstr) ; void ShellClick_Refresh( PMOUSEBUTSTR pMstr ) ; // // Debug Info. // #ifdef DEBUG #define REG_INTEGER 1000 int fTraceRegAccess = 0; void RegDetails( int iWrite, HKEY hk, LPCTSTR lpszSubKey, LPCTSTR lpszValueName, DWORD dwType, LPTSTR lpszString, int iValue) { TCHAR Buff[256]; TCHAR *lpszReadWrite[] = { TEXT("DESK.CPL:Read"), TEXT("DESK.CPL:Write") }; if (!fTraceRegAccess) { return; } switch (dwType) { case ( REG_SZ ) : { wsprintf( Buff, TEXT("%s String:hk=%#08lx, %s:%s=%s\n\r"), lpszReadWrite[iWrite], hk, lpszSubKey, lpszValueName, lpszString ); break; } case ( REG_INTEGER ) : { wsprintf( Buff, TEXT("%s int:hk=%#08lx, %s:%s=%d\n\r"), lpszReadWrite[iWrite], hk, lpszSubKey, lpszValueName, iValue ); break; } case ( REG_BINARY ) : { wsprintf( Buff, TEXT("%s Binary:hk=%#08lx, %s:%s=%#0lx;DataSize:%d\r\n"), lpszReadWrite[iWrite], hk, lpszSubKey, lpszValueName, lpszString, iValue ); break; } } OutputDebugString(Buff); } #endif // DEBUG //////////////////////////////////////////////////////////////////////////// // // GetIntFromSubKey // // hKey is the handle to the subkey (already pointing to the proper // location. // //////////////////////////////////////////////////////////////////////////// int GetIntFromSubkey( HKEY hKey, LPCTSTR lpszValueName, int iDefault) { TCHAR szValue[20]; DWORD dwSizeofValueBuff = sizeof(szValue); DWORD dwType; int iRetValue = iDefault; if ((RegQueryValueEx( hKey, (LPTSTR)lpszValueName, NULL, &dwType, (LPBYTE)szValue, &dwSizeofValueBuff ) == ERROR_SUCCESS) && (dwSizeofValueBuff)) { // // BOGUS: This handles only the string type entries now! // if (dwType == REG_SZ) { iRetValue = (int)StrToLong(szValue); } #ifdef DEBUG else { OutputDebugString(TEXT("String type expected from Registry\n\r")); } #endif } #ifdef DEBUG RegDetails(0, hKey, TEXT(""), lpszValueName, REG_INTEGER, NULL, iRetValue); #endif return (iRetValue); } //////////////////////////////////////////////////////////////////////////// // // GetIntFromReg // // Opens the given subkey and gets the int value. // //////////////////////////////////////////////////////////////////////////// int GetIntFromReg( HKEY hKey, LPCTSTR lpszSubkey, LPCTSTR lpszNameValue, int iDefault) { HKEY hk; int iRetValue = iDefault; // // See if the key is present. // if (RegOpenKey(hKey, lpszSubkey, &hk) == ERROR_SUCCESS) { iRetValue = GetIntFromSubkey(hk, lpszNameValue, iDefault); RegCloseKey(hk); } return (iRetValue); } //////////////////////////////////////////////////////////////////////////// // // GetStringFromReg // // Opens the given subkey and gets the string value. // //////////////////////////////////////////////////////////////////////////// BOOL GetStringFromReg( HKEY hKey, LPCTSTR lpszSubkey, LPCTSTR lpszValueName, LPCTSTR lpszDefault, LPTSTR lpszValue, DWORD dwSizeofValueBuff) { HKEY hk; DWORD dwType; BOOL fSuccess = FALSE; // // See if the key is present. // if (RegOpenKey(hKey, lpszSubkey, &hk) == ERROR_SUCCESS) { if ((RegQueryValueEx( hk, (LPTSTR)lpszValueName, NULL, &dwType, (LPBYTE)lpszValue, &dwSizeofValueBuff ) == ERROR_SUCCESS) && (dwSizeofValueBuff)) { // // BOGUS: This handles only the string type entries now! // #ifdef DEBUG if (dwType != REG_SZ) { OutputDebugString(TEXT("String type expected from Registry\n\r")); } else #endif fSuccess = TRUE; } RegCloseKey(hk); } // // If failure, use the default string. // if (!fSuccess) { lstrcpy(lpszValue, lpszDefault); } #ifdef DEBUG RegDetails(0, hKey, lpszSubkey, lpszValueName, REG_SZ, lpszValue, 0); #endif return (fSuccess); } //////////////////////////////////////////////////////////////////////////// // // UpdateRegistry // // This updates a given value of any data type at a given location in // the registry. // // The value name is passed in as an Id to a string in USER's String // table. // //////////////////////////////////////////////////////////////////////////// BOOL UpdateRegistry( HKEY hKey, LPCTSTR lpszSubkey, LPCTSTR lpszValueName, DWORD dwDataType, LPVOID lpvData, DWORD dwDataSize) { HKEY hk; if (RegCreateKey(hKey, lpszSubkey, &hk) == ERROR_SUCCESS) { RegSetValueEx( hk, (LPTSTR)lpszValueName, 0, dwDataType, (LPBYTE)lpvData, dwDataSize ); #ifdef DEBUG RegDetails(1, hKey, lpszSubkey, lpszValueName, dwDataType, lpvData, (int)dwDataSize); #endif RegCloseKey(hk); return (TRUE); } return (FALSE); } //////////////////////////////////////////////////////////////////////////// // // CenterDlgOverParent // //////////////////////////////////////////////////////////////////////////// void WINAPI CenterDlgOverParent (HWND hWnd) { HWND hwndOwner; RECT rc, rcDlg, rcOwner; if ((hwndOwner = GetParent(hWnd)) == NULL) { return; } GetWindowRect(hwndOwner, &rcOwner); GetWindowRect(hWnd, &rcDlg); CopyRect(&rc, &rcOwner); // Offset the owner and dialog box rectangles so that // right and bottom values represent the width and // height, and then offset the owner again to discard // space taken up by the dialog box. OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top); OffsetRect(&rc, -rc.left, -rc.top); OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom); //The new position is the sum of half the remaining //space and the owner's original position. SetWindowPos(hWnd, HWND_TOP, rcOwner.left + (rc.right / 2), rcOwner.top + (rc.bottom / 2), 0, 0, // ignores size arguments SWP_NOSIZE); // now let's verify left side is not off screen GetWindowRect( hWnd, &rc); if ((rc.left < 0) || (rc.top < 0)) { if (rc.left < 0) rc.left = 0; if (rc.top < 0) rc.top = 0; SetWindowPos(hWnd, HWND_TOP, rc.left, rc.top, 0, 0, // ignores size arguments SWP_NOSIZE); } } //////////////////////////////////////////////////////////////////////////// // // ShowButtonState // // Swaps the menu and selection bitmaps. // //////////////////////////////////////////////////////////////////////////// void ShowButtonState( PMOUSEBUTSTR pMstr) { HWND hDlg; Assert(pMstr); hDlg = pMstr->hDlg; MouseControlSetSwap(GetDlgItem(hDlg, MOUSE_MOUSEBMP), pMstr->bSwap); CheckDlgButton(hDlg,IDBTN_BUTTONSWAP, pMstr->bSwap); #ifdef SHELL_SINGLE_CLICK //This was removed CheckDlgButton(hDlg, MOUSE_SGLCLICK, pMstr->bShellSingleClick); CheckDlgButton(hDlg, MOUSE_DBLCLICK, !pMstr->bShellSingleClick); #endif //SHELL_SINGLE_CLICK } //////////////////////////////////////////////////////////////////////////// // // DestroyMouseButDlg // //////////////////////////////////////////////////////////////////////////// void DestroyMouseButDlg( PMOUSEBUTSTR pMstr) { if (pMstr) { #ifdef SHELL_SINGLE_CLICK SAFE_DESTROYICON( pMstr->hIconSglClick ) ; SAFE_DESTROYICON( pMstr->hIconDblClick ) ; #endif SAFE_DESTROYICON( pMstr->hIconDblClick[0]); SAFE_DESTROYICON( pMstr->hIconDblClick[1]); SetWindowLongPtr(pMstr->hDlg, DWLP_USER, 0); LocalFree((HGLOBAL)pMstr); } } //////////////////////////////////////////////////////////////////////////// // // ClickLockSettingsDlg // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK ClickLockSettingsDlg ( HWND hDlg, // dialog window handle UINT msg, // message identifier WPARAM wParam, // primary parameter LPARAM lParam) // secondary parameter { static DWORD* pdwClickLockTime; static HICON hIcon = 0; switch (msg) { case WM_INITDIALOG: { WPARAM wSliderSetting; //ClickLock time in terms of slider units HourGlass (TRUE); Assert(lParam); pdwClickLockTime = (DWORD*) lParam; //Save Original value for return //Convert into slider units from milliseconds. Note that the slider //values get larger as the ClickLock time gets larger. wSliderSetting = (*pdwClickLockTime) / CLICKLOCK_TIME_FACTOR; //Make sure setting is within valid range for ClickLock slider wSliderSetting = max(wSliderSetting, CLICKLOCK_TIME_SLIDER_MIN); wSliderSetting = min(wSliderSetting, CLICKLOCK_TIME_SLIDER_MAX); SendDlgItemMessage (hDlg, IDT_CLICKLOCK_TIME_SETTINGS, TBM_SETRANGE, TRUE, MAKELONG(CLICKLOCK_TIME_SLIDER_MIN, CLICKLOCK_TIME_SLIDER_MAX)); SendDlgItemMessage (hDlg, IDT_CLICKLOCK_TIME_SETTINGS, TBM_SETPAGESIZE, 0, TICKS_PER_CLICK); // click movement SendDlgItemMessage (hDlg, IDT_CLICKLOCK_TIME_SETTINGS, TBM_SETPOS, TRUE, (LPARAM)(LONG)wSliderSetting); //icon for the dialog // (saved in a static variable, and released on WM_DESTROY) hIcon = LoadIcon((HINSTANCE)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ), MAKEINTRESOURCE(ICON_CLICKLOCK)); SendMessage( GetDlgItem (hDlg, MOUSE_CLICKICON), STM_SETICON, (WPARAM)hIcon, 0L ); CenterDlgOverParent(hDlg); //Center dialog here so it doesn't jump around on screen HourGlass(FALSE); return(TRUE); } case WM_HSCROLL: { if (LOWORD(wParam) == TB_ENDTRACK) { DWORD dwClTime; int wSliderSetting = (int) SendMessage (GetDlgItem (hDlg, IDT_CLICKLOCK_TIME_SETTINGS), TBM_GETPOS, 0, 0L); dwClTime = wSliderSetting * CLICKLOCK_TIME_FACTOR; SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, 0, (PVOID) (LOWORD(dwClTime)), 0); } } break; case WM_HELP: //F1 { WinHelp( ((LPHELPINFO)lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aMouseButHelpIds ); } break; case WM_CONTEXTMENU: // Display simple "What's This?" menu { WinHelp( (HWND) wParam, HELP_FILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aMouseButHelpIds ); } break; case WM_DESTROY: SAFE_DESTROYICON(hIcon); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: // Flag to save setting { DWORD dwClickLockTime; int wSliderSetting = (int) SendMessage (GetDlgItem (hDlg, IDT_CLICKLOCK_TIME_SETTINGS), TBM_GETPOS, 0, 0L); //verify range wSliderSetting = max(wSliderSetting, CLICKLOCK_TIME_SLIDER_MIN); wSliderSetting = min(wSliderSetting, CLICKLOCK_TIME_SLIDER_MAX); // Convert to milliseconds from slider units. dwClickLockTime = wSliderSetting * CLICKLOCK_TIME_FACTOR; *pdwClickLockTime = dwClickLockTime; EndDialog(hDlg, IDOK); break; } case IDCANCEL: // revert to previous setting EndDialog(hDlg, IDCANCEL); break; default: return(FALSE); } return (TRUE); default: return(FALSE); } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // InitMouseButDlg // //////////////////////////////////////////////////////////////////////////// BOOL InitMouseButDlg( HWND hDlg) { SHELLSTATE shellstate = {0} ; PMOUSEBUTSTR pMstr = NULL; HINSTANCE hInstDlg = (HINSTANCE)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ) ; HWND hwndClickLockSettingsButton = GetDlgItem(hDlg, IDBTN_CLICKLOCK_SETTINGS); DWORD dwClickLockSetting = 0; HWND hwndDoubleClickTestArea = NULL; pMstr = (PMOUSEBUTSTR)LocalAlloc(LPTR , sizeof(MOUSEBUTSTR)); if (pMstr == NULL) { return (TRUE); } SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pMstr); pMstr->hDlg = hDlg; // //Set up the double click test area // pMstr->hWndDblClk_TestArea = GetDlgItem(hDlg, MOUSE_DBLCLK_TEST_AREA); GetWindowRect(pMstr->hWndDblClk_TestArea, &pMstr->DblClkRect); MapWindowPoints(NULL, hDlg, (LPPOINT) &pMstr->DblClkRect, 2); pMstr->hIconDblClick[0] = LoadIcon(hInstDlg, MAKEINTRESOURCE(ICON_FOLDER_CLOSED)); pMstr->hIconDblClick[1] = LoadIcon(hInstDlg, MAKEINTRESOURCE(ICON_FOLDER_OPEN)); SendMessage(pMstr->hWndDblClk_TestArea, STM_SETICON, (WPARAM)pMstr->hIconDblClick[0], 0L); // // Set (and get), then restore the state of the mouse buttons. // (pMstr->bOrigSwap) = (pMstr->bSwap) = SwapMouseButton(TRUE); SwapMouseButton(pMstr->bOrigSwap); #ifdef SHELL_SINGLE_CLICK // // Get shell single-click behavior: // SHGetSetSettings( &shellstate, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC, FALSE /*get*/ ) ; pMstr->bShellSingleClick = pMstr->bOrigShellSingleClick = shellstate.fWin95Classic ? FALSE : shellstate.fDoubleClickInWebView ? FALSE : TRUE ; pMstr->hIconSglClick = LoadIcon( hInstDlg, MAKEINTRESOURCE( IDI_SGLCLICK ) ) ; pMstr->hIconDblClick = LoadIcon( hInstDlg, MAKEINTRESOURCE( IDI_DBLCLICK ) ) ; ShellClick_UpdateUI( hDlg, pMstr ) ; #endif //SHELL_SINGLE_CLICK // // Initialize check/radio button state // ShowButtonState(pMstr); pMstr->OrigDblClkSpeed = pMstr->ClickSpeed = (SHORT) GetIntFromReg( HKEY_CURRENT_USER, szRegStr_Mouse, szDblClkSpeed, DBLCLICK_DEFAULT_TIME ); pMstr->hWndDblClkScroll = GetDlgItem(hDlg, MOUSE_CLICKSCROLL); SendMessage( pMstr->hWndDblClkScroll, TBM_SETRANGE, 0, MAKELONG(DBLCLICK_TIME_SLIDER_MIN, DBLCLICK_TIME_SLIDER_MAX) ); SendMessage( pMstr->hWndDblClkScroll, TBM_SETPOS, TRUE, (LONG) (DBLCLICK_TIME_TO_TICKS(pMstr->ClickSpeed)) ); SetDoubleClickTime(pMstr->ClickSpeed); // //Get clicklock settings and set the checkbox // SystemParametersInfo(SPI_GETMOUSECLICKLOCK, 0, (PVOID)&dwClickLockSetting, 0); pMstr->bOrigClickLock = pMstr->bClickLock = (dwClickLockSetting) ? TRUE : FALSE; if ( pMstr->bClickLock ) { CheckDlgButton (hDlg, IDCK_CLICKLOCK, BST_CHECKED); EnableWindow(hwndClickLockSettingsButton, TRUE); } else { CheckDlgButton (hDlg, IDCK_CLICKLOCK, BST_UNCHECKED); EnableWindow(hwndClickLockSettingsButton, FALSE); } // click lock speed { DWORD dwClTime = 0; SystemParametersInfo(SPI_GETMOUSECLICKLOCKTIME, 0, (PVOID)&dwClTime, 0); dwClTime = max(dwClTime, CLICKLOCK_TIME_SLIDER_MIN * CLICKLOCK_TIME_FACTOR); dwClTime = min(dwClTime, CLICKLOCK_TIME_SLIDER_MAX * CLICKLOCK_TIME_FACTOR); pMstr->dwOrigClickLockTime = pMstr->dwClickLockTime = dwClTime; } return (TRUE); } //////////////////////////////////////////////////////////////////////////// // // MouseButDlg // //////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK MouseButDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static int iTestIcon = 0; //index into hIconDblClick array PMOUSEBUTSTR pMstr = (PMOUSEBUTSTR)GetWindowLongPtr(hDlg, DWLP_USER); switch (message) { case ( WM_INITDIALOG ) : { iTestIcon = 0; return (InitMouseButDlg(hDlg)); } case ( WM_DESTROY ) : { DestroyMouseButDlg(pMstr); break; } case ( WM_HSCROLL ) : { if ((HWND)lParam == pMstr->hWndDblClkScroll) { short temp = DBLCLICK_TICKS_TO_TIME((short)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0L )); if (temp != pMstr->ClickSpeed) { pMstr->ClickSpeed = temp; SetDoubleClickTime(pMstr->ClickSpeed); SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L); } } break; } case ( WM_RBUTTONDBLCLK ) : case ( WM_LBUTTONDBLCLK ) : { POINT point = { (int)MAKEPOINTS(lParam).x, (int)MAKEPOINTS(lParam).y }; if (PtInRect(&pMstr->DblClkRect, point)) { iTestIcon ^= 1; SendMessage(pMstr->hWndDblClk_TestArea, STM_SETICON, (WPARAM)pMstr->hIconDblClick[iTestIcon], 0L); } break; } case ( WM_COMMAND ) : { switch (LOWORD(wParam)) { case ( IDCK_CLICKLOCK ) : { HWND hwndClickLockSettingsButton = GetDlgItem(hDlg, IDBTN_CLICKLOCK_SETTINGS); SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L); pMstr->bClickLock = !(pMstr->bClickLock); // update control(s) appearance CheckDlgButton (hDlg, IDCK_CLICKLOCK, ( pMstr->bClickLock ) ? BST_CHECKED : BST_UNCHECKED); EnableWindow(hwndClickLockSettingsButton, ( pMstr->bClickLock ) ? TRUE : FALSE); SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, IntToPtr(pMstr->bClickLock), 0); break; } case ( IDBTN_CLICKLOCK_SETTINGS ) : { LPARAM lRet; UINT code = HIWORD(wParam); DWORD dwTempClickLockTime = pMstr->dwClickLockTime; if (code == BN_CLICKED) { lRet = DialogBoxParam ((HINSTANCE)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ), MAKEINTRESOURCE(IDD_CLICKLOCK_SETTINGS_DLG ), GetParent (hDlg), ClickLockSettingsDlg, (LPARAM) &dwTempClickLockTime); if (lRet == IDOK && pMstr->dwClickLockTime != dwTempClickLockTime) { pMstr->dwClickLockTime = dwTempClickLockTime; SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L); } else if (lRet == IDCANCEL) { //set back DWORD dwClTime = pMstr->dwClickLockTime; SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, 0, IntToPtr(LOWORD(dwClTime)), 0); } } break; } case ( IDBTN_BUTTONSWAP) : { pMstr->bSwap = !pMstr->bSwap; SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L); SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP, pMstr->bSwap, NULL, 0); ShowButtonState(pMstr); } #ifdef SHELL_SINGLE_CLICK case ( MOUSE_SGLCLICK ) : case ( MOUSE_DBLCLICK ) : { if( pMstr->bShellSingleClick != (MOUSE_SGLCLICK == LOWORD(wParam)) ) { pMstr->bShellSingleClick = (MOUSE_SGLCLICK == LOWORD(wParam)) ; ShellClick_UpdateUI( hDlg, pMstr ) ; SendMessage( GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L ) ; } break ; } #endif // SHELL_SINGLE_CLICK } break; } case ( WM_NOTIFY ) : { switch (((NMHDR *)lParam)->code) { case ( PSN_APPLY ) : { HourGlass(TRUE); // // Apply Button Swap setting. // if (pMstr->bSwap != pMstr->bOrigSwap) { SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP, pMstr->bSwap, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ); pMstr->bOrigSwap = pMstr->bSwap; } // // Apply DoubleClickTime setting. // if (pMstr->ClickSpeed != pMstr->OrigDblClkSpeed) { SystemParametersInfo( SPI_SETDOUBLECLICKTIME, pMstr->ClickSpeed, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ); pMstr->OrigDblClkSpeed = pMstr->ClickSpeed; } // // Apply ClickLock setting. // if (pMstr->bClickLock != pMstr->bOrigClickLock) { SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, IntToPtr(pMstr->bClickLock), SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); pMstr->bOrigClickLock = pMstr->bClickLock; } // // Apply ClickLockTime setting. // if (pMstr->dwClickLockTime != pMstr->dwOrigClickLockTime) { SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, 0, (PVOID) (LOWORD(pMstr->dwClickLockTime)), SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ); pMstr->dwOrigClickLockTime = pMstr->dwClickLockTime; } #ifdef SHELL_SINGLE_CLICK if( pMstr->bOrigShellSingleClick != pMstr->bShellSingleClick ) { SHELLSTATE shellstate = {0} ; ULONG dwFlags = SSF_DOUBLECLICKINWEBVIEW ; shellstate.fWin95Classic = shellstate.fDoubleClickInWebView = !pMstr->bShellSingleClick ; // update the WIN95CLASSIC member only if we've chosen single-click. if( pMstr->bShellSingleClick ) dwFlags |= SSF_WIN95CLASSIC ; SHGetSetSettings( &shellstate, dwFlags, TRUE ) ; ShellClick_Refresh( pMstr ) ; pMstr->bOrigShellSingleClick = pMstr->bShellSingleClick ; } #endif //SHELL_SINGLE_CLICK HourGlass(FALSE); break; } case ( PSN_RESET ) : { // // Reset Button Swap setting. // if (pMstr->bSwap != pMstr->bOrigSwap) { SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP, pMstr->bOrigSwap, NULL, 0); } // // Reset DoubleClickTime setting. // if (pMstr->ClickSpeed != pMstr->OrigDblClkSpeed) { SystemParametersInfo( SPI_SETDOUBLECLICKTIME, pMstr->OrigDblClkSpeed, NULL, 0); } // // Reset ClickLock setting. // if (pMstr->bClickLock != pMstr->bOrigClickLock) { SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, IntToPtr(pMstr->bOrigClickLock), 0); } // // Reset ClickLockTime setting. // if (pMstr->dwClickLockTime != pMstr->dwOrigClickLockTime) { SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, 0, (PVOID) (LOWORD(pMstr->dwOrigClickLockTime)), 0); } #ifdef SHELL_SINGLE_CLICK if( pMstr->bOrigShellSingleClick != pMstr->bShellSingleClick ) { SHELLSTATE shellstate = {0} ; ULONG dwFlags = SSF_DOUBLECLICKINWEBVIEW ; shellstate.fWin95Classic = shellstate.fDoubleClickInWebView = !pMstr->bOrigShellSingleClick ; // update the WIN95CLASSIC member only if we've chosen single-click. if( pMstr->bShellSingleClick ) dwFlags |= SSF_WIN95CLASSIC ; SHGetSetSettings( &shellstate, dwFlags, TRUE ) ; ShellClick_Refresh( pMstr ) ; pMstr->bShellSingleClick = pMstr->bOrigShellSingleClick ; } #endif //SHELL_SINGLE_CLICK break; } default : { return (FALSE); } } break; } case ( WM_HELP ) : // F1 { WinHelp( ((LPHELPINFO)lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP, (DWORD_PTR)(LPTSTR)aMouseButHelpIds ); break; } case ( WM_CONTEXTMENU ) : // right mouse click { WinHelp( (HWND) wParam, HELP_FILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR)aMouseButHelpIds ); break; } case ( WM_DISPLAYCHANGE ) : case ( WM_WININICHANGE ) : case ( WM_SYSCOLORCHANGE ) : { SHPropagateMessage(hDlg, message, wParam, lParam, TRUE); return TRUE; } default : { return (FALSE); } } return (TRUE); } #ifdef SHELL_SINGLE_CLICK //////////////////////////////////////////////////////////////////////////// // // ShellClick_UpdateUI // // Assigns the appropriate icon for shell single/double click // //////////////////////////////////////////////////////////////////////////// void ShellClick_UpdateUI( HWND hDlg, PMOUSEBUTSTR pMstr) { HICON hicon = pMstr->bShellSingleClick ? pMstr->hIconSglClick : pMstr->hIconDblClick ; SendMessage( GetDlgItem( hDlg, MOUSE_CLICKICON ), STM_SETICON, (WPARAM)hicon, 0L ) ; } #endif //SHELL_SINGLE_CLICK //////////////////////////////////////////////////////////////////////////// // // IsShellWindow // // Determines whether the specified window is a shell folder window. // //////////////////////////////////////////////////////////////////////////// #define c_szExploreClass TEXT("ExploreWClass") #define c_szIExploreClass TEXT("IEFrame") #ifdef IE3CLASSNAME #define c_szCabinetClass TEXT("IEFrame") #else #define c_szCabinetClass TEXT("CabinetWClass") #endif BOOL IsShellWindow( HWND hwnd ) { TCHAR szClass[32]; GetClassName(hwnd, szClass, ARRAYSIZE(szClass)); return (lstrcmp(szClass, c_szCabinetClass) == 0) || (lstrcmp(szClass, c_szExploreClass) == 0) || (lstrcmp(szClass, c_szIExploreClass) == 0) ; } //The following value is taken from shdocvw\rcids.h #ifndef FCIDM_REFRESH #define FCIDM_REFRESH 0xA220 #endif // FCIDM_REFRESH //////////////////////////////////////////////////////////////////////////// // // ShellClick_RefreshEnumProc // // EnumWindow callback for shell refresh. // //////////////////////////////////////////////////////////////////////////// BOOL CALLBACK ShellClick_RefreshEnumProc( HWND hwnd, LPARAM lParam ) { if( IsShellWindow(hwnd) ) PostMessage(hwnd, WM_COMMAND, FCIDM_REFRESH, 0L); return(TRUE); } //////////////////////////////////////////////////////////////////////////// // // ShellClick_Refresh // // Re-renders the contents of all shell folder windows. // //////////////////////////////////////////////////////////////////////////// void ShellClick_Refresh( PMOUSEBUTSTR pMstr ) { HWND hwndDesktop = FindWindowEx(NULL, NULL, TEXT(STR_DESKTOPCLASS), NULL); if( NULL != hwndDesktop ) PostMessage( hwndDesktop, WM_COMMAND, FCIDM_REFRESH, 0L ); EnumWindows( ShellClick_RefreshEnumProc, 0L ) ; }