Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1131 lines
34 KiB

  1. /*++
  2. Copyright (c) 1994-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. mousebut.c
  5. Abstract:
  6. This module contains the routines for the Mouse Buttons Property Sheet
  7. page.
  8. Revision History:
  9. --*/
  10. //
  11. // Include Files.
  12. //
  13. #include "main.h"
  14. #include "util.h"
  15. #include "rc.h"
  16. #include "mousectl.h"
  17. #include <regstr.h>
  18. #include <winerror.h> // needed for ERROR_SUCCESS value
  19. #include "mousehlp.h"
  20. //
  21. // Constant Declarations.
  22. //
  23. const TCHAR szYes[] = TEXT("yes");
  24. const TCHAR szNo[] = TEXT("no");
  25. const TCHAR szDblClkSpeed[] = TEXT("DoubleClickSpeed");
  26. const TCHAR szRegStr_Mouse[] = REGSTR_PATH_MOUSE;
  27. #define SAFE_DESTROYICON(hicon) if (hicon) { DestroyIcon(hicon); hicon=NULL; }
  28. //
  29. // SwapMouseButtons takes:
  30. // TRUE to make it a right mouse
  31. // FALSE to make it a left mouse
  32. //
  33. #define RIGHT TRUE
  34. #define LEFT FALSE
  35. //Identifiers used for setting DoubleClick speed
  36. #define DBLCLICK_MIN 200 // milliseconds
  37. #define DBLCLICK_MAX 900
  38. #define DBLCLICK_DEFAULT_TIME 500
  39. #define DBLCLICK_TIME_SLIDER_MIN 0
  40. #define DBLCLICK_TIME_SLIDER_MAX 10
  41. #define DBLCLICK_RANGE (DBLCLICK_MAX - DBLCLICK_MIN)
  42. #define DBLCLICK_SLIDER_RANGE ( CLICKLOCK_TIME_SLIDER_MAX - CLICKLOCK_TIME_SLIDER_MIN)
  43. #define DBLCLICK_TICKMULT (DBLCLICK_RANGE / DBLCLICK_SLIDER_RANGE)
  44. #define DBLCLICK_TICKS_TO_TIME(ticks) (SHORT) (((DBLCLICK_TIME_SLIDER_MAX - ticks) * DBLCLICK_TICKMULT) + DBLCLICK_MIN)
  45. #define DBLCLICK_TIME_TO_TICKS(time) (SHORT) (DBLCLICK_TIME_SLIDER_MAX - ((time - DBLCLICK_MIN) / DBLCLICK_TICKMULT))
  46. #define CLICKLOCK_TIME_SLIDER_MIN 1 //Minimum ClickLock Time setting for slider control
  47. #define CLICKLOCK_TIME_SLIDER_MAX 11 //Maximum ClickLock Time setting for slider control
  48. #define CLICKLOCK_TIME_FACTOR 200 //Multiplier for translating clicklock time slider units to milliseconds
  49. #define TICKS_PER_CLICK 1
  50. //Size assumed as the default size for icons, used for scaling the icons
  51. #define ICON_SIZEX 32
  52. #define ICON_SIZEY 32
  53. //The font size used for scaling
  54. #define SMALLFONTSIZE 96
  55. #define CLAPPER_CLASS TEXT("Clapper")
  56. //
  57. // Typedef Declarations.
  58. //
  59. typedef struct tag_MouseGenStr
  60. {
  61. BOOL bSwap;
  62. BOOL bOrigSwap;
  63. short ClickSpeed;
  64. short OrigDblClkSpeed;
  65. HWND hWndDblClkScroll;
  66. HWND hDlg;
  67. HWND hWndDblClk_TestArea;
  68. RECT DblClkRect;
  69. HICON hIconDblClick[2];
  70. #ifdef SHELL_SINGLE_CLICK
  71. BOOL bShellSingleClick,
  72. bOrigShellSingleClick ;
  73. HICON hIconSglClick,
  74. hIconDblClick ;
  75. #endif //SHELL_SINGLE_CLICK
  76. BOOL bClickLock;
  77. BOOL bOrigClickLock;
  78. DWORD dwClickLockTime;
  79. DWORD dwOrigClickLockTime;
  80. } MOUSEBUTSTR, *PMOUSEBUTSTR, *LPMOUSEBUTSTR;
  81. //
  82. // Context Help Ids.
  83. //
  84. const DWORD aMouseButHelpIds[] =
  85. {
  86. IDC_GROUPBOX_1, IDH_COMM_GROUPBOX,
  87. IDBTN_BUTTONSWAP, IDH_MOUSE_SWITCH,
  88. MOUSE_MOUSEBMP, IDH_MOUSE_SWITCH_PIC,
  89. IDC_GROUPBOX_2, IDH_COMM_GROUPBOX,
  90. IDC_GROUPBOX_4, IDH_COMM_GROUPBOX,
  91. MOUSE_CLICKSCROLL, IDH_MOUSE_DOUBLECLICK,
  92. IDC_DBLCLICK_TEXT, IDH_COMM_GROUPBOX,
  93. IDC_TEST_DOUBLE_CLICK, IDH_MOUSE_DCLICK_TEST_BOX,
  94. MOUSE_DBLCLK_TEST_AREA, IDH_MOUSE_DCLICK_TEST_BOX,
  95. IDC_GROUPBOX_6, IDH_COMM_GROUPBOX,
  96. IDCK_CLICKLOCK, IDH_MOUSE_CLKLCK_CHKBOX,
  97. IDBTN_CLICKLOCK_SETTINGS, IDH_MOUSE_CLKLCK_SETTINGS_BTN,
  98. IDC_CLICKLOCK_TEXT, IDH_COMM_GROUPBOX,
  99. IDC_CLICKLOCK_SETTINGS_TXT, IDH_COMM_GROUPBOX,
  100. IDT_CLICKLOCK_TIME_SETTINGS, IDH_MOUSE_CLKLCK_DIALOG,
  101. IDC_CLICKLOCK_SETTINGS_LEFT_TXT, IDH_MOUSE_CLKLCK_DIALOG,
  102. IDC_CLICKLOCK_SETTINGS_RIGHT_TXT, IDH_MOUSE_CLKLCK_DIALOG,
  103. #ifdef SHELL_SINGLE_CLICK
  104. MOUSE_SGLCLICK, IDH_MOUSE_SGLCLICK,
  105. MOUSE_DBLCLICK, IDH_MOUSE_DBLCLICK,
  106. #endif // SHELL_SINGLE_CLICK
  107. 0,0
  108. };
  109. //
  110. // helper function prototypes
  111. //
  112. void ShellClick_UpdateUI( HWND hDlg, PMOUSEBUTSTR pMstr) ;
  113. void ShellClick_Refresh( PMOUSEBUTSTR pMstr ) ;
  114. //
  115. // Debug Info.
  116. //
  117. #ifdef DEBUG
  118. #define REG_INTEGER 1000
  119. int fTraceRegAccess = 0;
  120. void RegDetails(
  121. int iWrite,
  122. HKEY hk,
  123. LPCTSTR lpszSubKey,
  124. LPCTSTR lpszValueName,
  125. DWORD dwType,
  126. LPTSTR lpszString,
  127. int iValue)
  128. {
  129. TCHAR Buff[256];
  130. TCHAR *lpszReadWrite[] = { TEXT("DESK.CPL:Read"), TEXT("DESK.CPL:Write") };
  131. if (!fTraceRegAccess)
  132. {
  133. return;
  134. }
  135. switch (dwType)
  136. {
  137. case ( REG_SZ ) :
  138. {
  139. StringCchPrintf(Buff,
  140. ARRAYSIZE(Buff),
  141. TEXT("%s String:hk=%#08lx, %s:%s=%s\n\r"),
  142. lpszReadWrite[iWrite],
  143. hk,
  144. lpszSubKey,
  145. lpszValueName,
  146. lpszString );
  147. break;
  148. }
  149. case ( REG_INTEGER ) :
  150. {
  151. StringCchPrintf(Buff,
  152. ARRAYSIZE(Buff),
  153. TEXT("%s int:hk=%#08lx, %s:%s=%d\n\r"),
  154. lpszReadWrite[iWrite],
  155. hk,
  156. lpszSubKey,
  157. lpszValueName,
  158. iValue );
  159. break;
  160. }
  161. case ( REG_BINARY ) :
  162. {
  163. StringCchPrintf(Buff,
  164. ARRAYSIZE(Buff),
  165. TEXT("%s Binary:hk=%#08lx, %s:%s=%#0lx;DataSize:%d\r\n"),
  166. lpszReadWrite[iWrite],
  167. hk,
  168. lpszSubKey,
  169. lpszValueName,
  170. lpszString,
  171. iValue );
  172. break;
  173. }
  174. }
  175. OutputDebugString(Buff);
  176. }
  177. #endif // DEBUG
  178. ////////////////////////////////////////////////////////////////////////////
  179. //
  180. // GetIntFromSubKey
  181. //
  182. // hKey is the handle to the subkey (already pointing to the proper
  183. // location.
  184. //
  185. ////////////////////////////////////////////////////////////////////////////
  186. int GetIntFromSubkey(
  187. HKEY hKey,
  188. LPCTSTR lpszValueName,
  189. int iDefault)
  190. {
  191. TCHAR szValue[20];
  192. DWORD dwSizeofValueBuff = sizeof(szValue);
  193. DWORD dwType;
  194. int iRetValue = iDefault;
  195. if ((RegQueryValueEx( hKey,
  196. (LPTSTR)lpszValueName,
  197. NULL,
  198. &dwType,
  199. (LPBYTE)szValue,
  200. &dwSizeofValueBuff ) == ERROR_SUCCESS) &&
  201. (dwSizeofValueBuff))
  202. {
  203. //
  204. // BOGUS: This handles only the string type entries now!
  205. //
  206. if (dwType == REG_SZ)
  207. {
  208. iRetValue = (int)StrToLong(szValue);
  209. }
  210. #ifdef DEBUG
  211. else
  212. {
  213. OutputDebugString(TEXT("String type expected from Registry\n\r"));
  214. }
  215. #endif
  216. }
  217. #ifdef DEBUG
  218. RegDetails(0, hKey, TEXT(""), lpszValueName, REG_INTEGER, NULL, iRetValue);
  219. #endif
  220. return (iRetValue);
  221. }
  222. ////////////////////////////////////////////////////////////////////////////
  223. //
  224. // GetIntFromReg
  225. //
  226. // Opens the given subkey and gets the int value.
  227. //
  228. ////////////////////////////////////////////////////////////////////////////
  229. int GetIntFromReg(
  230. HKEY hKey,
  231. LPCTSTR lpszSubkey,
  232. LPCTSTR lpszNameValue,
  233. int iDefault)
  234. {
  235. HKEY hk;
  236. int iRetValue = iDefault;
  237. //
  238. // See if the key is present.
  239. //
  240. if (RegOpenKeyEx(hKey, lpszSubkey, 0, KEY_READ, &hk) == ERROR_SUCCESS)
  241. {
  242. iRetValue = GetIntFromSubkey(hk, lpszNameValue, iDefault);
  243. RegCloseKey(hk);
  244. }
  245. return (iRetValue);
  246. }
  247. ////////////////////////////////////////////////////////////////////////////
  248. //
  249. // CenterDlgOverParent
  250. //
  251. ////////////////////////////////////////////////////////////////////////////
  252. void WINAPI CenterDlgOverParent (HWND hWnd)
  253. {
  254. HWND hwndOwner;
  255. RECT rc, rcDlg, rcOwner;
  256. if ((hwndOwner = GetParent(hWnd)) == NULL)
  257. {
  258. return;
  259. }
  260. GetWindowRect(hwndOwner, &rcOwner);
  261. GetWindowRect(hWnd, &rcDlg);
  262. CopyRect(&rc, &rcOwner);
  263. // Offset the owner and dialog box rectangles so that
  264. // right and bottom values represent the width and
  265. // height, and then offset the owner again to discard
  266. // space taken up by the dialog box.
  267. OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
  268. OffsetRect(&rc, -rc.left, -rc.top);
  269. OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
  270. //The new position is the sum of half the remaining
  271. //space and the owner's original position.
  272. SetWindowPos(hWnd,
  273. HWND_TOP,
  274. rcOwner.left + (rc.right / 2),
  275. rcOwner.top + (rc.bottom / 2),
  276. 0, 0, // ignores size arguments
  277. SWP_NOSIZE);
  278. // now let's verify left side is not off screen
  279. GetWindowRect( hWnd, &rc);
  280. if ((rc.left < 0) || (rc.top < 0))
  281. {
  282. if (rc.left < 0)
  283. rc.left = 0;
  284. if (rc.top < 0)
  285. rc.top = 0;
  286. SetWindowPos(hWnd,
  287. HWND_TOP,
  288. rc.left,
  289. rc.top,
  290. 0, 0, // ignores size arguments
  291. SWP_NOSIZE);
  292. }
  293. }
  294. ////////////////////////////////////////////////////////////////////////////
  295. //
  296. // ShowButtonState
  297. //
  298. // Swaps the menu and selection bitmaps.
  299. //
  300. ////////////////////////////////////////////////////////////////////////////
  301. void ShowButtonState(
  302. PMOUSEBUTSTR pMstr)
  303. {
  304. HWND hDlg;
  305. Assert(pMstr);
  306. hDlg = pMstr->hDlg;
  307. MouseControlSetSwap(GetDlgItem(hDlg, MOUSE_MOUSEBMP), pMstr->bSwap);
  308. CheckDlgButton(hDlg,IDBTN_BUTTONSWAP, pMstr->bSwap);
  309. #ifdef SHELL_SINGLE_CLICK
  310. //This was removed
  311. CheckDlgButton(hDlg, MOUSE_SGLCLICK, pMstr->bShellSingleClick);
  312. CheckDlgButton(hDlg, MOUSE_DBLCLICK, !pMstr->bShellSingleClick);
  313. #endif //SHELL_SINGLE_CLICK
  314. }
  315. ////////////////////////////////////////////////////////////////////////////
  316. //
  317. // DestroyMouseButDlg
  318. //
  319. ////////////////////////////////////////////////////////////////////////////
  320. void DestroyMouseButDlg(
  321. PMOUSEBUTSTR pMstr)
  322. {
  323. if (pMstr)
  324. {
  325. #ifdef SHELL_SINGLE_CLICK
  326. SAFE_DESTROYICON( pMstr->hIconSglClick ) ;
  327. SAFE_DESTROYICON( pMstr->hIconDblClick ) ;
  328. #endif
  329. SAFE_DESTROYICON( pMstr->hIconDblClick[0]);
  330. SAFE_DESTROYICON( pMstr->hIconDblClick[1]);
  331. SetWindowLongPtr(pMstr->hDlg, DWLP_USER, 0);
  332. LocalFree((HGLOBAL)pMstr);
  333. }
  334. }
  335. ////////////////////////////////////////////////////////////////////////////
  336. //
  337. // ClickLockSettingsDlg
  338. //
  339. ////////////////////////////////////////////////////////////////////////////
  340. INT_PTR CALLBACK ClickLockSettingsDlg (
  341. HWND hDlg, // dialog window handle
  342. UINT msg, // message identifier
  343. WPARAM wParam, // primary parameter
  344. LPARAM lParam) // secondary parameter
  345. {
  346. static DWORD* pdwClickLockTime;
  347. static HICON hIcon = 0;
  348. switch (msg)
  349. {
  350. case WM_INITDIALOG:
  351. {
  352. WPARAM wSliderSetting; //ClickLock time in terms of slider units
  353. HourGlass (TRUE);
  354. Assert(lParam);
  355. pdwClickLockTime = (DWORD*) lParam; //Save Original value for return
  356. //Convert into slider units from milliseconds. Note that the slider
  357. //values get larger as the ClickLock time gets larger.
  358. wSliderSetting = (*pdwClickLockTime) / CLICKLOCK_TIME_FACTOR;
  359. //Make sure setting is within valid range for ClickLock slider
  360. wSliderSetting = max(wSliderSetting, CLICKLOCK_TIME_SLIDER_MIN);
  361. wSliderSetting = min(wSliderSetting, CLICKLOCK_TIME_SLIDER_MAX);
  362. SendDlgItemMessage (hDlg, IDT_CLICKLOCK_TIME_SETTINGS, TBM_SETRANGE,
  363. TRUE, MAKELONG(CLICKLOCK_TIME_SLIDER_MIN, CLICKLOCK_TIME_SLIDER_MAX));
  364. SendDlgItemMessage (hDlg, IDT_CLICKLOCK_TIME_SETTINGS, TBM_SETPAGESIZE,
  365. 0, TICKS_PER_CLICK); // click movement
  366. SendDlgItemMessage (hDlg, IDT_CLICKLOCK_TIME_SETTINGS, TBM_SETPOS,
  367. TRUE, (LPARAM)(LONG)wSliderSetting);
  368. //icon for the dialog
  369. // (saved in a static variable, and released on WM_DESTROY)
  370. hIcon = LoadIcon((HINSTANCE)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ),
  371. MAKEINTRESOURCE(ICON_CLICKLOCK));
  372. SendMessage( GetDlgItem (hDlg, MOUSE_CLICKICON),
  373. STM_SETICON, (WPARAM)hIcon, 0L );
  374. CenterDlgOverParent(hDlg); //Center dialog here so it doesn't jump around on screen
  375. HourGlass(FALSE);
  376. return(TRUE);
  377. }
  378. case WM_HSCROLL:
  379. {
  380. if (LOWORD(wParam) == TB_ENDTRACK)
  381. {
  382. DWORD dwClTime;
  383. int wSliderSetting = (int) SendMessage (GetDlgItem (hDlg, IDT_CLICKLOCK_TIME_SETTINGS),
  384. TBM_GETPOS, 0, 0L);
  385. dwClTime = wSliderSetting * CLICKLOCK_TIME_FACTOR;
  386. SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME,
  387. 0,
  388. (PVOID) (LOWORD(dwClTime)),
  389. 0);
  390. }
  391. }
  392. break;
  393. case WM_HELP: //F1
  394. {
  395. WinHelp( ((LPHELPINFO)lParam)->hItemHandle,
  396. HELP_FILE,
  397. HELP_WM_HELP,
  398. (DWORD_PTR)(LPTSTR)aMouseButHelpIds );
  399. }
  400. break;
  401. case WM_CONTEXTMENU: // Display simple "What's This?" menu
  402. {
  403. WinHelp( (HWND) wParam,
  404. HELP_FILE,
  405. HELP_CONTEXTMENU,
  406. (DWORD_PTR)(LPTSTR)aMouseButHelpIds );
  407. }
  408. break;
  409. case WM_DESTROY:
  410. SAFE_DESTROYICON(hIcon);
  411. break;
  412. case WM_COMMAND:
  413. switch(LOWORD(wParam))
  414. {
  415. case IDOK: // Flag to save setting
  416. {
  417. DWORD dwClickLockTime;
  418. int wSliderSetting = (int) SendMessage (GetDlgItem (hDlg, IDT_CLICKLOCK_TIME_SETTINGS),
  419. TBM_GETPOS, 0, 0L);
  420. //verify range
  421. wSliderSetting = max(wSliderSetting, CLICKLOCK_TIME_SLIDER_MIN);
  422. wSliderSetting = min(wSliderSetting, CLICKLOCK_TIME_SLIDER_MAX);
  423. // Convert to milliseconds from slider units.
  424. dwClickLockTime = wSliderSetting * CLICKLOCK_TIME_FACTOR;
  425. *pdwClickLockTime = dwClickLockTime;
  426. EndDialog(hDlg, IDOK);
  427. break;
  428. }
  429. case IDCANCEL: // revert to previous setting
  430. EndDialog(hDlg, IDCANCEL);
  431. break;
  432. default:
  433. return(FALSE);
  434. }
  435. return (TRUE);
  436. default:
  437. return(FALSE);
  438. }
  439. return (TRUE);
  440. }
  441. ////////////////////////////////////////////////////////////////////////////
  442. //
  443. // InitMouseButDlg
  444. //
  445. ////////////////////////////////////////////////////////////////////////////
  446. BOOL InitMouseButDlg(
  447. HWND hDlg)
  448. {
  449. SHELLSTATE shellstate = {0} ;
  450. PMOUSEBUTSTR pMstr = NULL;
  451. HINSTANCE hInstDlg = (HINSTANCE)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ) ;
  452. HWND hwndClickLockSettingsButton = GetDlgItem(hDlg, IDBTN_CLICKLOCK_SETTINGS);
  453. DWORD dwClickLockSetting = 0;
  454. HWND hwndDoubleClickTestArea = NULL;
  455. pMstr = (PMOUSEBUTSTR)LocalAlloc(LPTR , sizeof(MOUSEBUTSTR));
  456. if (pMstr == NULL)
  457. {
  458. return (TRUE);
  459. }
  460. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pMstr);
  461. pMstr->hDlg = hDlg;
  462. //
  463. //Set up the double click test area
  464. //
  465. pMstr->hWndDblClk_TestArea = GetDlgItem(hDlg, MOUSE_DBLCLK_TEST_AREA);
  466. GetWindowRect(pMstr->hWndDblClk_TestArea, &pMstr->DblClkRect);
  467. MapWindowPoints(NULL, hDlg, (LPPOINT) &pMstr->DblClkRect, 2);
  468. pMstr->hIconDblClick[0] = LoadIcon(hInstDlg, MAKEINTRESOURCE(ICON_FOLDER_CLOSED));
  469. pMstr->hIconDblClick[1] = LoadIcon(hInstDlg, MAKEINTRESOURCE(ICON_FOLDER_OPEN));
  470. SendMessage(pMstr->hWndDblClk_TestArea, STM_SETICON, (WPARAM)pMstr->hIconDblClick[0], 0L);
  471. //
  472. // Set (and get), then restore the state of the mouse buttons.
  473. //
  474. (pMstr->bOrigSwap) = (pMstr->bSwap) = SwapMouseButton(TRUE);
  475. SwapMouseButton(pMstr->bOrigSwap);
  476. #ifdef SHELL_SINGLE_CLICK
  477. //
  478. // Get shell single-click behavior:
  479. //
  480. SHGetSetSettings( &shellstate, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC, FALSE /*get*/ ) ;
  481. pMstr->bShellSingleClick =
  482. pMstr->bOrigShellSingleClick = shellstate.fWin95Classic ? FALSE :
  483. shellstate.fDoubleClickInWebView ? FALSE :
  484. TRUE ;
  485. pMstr->hIconSglClick = LoadIcon( hInstDlg, MAKEINTRESOURCE( IDI_SGLCLICK ) ) ;
  486. pMstr->hIconDblClick = LoadIcon( hInstDlg, MAKEINTRESOURCE( IDI_DBLCLICK ) ) ;
  487. ShellClick_UpdateUI( hDlg, pMstr ) ;
  488. #endif //SHELL_SINGLE_CLICK
  489. //
  490. // Initialize check/radio button state
  491. //
  492. ShowButtonState(pMstr);
  493. pMstr->OrigDblClkSpeed =
  494. pMstr->ClickSpeed = (SHORT) GetIntFromReg( HKEY_CURRENT_USER,
  495. szRegStr_Mouse,
  496. szDblClkSpeed,
  497. DBLCLICK_DEFAULT_TIME );
  498. pMstr->hWndDblClkScroll = GetDlgItem(hDlg, MOUSE_CLICKSCROLL);
  499. SendMessage( pMstr->hWndDblClkScroll,
  500. TBM_SETRANGE,
  501. 0,
  502. MAKELONG(DBLCLICK_TIME_SLIDER_MIN, DBLCLICK_TIME_SLIDER_MAX) );
  503. SendMessage( pMstr->hWndDblClkScroll,
  504. TBM_SETPOS,
  505. TRUE,
  506. (LONG) (DBLCLICK_TIME_TO_TICKS(pMstr->ClickSpeed)) );
  507. SetDoubleClickTime(pMstr->ClickSpeed);
  508. //
  509. //Get clicklock settings and set the checkbox
  510. //
  511. SystemParametersInfo(SPI_GETMOUSECLICKLOCK, 0, (PVOID)&dwClickLockSetting, 0);
  512. pMstr->bOrigClickLock = pMstr->bClickLock = (dwClickLockSetting) ? TRUE : FALSE;
  513. if ( pMstr->bClickLock )
  514. {
  515. CheckDlgButton (hDlg, IDCK_CLICKLOCK, BST_CHECKED);
  516. EnableWindow(hwndClickLockSettingsButton, TRUE);
  517. }
  518. else
  519. {
  520. CheckDlgButton (hDlg, IDCK_CLICKLOCK, BST_UNCHECKED);
  521. EnableWindow(hwndClickLockSettingsButton, FALSE);
  522. }
  523. // click lock speed
  524. {
  525. DWORD dwClTime = 0;
  526. SystemParametersInfo(SPI_GETMOUSECLICKLOCKTIME, 0, (PVOID)&dwClTime, 0);
  527. dwClTime = max(dwClTime, CLICKLOCK_TIME_SLIDER_MIN * CLICKLOCK_TIME_FACTOR);
  528. dwClTime = min(dwClTime, CLICKLOCK_TIME_SLIDER_MAX * CLICKLOCK_TIME_FACTOR);
  529. pMstr->dwOrigClickLockTime = pMstr->dwClickLockTime = dwClTime;
  530. }
  531. return (TRUE);
  532. }
  533. ////////////////////////////////////////////////////////////////////////////
  534. //
  535. // MouseButDlg
  536. //
  537. ////////////////////////////////////////////////////////////////////////////
  538. INT_PTR CALLBACK MouseButDlg(
  539. HWND hDlg,
  540. UINT message,
  541. WPARAM wParam,
  542. LPARAM lParam)
  543. {
  544. static int iTestIcon = 0; //index into hIconDblClick array
  545. PMOUSEBUTSTR pMstr = (PMOUSEBUTSTR)GetWindowLongPtr(hDlg, DWLP_USER);
  546. switch (message)
  547. {
  548. case ( WM_INITDIALOG ) :
  549. {
  550. iTestIcon = 0;
  551. return (InitMouseButDlg(hDlg));
  552. }
  553. case ( WM_DESTROY ) :
  554. {
  555. DestroyMouseButDlg(pMstr);
  556. break;
  557. }
  558. case ( WM_HSCROLL ) :
  559. {
  560. if ((HWND)lParam == pMstr->hWndDblClkScroll)
  561. {
  562. short temp = DBLCLICK_TICKS_TO_TIME((short)SendMessage( (HWND)lParam,
  563. TBM_GETPOS,
  564. 0,
  565. 0L ));
  566. if (temp != pMstr->ClickSpeed)
  567. {
  568. pMstr->ClickSpeed = temp;
  569. SetDoubleClickTime(pMstr->ClickSpeed);
  570. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  571. }
  572. }
  573. break;
  574. }
  575. case ( WM_RBUTTONDBLCLK ) :
  576. case ( WM_LBUTTONDBLCLK ) :
  577. {
  578. POINT point = { (int)MAKEPOINTS(lParam).x,
  579. (int)MAKEPOINTS(lParam).y };
  580. if (PtInRect(&pMstr->DblClkRect, point))
  581. {
  582. iTestIcon ^= 1;
  583. SendMessage(pMstr->hWndDblClk_TestArea, STM_SETICON,
  584. (WPARAM)pMstr->hIconDblClick[iTestIcon], 0L);
  585. }
  586. break;
  587. }
  588. case ( WM_COMMAND ) :
  589. {
  590. switch (LOWORD(wParam))
  591. {
  592. case ( IDCK_CLICKLOCK ) :
  593. {
  594. HWND hwndClickLockSettingsButton = GetDlgItem(hDlg, IDBTN_CLICKLOCK_SETTINGS);
  595. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  596. pMstr->bClickLock = !(pMstr->bClickLock);
  597. // update control(s) appearance
  598. CheckDlgButton (hDlg, IDCK_CLICKLOCK, ( pMstr->bClickLock ) ? BST_CHECKED : BST_UNCHECKED);
  599. EnableWindow(hwndClickLockSettingsButton, ( pMstr->bClickLock ) ? TRUE : FALSE);
  600. SystemParametersInfo(SPI_SETMOUSECLICKLOCK,
  601. 0,
  602. IntToPtr(pMstr->bClickLock),
  603. 0);
  604. break;
  605. }
  606. case ( IDBTN_CLICKLOCK_SETTINGS ) :
  607. {
  608. LPARAM lRet;
  609. UINT code = HIWORD(wParam);
  610. DWORD dwTempClickLockTime = pMstr->dwClickLockTime;
  611. if (code == BN_CLICKED)
  612. {
  613. lRet = DialogBoxParam ((HINSTANCE)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ),
  614. MAKEINTRESOURCE(IDD_CLICKLOCK_SETTINGS_DLG ),
  615. GetParent (hDlg),
  616. ClickLockSettingsDlg,
  617. (LPARAM) &dwTempClickLockTime);
  618. if (lRet == IDOK &&
  619. pMstr->dwClickLockTime != dwTempClickLockTime)
  620. {
  621. pMstr->dwClickLockTime = dwTempClickLockTime;
  622. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  623. }
  624. else if (lRet == IDCANCEL)
  625. {
  626. //set back
  627. DWORD dwClTime = pMstr->dwClickLockTime;
  628. SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME,
  629. 0,
  630. IntToPtr(LOWORD(dwClTime)),
  631. 0);
  632. }
  633. }
  634. break;
  635. }
  636. case ( IDBTN_BUTTONSWAP) :
  637. {
  638. pMstr->bSwap = !pMstr->bSwap;
  639. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  640. SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP,
  641. pMstr->bSwap,
  642. NULL,
  643. 0);
  644. ShowButtonState(pMstr);
  645. }
  646. #ifdef SHELL_SINGLE_CLICK
  647. case ( MOUSE_SGLCLICK ) :
  648. case ( MOUSE_DBLCLICK ) :
  649. {
  650. if( pMstr->bShellSingleClick != (MOUSE_SGLCLICK == LOWORD(wParam)) )
  651. {
  652. pMstr->bShellSingleClick = (MOUSE_SGLCLICK == LOWORD(wParam)) ;
  653. ShellClick_UpdateUI( hDlg, pMstr ) ;
  654. SendMessage( GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L ) ;
  655. }
  656. break ;
  657. }
  658. #endif // SHELL_SINGLE_CLICK
  659. }
  660. break;
  661. }
  662. case ( WM_NOTIFY ) :
  663. {
  664. switch (((NMHDR *)lParam)->code)
  665. {
  666. case ( PSN_APPLY ) :
  667. {
  668. HourGlass(TRUE);
  669. //
  670. // Apply Button Swap setting.
  671. //
  672. if (pMstr->bSwap != pMstr->bOrigSwap)
  673. {
  674. SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP,
  675. pMstr->bSwap,
  676. NULL,
  677. SPIF_UPDATEINIFILE |
  678. SPIF_SENDWININICHANGE );
  679. pMstr->bOrigSwap = pMstr->bSwap;
  680. }
  681. //
  682. // Apply DoubleClickTime setting.
  683. //
  684. if (pMstr->ClickSpeed != pMstr->OrigDblClkSpeed)
  685. {
  686. SystemParametersInfo( SPI_SETDOUBLECLICKTIME,
  687. pMstr->ClickSpeed,
  688. NULL,
  689. SPIF_UPDATEINIFILE |
  690. SPIF_SENDWININICHANGE );
  691. pMstr->OrigDblClkSpeed = pMstr->ClickSpeed;
  692. }
  693. //
  694. // Apply ClickLock setting.
  695. //
  696. if (pMstr->bClickLock != pMstr->bOrigClickLock)
  697. {
  698. SystemParametersInfo(SPI_SETMOUSECLICKLOCK,
  699. 0,
  700. IntToPtr(pMstr->bClickLock),
  701. SPIF_UPDATEINIFILE |
  702. SPIF_SENDWININICHANGE);
  703. pMstr->bOrigClickLock = pMstr->bClickLock;
  704. }
  705. //
  706. // Apply ClickLockTime setting.
  707. //
  708. if (pMstr->dwClickLockTime != pMstr->dwOrigClickLockTime)
  709. {
  710. SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME,
  711. 0,
  712. (PVOID) (LOWORD(pMstr->dwClickLockTime)),
  713. SPIF_UPDATEINIFILE |
  714. SPIF_SENDWININICHANGE );
  715. pMstr->dwOrigClickLockTime = pMstr->dwClickLockTime;
  716. }
  717. #ifdef SHELL_SINGLE_CLICK
  718. if( pMstr->bOrigShellSingleClick != pMstr->bShellSingleClick )
  719. {
  720. SHELLSTATE shellstate = {0} ;
  721. ULONG dwFlags = SSF_DOUBLECLICKINWEBVIEW ;
  722. shellstate.fWin95Classic =
  723. shellstate.fDoubleClickInWebView = !pMstr->bShellSingleClick ;
  724. // update the WIN95CLASSIC member only if we've chosen single-click.
  725. if( pMstr->bShellSingleClick )
  726. dwFlags |= SSF_WIN95CLASSIC ;
  727. SHGetSetSettings( &shellstate, dwFlags, TRUE ) ;
  728. ShellClick_Refresh( pMstr ) ;
  729. pMstr->bOrigShellSingleClick = pMstr->bShellSingleClick ;
  730. }
  731. #endif //SHELL_SINGLE_CLICK
  732. HourGlass(FALSE);
  733. break;
  734. }
  735. case ( PSN_RESET ) :
  736. {
  737. //
  738. // Reset Button Swap setting.
  739. //
  740. if (pMstr->bSwap != pMstr->bOrigSwap)
  741. {
  742. SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP,
  743. pMstr->bOrigSwap,
  744. NULL,
  745. 0);
  746. }
  747. //
  748. // Reset DoubleClickTime setting.
  749. //
  750. if (pMstr->ClickSpeed != pMstr->OrigDblClkSpeed)
  751. {
  752. SystemParametersInfo( SPI_SETDOUBLECLICKTIME,
  753. pMstr->OrigDblClkSpeed,
  754. NULL,
  755. 0);
  756. }
  757. //
  758. // Reset ClickLock setting.
  759. //
  760. if (pMstr->bClickLock != pMstr->bOrigClickLock)
  761. {
  762. SystemParametersInfo(SPI_SETMOUSECLICKLOCK,
  763. 0,
  764. IntToPtr(pMstr->bOrigClickLock),
  765. 0);
  766. }
  767. //
  768. // Reset ClickLockTime setting.
  769. //
  770. if (pMstr->dwClickLockTime != pMstr->dwOrigClickLockTime)
  771. {
  772. SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME,
  773. 0,
  774. (PVOID) (LOWORD(pMstr->dwOrigClickLockTime)),
  775. 0);
  776. }
  777. #ifdef SHELL_SINGLE_CLICK
  778. if( pMstr->bOrigShellSingleClick != pMstr->bShellSingleClick )
  779. {
  780. SHELLSTATE shellstate = {0} ;
  781. ULONG dwFlags = SSF_DOUBLECLICKINWEBVIEW ;
  782. shellstate.fWin95Classic =
  783. shellstate.fDoubleClickInWebView = !pMstr->bOrigShellSingleClick ;
  784. // update the WIN95CLASSIC member only if we've chosen single-click.
  785. if( pMstr->bShellSingleClick )
  786. dwFlags |= SSF_WIN95CLASSIC ;
  787. SHGetSetSettings( &shellstate, dwFlags, TRUE ) ;
  788. ShellClick_Refresh( pMstr ) ;
  789. pMstr->bShellSingleClick = pMstr->bOrigShellSingleClick ;
  790. }
  791. #endif //SHELL_SINGLE_CLICK
  792. break;
  793. }
  794. default :
  795. {
  796. return (FALSE);
  797. }
  798. }
  799. break;
  800. }
  801. case ( WM_HELP ) : // F1
  802. {
  803. WinHelp( ((LPHELPINFO)lParam)->hItemHandle,
  804. HELP_FILE,
  805. HELP_WM_HELP,
  806. (DWORD_PTR)(LPTSTR)aMouseButHelpIds );
  807. break;
  808. }
  809. case ( WM_CONTEXTMENU ) : // right mouse click
  810. {
  811. WinHelp( (HWND) wParam,
  812. HELP_FILE,
  813. HELP_CONTEXTMENU,
  814. (DWORD_PTR)(LPTSTR)aMouseButHelpIds );
  815. break;
  816. }
  817. case ( WM_DISPLAYCHANGE ) :
  818. case ( WM_WININICHANGE ) :
  819. case ( WM_SYSCOLORCHANGE ) :
  820. {
  821. SHPropagateMessage(hDlg, message, wParam, lParam, TRUE);
  822. return TRUE;
  823. }
  824. default :
  825. {
  826. return (FALSE);
  827. }
  828. }
  829. return (TRUE);
  830. }
  831. #ifdef SHELL_SINGLE_CLICK
  832. ////////////////////////////////////////////////////////////////////////////
  833. //
  834. // ShellClick_UpdateUI
  835. //
  836. // Assigns the appropriate icon for shell single/double click
  837. //
  838. ////////////////////////////////////////////////////////////////////////////
  839. void ShellClick_UpdateUI(
  840. HWND hDlg,
  841. PMOUSEBUTSTR pMstr)
  842. {
  843. HICON hicon = pMstr->bShellSingleClick ? pMstr->hIconSglClick :
  844. pMstr->hIconDblClick ;
  845. SendMessage( GetDlgItem( hDlg, MOUSE_CLICKICON ), STM_SETICON,
  846. (WPARAM)hicon, 0L ) ;
  847. }
  848. #endif //SHELL_SINGLE_CLICK
  849. ////////////////////////////////////////////////////////////////////////////
  850. //
  851. // IsShellWindow
  852. //
  853. // Determines whether the specified window is a shell folder window.
  854. //
  855. ////////////////////////////////////////////////////////////////////////////
  856. #define c_szExploreClass TEXT("ExploreWClass")
  857. #define c_szIExploreClass TEXT("IEFrame")
  858. #ifdef IE3CLASSNAME
  859. #define c_szCabinetClass TEXT("IEFrame")
  860. #else
  861. #define c_szCabinetClass TEXT("CabinetWClass")
  862. #endif
  863. BOOL IsShellWindow( HWND hwnd )
  864. {
  865. TCHAR szClass[32];
  866. GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  867. return (lstrcmp(szClass, c_szCabinetClass) == 0) ||
  868. (lstrcmp(szClass, c_szExploreClass) == 0) ||
  869. (lstrcmp(szClass, c_szIExploreClass) == 0) ;
  870. }
  871. //The following value is taken from shdocvw\rcids.h
  872. #ifndef FCIDM_REFRESH
  873. #define FCIDM_REFRESH 0xA220
  874. #endif // FCIDM_REFRESH
  875. ////////////////////////////////////////////////////////////////////////////
  876. //
  877. // ShellClick_RefreshEnumProc
  878. //
  879. // EnumWindow callback for shell refresh.
  880. //
  881. ////////////////////////////////////////////////////////////////////////////
  882. BOOL CALLBACK ShellClick_RefreshEnumProc( HWND hwnd, LPARAM lParam )
  883. {
  884. if( IsShellWindow(hwnd) )
  885. PostMessage(hwnd, WM_COMMAND, FCIDM_REFRESH, 0L);
  886. return(TRUE);
  887. }
  888. ////////////////////////////////////////////////////////////////////////////
  889. //
  890. // ShellClick_Refresh
  891. //
  892. // Re-renders the contents of all shell folder windows.
  893. //
  894. ////////////////////////////////////////////////////////////////////////////
  895. void ShellClick_Refresh( PMOUSEBUTSTR pMstr )
  896. {
  897. HWND hwndDesktop = FindWindowEx(NULL, NULL, TEXT(STR_DESKTOPCLASS), NULL);
  898. if( NULL != hwndDesktop )
  899. PostMessage( hwndDesktop, WM_COMMAND, FCIDM_REFRESH, 0L );
  900. EnumWindows( ShellClick_RefreshEnumProc, 0L ) ;
  901. }