Source code of Windows XP (NT5)
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.

1009 lines
25 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. // Global Variables.
  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. //
  28. // Constant Declarations.
  29. //
  30. //
  31. // SwapMouseButtons takes:
  32. // TRUE to make it a right mouse
  33. // FALSE to make it a left mouse
  34. //
  35. #define RIGHT TRUE
  36. #define LEFT FALSE
  37. #define CLICKMIN 100 // milliseconds
  38. #define CLICKMAX 900
  39. #define CLICKSUM (CLICKMIN + CLICKMAX)
  40. #define CLICKRANGE (CLICKMAX - CLICKMIN)
  41. //
  42. // From shell\inc\shsemip.h
  43. //
  44. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  45. #define Assert(f)
  46. //
  47. // Typedef Declarations.
  48. //
  49. typedef struct tag_MouseGenStr
  50. {
  51. BOOL bSwap;
  52. BOOL bOrigSwap;
  53. short ClickSpeed;
  54. short OrigDblClkSpeed;
  55. HWND hWndDblClkScroll;
  56. HWND hDlg; // HWND hMouseButDlg;
  57. RECT OrigRect;
  58. RECT DblClkRect;
  59. POINT ObjectPoint;
  60. POINT SelectPoint;
  61. int jackstate, jackhits; // for jack-in-the-box control
  62. int jackignore; // for jack-in-the-box control
  63. BOOL bShellSingleClick,
  64. bOrigShellSingleClick ;
  65. HICON hIconSglClick,
  66. hIconDblClick ;
  67. } MOUSEBUTSTR, *PMOUSEBUTSTR, *LPMOUSEBUTSTR;
  68. //
  69. // Context Help Ids.
  70. //
  71. const DWORD aMouseButHelpIds[] =
  72. {
  73. IDC_GROUPBOX_1, IDH_COMM_GROUPBOX,
  74. IDC_GROUPBOX_2, IDH_DLGMOUSE_HANDED_PIC,
  75. IDC_GROUPBOX_3, IDH_DLGMOUSE_HANDED_PIC,
  76. IDC_GROUPBOX_4, IDH_COMM_GROUPBOX,
  77. IDC_SELECTDRAG, IDH_DLGMOUSE_HANDED_PIC,
  78. IDC_OBJECTMENU, IDH_DLGMOUSE_HANDED_PIC,
  79. MOUSE_LEFTHAND, IDH_DLGMOUSE_LEFT,
  80. MOUSE_RIGHTHAND, IDH_DLGMOUSE_RIGHT,
  81. MOUSE_SELECTBMP, IDH_DLGMOUSE_HANDED_PIC,
  82. MOUSE_MOUSEBMP, IDH_DLGMOUSE_HANDED_PIC,
  83. MOUSE_MENUBMP, IDH_DLGMOUSE_HANDED_PIC,
  84. MOUSE_CLICKSCROLL, IDH_DLGMOUSE_DOUBCLICK,
  85. IDC_GROUPBOX_5, IDH_DLGMOUSE_DCLICK_PIC,
  86. MOUSE_DBLCLKBMP, IDH_DLGMOUSE_DCLICK_PIC,
  87. MOUSE_SGLCLICK, IDH_MOUSE_SGLCLICK,
  88. MOUSE_DBLCLICK, IDH_MOUSE_DBLCLICK,
  89. 0, 0
  90. };
  91. //
  92. // helper function prototypes
  93. //
  94. void ShellClick_UpdateUI( HWND hDlg, PMOUSEBUTSTR pMstr) ;
  95. void ShellClick_Refresh( PMOUSEBUTSTR pMstr ) ;
  96. //
  97. // Debug Info.
  98. //
  99. #ifdef DEBUG
  100. #define REG_INTEGER 1000
  101. int fTraceRegAccess = 0;
  102. void RegDetails(
  103. int iWrite,
  104. HKEY hk,
  105. LPCTSTR lpszSubKey,
  106. LPCTSTR lpszValueName,
  107. DWORD dwType,
  108. LPTSTR lpszString,
  109. int iValue)
  110. {
  111. TCHAR Buff[256];
  112. TCHAR *lpszReadWrite[] = { TEXT("DESK.CPL:Read"), TEXT("DESK.CPL:Write") };
  113. if (!fTraceRegAccess)
  114. {
  115. return;
  116. }
  117. switch (dwType)
  118. {
  119. case ( REG_SZ ) :
  120. {
  121. wsprintf( Buff,
  122. TEXT("%s String:hk=%#08lx, %s:%s=%s\n\r"),
  123. lpszReadWrite[iWrite],
  124. hk,
  125. lpszSubKey,
  126. lpszValueName,
  127. lpszString );
  128. break;
  129. }
  130. case ( REG_INTEGER ) :
  131. {
  132. wsprintf( Buff,
  133. TEXT("%s int:hk=%#08lx, %s:%s=%d\n\r"),
  134. lpszReadWrite[iWrite],
  135. hk,
  136. lpszSubKey,
  137. lpszValueName,
  138. iValue );
  139. break;
  140. }
  141. case ( REG_BINARY ) :
  142. {
  143. wsprintf( Buff,
  144. TEXT("%s Binary:hk=%#08lx, %s:%s=%#0lx;DataSize:%d\r\n"),
  145. lpszReadWrite[iWrite],
  146. hk,
  147. lpszSubKey,
  148. lpszValueName,
  149. lpszString,
  150. iValue );
  151. break;
  152. }
  153. }
  154. OutputDebugString(Buff);
  155. }
  156. #endif // DEBUG
  157. ////////////////////////////////////////////////////////////////////////////
  158. //
  159. // GetIntFromSubKey
  160. //
  161. // hKey is the handle to the subkey (already pointing to the proper
  162. // location.
  163. //
  164. ////////////////////////////////////////////////////////////////////////////
  165. int GetIntFromSubkey(
  166. HKEY hKey,
  167. LPCTSTR lpszValueName,
  168. int iDefault)
  169. {
  170. TCHAR szValue[20];
  171. DWORD dwSizeofValueBuff = sizeof(szValue);
  172. DWORD dwType;
  173. int iRetValue = iDefault;
  174. if ((RegQueryValueEx( hKey,
  175. (LPTSTR)lpszValueName,
  176. NULL,
  177. &dwType,
  178. (LPBYTE)szValue,
  179. &dwSizeofValueBuff ) == ERROR_SUCCESS) &&
  180. (dwSizeofValueBuff))
  181. {
  182. //
  183. // BOGUS: This handles only the string type entries now!
  184. //
  185. if (dwType == REG_SZ)
  186. {
  187. iRetValue = (int)StrToLong(szValue);
  188. }
  189. #ifdef DEBUG
  190. else
  191. {
  192. OutputDebugString(TEXT("String type expected from Registry\n\r"));
  193. }
  194. #endif
  195. }
  196. #ifdef DEBUG
  197. RegDetails(0, hKey, TEXT(""), lpszValueName, REG_INTEGER, NULL, iRetValue);
  198. #endif
  199. return (iRetValue);
  200. }
  201. ////////////////////////////////////////////////////////////////////////////
  202. //
  203. // GetIntFromReg
  204. //
  205. // Opens the given subkey and gets the int value.
  206. //
  207. ////////////////////////////////////////////////////////////////////////////
  208. int GetIntFromReg(
  209. HKEY hKey,
  210. LPCTSTR lpszSubkey,
  211. LPCTSTR lpszNameValue,
  212. int iDefault)
  213. {
  214. HKEY hk;
  215. int iRetValue = iDefault;
  216. //
  217. // See if the key is present.
  218. //
  219. if (RegOpenKey(hKey, lpszSubkey, &hk) == ERROR_SUCCESS)
  220. {
  221. iRetValue = GetIntFromSubkey(hk, lpszNameValue, iDefault);
  222. RegCloseKey(hk);
  223. }
  224. return (iRetValue);
  225. }
  226. ////////////////////////////////////////////////////////////////////////////
  227. //
  228. // GetStringFromReg
  229. //
  230. // Opens the given subkey and gets the string value.
  231. //
  232. ////////////////////////////////////////////////////////////////////////////
  233. BOOL GetStringFromReg(
  234. HKEY hKey,
  235. LPCTSTR lpszSubkey,
  236. LPCTSTR lpszValueName,
  237. LPCTSTR lpszDefault,
  238. LPTSTR lpszValue,
  239. DWORD dwSizeofValueBuff)
  240. {
  241. HKEY hk;
  242. DWORD dwType;
  243. BOOL fSuccess = FALSE;
  244. //
  245. // See if the key is present.
  246. //
  247. if (RegOpenKey(hKey, lpszSubkey, &hk) == ERROR_SUCCESS)
  248. {
  249. if ((RegQueryValueEx( hk,
  250. (LPTSTR)lpszValueName,
  251. NULL,
  252. &dwType,
  253. (LPBYTE)lpszValue,
  254. &dwSizeofValueBuff ) == ERROR_SUCCESS) &&
  255. (dwSizeofValueBuff))
  256. {
  257. //
  258. // BOGUS: This handles only the string type entries now!
  259. //
  260. #ifdef DEBUG
  261. if (dwType != REG_SZ)
  262. {
  263. OutputDebugString(TEXT("String type expected from Registry\n\r"));
  264. }
  265. else
  266. #endif
  267. fSuccess = TRUE;
  268. }
  269. RegCloseKey(hk);
  270. }
  271. //
  272. // If failure, use the default string.
  273. //
  274. if (!fSuccess)
  275. {
  276. lstrcpy(lpszValue, lpszDefault);
  277. }
  278. #ifdef DEBUG
  279. RegDetails(0, hKey, lpszSubkey, lpszValueName, REG_SZ, lpszValue, 0);
  280. #endif
  281. return (fSuccess);
  282. }
  283. ////////////////////////////////////////////////////////////////////////////
  284. //
  285. // UpdateRegistry
  286. //
  287. // This updates a given value of any data type at a given location in
  288. // the registry.
  289. //
  290. // The value name is passed in as an Id to a string in USER's String
  291. // table.
  292. //
  293. ////////////////////////////////////////////////////////////////////////////
  294. BOOL UpdateRegistry(
  295. HKEY hKey,
  296. LPCTSTR lpszSubkey,
  297. LPCTSTR lpszValueName,
  298. DWORD dwDataType,
  299. LPVOID lpvData,
  300. DWORD dwDataSize)
  301. {
  302. HKEY hk;
  303. if (RegCreateKey(hKey, lpszSubkey, &hk) == ERROR_SUCCESS)
  304. {
  305. RegSetValueEx( hk,
  306. (LPTSTR)lpszValueName,
  307. 0,
  308. dwDataType,
  309. (LPBYTE)lpvData,
  310. dwDataSize );
  311. #ifdef DEBUG
  312. RegDetails(1, hKey, lpszSubkey, lpszValueName, dwDataType, lpvData, (int)dwDataSize);
  313. #endif
  314. RegCloseKey(hk);
  315. return (TRUE);
  316. }
  317. return (FALSE);
  318. }
  319. ////////////////////////////////////////////////////////////////////////////
  320. //
  321. // ShowButtonState
  322. //
  323. // Swaps the menu and selection bitmaps.
  324. //
  325. ////////////////////////////////////////////////////////////////////////////
  326. void ShowButtonState(
  327. PMOUSEBUTSTR pMstr)
  328. {
  329. HWND hDlg;
  330. Assert(pMstr);
  331. hDlg = pMstr->hDlg;
  332. MouseControlSetSwap(GetDlgItem(hDlg, MOUSE_MOUSEBMP), pMstr->bSwap);
  333. SetWindowPos( GetDlgItem(hDlg, pMstr->bSwap ? IDC_SELECTDRAG : IDC_OBJECTMENU),
  334. NULL,
  335. pMstr->ObjectPoint.x,
  336. pMstr->ObjectPoint.y,
  337. 0,
  338. 0,
  339. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
  340. SetWindowPos( GetDlgItem(hDlg, !pMstr->bSwap ? IDC_SELECTDRAG : IDC_OBJECTMENU),
  341. NULL,
  342. pMstr->SelectPoint.x,
  343. pMstr->SelectPoint.y,
  344. 0,
  345. 0,
  346. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
  347. CheckDlgButton(hDlg, MOUSE_RIGHTHAND, !pMstr->bSwap);
  348. CheckDlgButton(hDlg, MOUSE_LEFTHAND, pMstr->bSwap);
  349. CheckDlgButton(hDlg, MOUSE_SGLCLICK, pMstr->bShellSingleClick);
  350. CheckDlgButton(hDlg, MOUSE_DBLCLICK, !pMstr->bShellSingleClick);
  351. }
  352. ////////////////////////////////////////////////////////////////////////////
  353. //
  354. // DestroyMouseButDlg
  355. //
  356. ////////////////////////////////////////////////////////////////////////////
  357. #define SAFE_DESTROYICON(hicon) if (hicon) { DestroyIcon(hicon); hicon=NULL; }
  358. void DestroyMouseButDlg(
  359. PMOUSEBUTSTR pMstr)
  360. {
  361. if (pMstr)
  362. {
  363. SAFE_DESTROYICON( pMstr->hIconSglClick ) ;
  364. SAFE_DESTROYICON( pMstr->hIconDblClick )
  365. SetWindowLongPtr(pMstr->hDlg, DWLP_USER, 0);
  366. LocalFree((HGLOBAL)pMstr);
  367. }
  368. }
  369. ////////////////////////////////////////////////////////////////////////////
  370. //
  371. // Jack stuff -- code to manage the jack-in-the-box double-click testbox.
  372. //
  373. ////////////////////////////////////////////////////////////////////////////
  374. typedef struct
  375. {
  376. int first; // first frame of state
  377. int last; // last frame of state
  378. int repeat; // state's repeat count
  379. } JACKSTATE;
  380. #define JACK_OPPOSITE_STATE (-2)
  381. #define JACK_NEXT_STATE (-1)
  382. #define JACK_CRANKING ( 0)
  383. #define JACK_OPENING ( 1)
  384. #define JACK_BOUNCING ( 2)
  385. #define JACK_CLOSING ( 3)
  386. //
  387. // NOTE: Every state starts with a key frame in the AVI file.
  388. //
  389. JACKSTATE JackFSA[] =
  390. {
  391. { 0, 7, -1 }, // cranking
  392. { 8, 12, 1 }, // opening
  393. { 16, 23, -1 }, // bouncing
  394. { 24, 27, 1 }, // closing
  395. };
  396. #define JACK_NUM_STATES (sizeof(JackFSA) / sizeof(JACKSTATE))
  397. ////////////////////////////////////////////////////////////////////////////
  398. //
  399. // JackSetState
  400. //
  401. ////////////////////////////////////////////////////////////////////////////
  402. void JackSetState(
  403. HWND dlg,
  404. PMOUSEBUTSTR mstr,
  405. int index)
  406. {
  407. JACKSTATE *state;
  408. switch (index)
  409. {
  410. case ( JACK_OPPOSITE_STATE ) :
  411. {
  412. mstr->jackstate++;
  413. // fall thru...
  414. }
  415. case ( JACK_NEXT_STATE ) :
  416. {
  417. index = mstr->jackstate + 1;
  418. }
  419. }
  420. index %= JACK_NUM_STATES;
  421. state = JackFSA + index;
  422. mstr->jackstate = index;
  423. mstr->jackignore++;
  424. Animate_Play( GetDlgItem(dlg, MOUSE_DBLCLKBMP),
  425. state->first,
  426. state->last,
  427. state->repeat );
  428. }
  429. ////////////////////////////////////////////////////////////////////////////
  430. //
  431. // JackClicked
  432. //
  433. ////////////////////////////////////////////////////////////////////////////
  434. void JackClicked(
  435. HWND dlg,
  436. PMOUSEBUTSTR mstr)
  437. {
  438. JACKSTATE *state = JackFSA + mstr->jackstate;
  439. if (state->repeat < 0)
  440. {
  441. JackSetState(dlg, mstr, JACK_NEXT_STATE);
  442. }
  443. else
  444. {
  445. mstr->jackhits++;
  446. }
  447. }
  448. ////////////////////////////////////////////////////////////////////////////
  449. //
  450. // JackStopped
  451. //
  452. ////////////////////////////////////////////////////////////////////////////
  453. void JackStopped(
  454. HWND dlg,
  455. PMOUSEBUTSTR mstr)
  456. {
  457. if (--mstr->jackignore < 0)
  458. {
  459. JACKSTATE *state = JackFSA + mstr->jackstate;
  460. if (state->repeat > 0)
  461. {
  462. int index;
  463. if (mstr->jackhits)
  464. {
  465. mstr->jackhits--;
  466. index = JACK_OPPOSITE_STATE;
  467. }
  468. else
  469. {
  470. index = JACK_NEXT_STATE;
  471. }
  472. JackSetState(dlg, mstr, index);
  473. }
  474. }
  475. }
  476. ////////////////////////////////////////////////////////////////////////////
  477. //
  478. // JackStart
  479. //
  480. ////////////////////////////////////////////////////////////////////////////
  481. void JackStart(
  482. HWND dlg,
  483. PMOUSEBUTSTR mstr)
  484. {
  485. mstr->jackhits = 0;
  486. mstr->jackstate = 0;
  487. mstr->jackignore = -1;
  488. Animate_Open( GetDlgItem(dlg, MOUSE_DBLCLKBMP),
  489. MAKEINTRESOURCE(IDA_JACKNBOX) );
  490. JackSetState(dlg, mstr, JACK_CRANKING);
  491. }
  492. ////////////////////////////////////////////////////////////////////////////
  493. //
  494. // InitMouseButDlg
  495. //
  496. ////////////////////////////////////////////////////////////////////////////
  497. BOOL InitMouseButDlg(
  498. HWND hDlg)
  499. {
  500. POINT Origin;
  501. SHELLSTATE shellstate = {0} ;
  502. PMOUSEBUTSTR pMstr;
  503. RECT TmpRect;
  504. HINSTANCE hInstDlg = (HINSTANCE)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ) ;
  505. pMstr = (PMOUSEBUTSTR)LocalAlloc(LPTR , sizeof(MOUSEBUTSTR));
  506. if (pMstr == NULL)
  507. {
  508. return (TRUE);
  509. }
  510. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pMstr);
  511. pMstr->hDlg = hDlg;
  512. Origin.x = Origin.y = 0;
  513. ClientToScreen(hDlg, (LPPOINT)&Origin);
  514. GetWindowRect(hDlg, &pMstr->OrigRect);
  515. pMstr->OrigRect.left -= Origin.x;
  516. pMstr->OrigRect.right -= Origin.x;
  517. GetWindowRect(GetDlgItem(hDlg, MOUSE_DBLCLKBMP), &pMstr->DblClkRect);
  518. pMstr->DblClkRect.top -= Origin.y;
  519. pMstr->DblClkRect.bottom -= Origin.y;
  520. pMstr->DblClkRect.left -= Origin.x;
  521. pMstr->DblClkRect.right -= Origin.x;
  522. //
  523. // Find position of Select and Object windows.
  524. //
  525. GetWindowRect(GetDlgItem(hDlg, IDC_SELECTDRAG), &TmpRect);
  526. ScreenToClient(hDlg, (POINT *)&TmpRect);
  527. pMstr->SelectPoint.x = TmpRect.left;
  528. pMstr->SelectPoint.y = TmpRect.top;
  529. GetWindowRect(GetDlgItem(hDlg, IDC_OBJECTMENU), &TmpRect);
  530. ScreenToClient(hDlg, (POINT *)&TmpRect);
  531. pMstr->ObjectPoint.x = TmpRect.left;
  532. pMstr->ObjectPoint.y = TmpRect.top;
  533. //
  534. // Set (and get), then restore the state of the mouse buttons.
  535. //
  536. (pMstr->bOrigSwap) = (pMstr->bSwap) = SwapMouseButton(TRUE);
  537. SwapMouseButton(pMstr->bOrigSwap);
  538. //
  539. // Get shell single-click behavior:
  540. //
  541. SHGetSetSettings( &shellstate, SSF_DOUBLECLICKINWEBVIEW | SSF_WIN95CLASSIC, FALSE /*get*/ ) ;
  542. pMstr->bShellSingleClick =
  543. pMstr->bOrigShellSingleClick = shellstate.fWin95Classic ? FALSE :
  544. shellstate.fDoubleClickInWebView ? FALSE :
  545. TRUE ;
  546. pMstr->hIconSglClick = LoadIcon( hInstDlg, MAKEINTRESOURCE( IDI_SGLCLICK ) ) ;
  547. pMstr->hIconDblClick = LoadIcon( hInstDlg, MAKEINTRESOURCE( IDI_DBLCLICK ) ) ;
  548. ShellClick_UpdateUI( hDlg, pMstr ) ;
  549. //
  550. // Initialize check/radio button state
  551. //
  552. ShowButtonState(pMstr);
  553. pMstr->OrigDblClkSpeed =
  554. pMstr->ClickSpeed = (SHORT) GetIntFromReg( HKEY_CURRENT_USER,
  555. szRegStr_Mouse,
  556. szDblClkSpeed,
  557. CLICKMIN + (CLICKRANGE / 2) );
  558. pMstr->hWndDblClkScroll = GetDlgItem(hDlg, MOUSE_CLICKSCROLL);
  559. SendMessage( pMstr->hWndDblClkScroll,
  560. TBM_SETRANGE,
  561. 0,
  562. MAKELONG(CLICKMIN, CLICKMAX) );
  563. SendMessage( pMstr->hWndDblClkScroll,
  564. TBM_SETPOS,
  565. TRUE,
  566. (LONG)(CLICKMIN + CLICKMAX - pMstr->ClickSpeed) );
  567. SetDoubleClickTime(pMstr->ClickSpeed);
  568. JackStart(hDlg, pMstr);
  569. return (TRUE);
  570. }
  571. ////////////////////////////////////////////////////////////////////////////
  572. //
  573. // MouseButDlg
  574. //
  575. ////////////////////////////////////////////////////////////////////////////
  576. INT_PTR CALLBACK MouseButDlg(
  577. HWND hDlg,
  578. UINT message,
  579. WPARAM wParam,
  580. LPARAM lParam)
  581. {
  582. PMOUSEBUTSTR pMstr = (PMOUSEBUTSTR)GetWindowLongPtr(hDlg, DWLP_USER);
  583. switch (message)
  584. {
  585. case ( WM_INITDIALOG ) :
  586. {
  587. return (InitMouseButDlg(hDlg));
  588. }
  589. case ( WM_DESTROY ) :
  590. {
  591. DestroyMouseButDlg(pMstr);
  592. break;
  593. }
  594. case ( WM_HSCROLL ) :
  595. {
  596. if ((HWND)lParam == pMstr->hWndDblClkScroll)
  597. {
  598. short temp = CLICKMIN + CLICKMAX -
  599. (short)SendMessage( (HWND)lParam,
  600. TBM_GETPOS,
  601. 0,
  602. 0L );
  603. if (temp != pMstr->ClickSpeed)
  604. {
  605. pMstr->ClickSpeed = temp;
  606. SetDoubleClickTime(pMstr->ClickSpeed);
  607. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  608. }
  609. }
  610. break;
  611. }
  612. case ( WM_RBUTTONDBLCLK ) :
  613. case ( WM_LBUTTONDBLCLK ) :
  614. {
  615. POINT point = { (int)MAKEPOINTS(lParam).x,
  616. (int)MAKEPOINTS(lParam).y };
  617. if (PtInRect(&pMstr->DblClkRect, point))
  618. {
  619. JackClicked(hDlg, pMstr);
  620. }
  621. break;
  622. }
  623. case ( WM_COMMAND ) :
  624. {
  625. switch (LOWORD(wParam))
  626. {
  627. case ( MOUSE_LEFTHAND ) :
  628. {
  629. if (pMstr->bSwap != RIGHT)
  630. {
  631. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  632. pMstr->bSwap = RIGHT;
  633. ShowButtonState(pMstr);
  634. }
  635. break;
  636. }
  637. case ( MOUSE_RIGHTHAND ) :
  638. {
  639. if (pMstr->bSwap != LEFT)
  640. {
  641. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  642. pMstr->bSwap = LEFT;
  643. ShowButtonState(pMstr);
  644. }
  645. break;
  646. }
  647. case ( MOUSE_DBLCLKBMP ) :
  648. {
  649. if (HIWORD(wParam) == ACN_STOP)
  650. {
  651. JackStopped(hDlg, pMstr);
  652. }
  653. break;
  654. }
  655. case ( MOUSE_SGLCLICK ) :
  656. case ( MOUSE_DBLCLICK ) :
  657. {
  658. if( pMstr->bShellSingleClick != (MOUSE_SGLCLICK == LOWORD(wParam)) )
  659. {
  660. pMstr->bShellSingleClick = (MOUSE_SGLCLICK == LOWORD(wParam)) ;
  661. ShellClick_UpdateUI( hDlg, pMstr ) ;
  662. SendMessage( GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L ) ;
  663. }
  664. break ;
  665. }
  666. }
  667. break;
  668. }
  669. case ( WM_NOTIFY ) :
  670. {
  671. switch (((NMHDR *)lParam)->code)
  672. {
  673. case ( PSN_APPLY ) :
  674. {
  675. HourGlass(TRUE);
  676. if (pMstr->bSwap != pMstr->bOrigSwap)
  677. {
  678. SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP,
  679. pMstr->bSwap,
  680. NULL,
  681. SPIF_UPDATEINIFILE |
  682. SPIF_SENDWININICHANGE );
  683. pMstr->bOrigSwap = pMstr->bSwap;
  684. }
  685. if (pMstr->ClickSpeed != pMstr->OrigDblClkSpeed)
  686. {
  687. SystemParametersInfo( SPI_SETDOUBLECLICKTIME,
  688. pMstr->ClickSpeed,
  689. NULL,
  690. SPIF_UPDATEINIFILE |
  691. SPIF_SENDWININICHANGE );
  692. pMstr->OrigDblClkSpeed = pMstr->ClickSpeed;
  693. }
  694. if( pMstr->bOrigShellSingleClick != pMstr->bShellSingleClick )
  695. {
  696. SHELLSTATE shellstate = {0} ;
  697. ULONG dwFlags = SSF_DOUBLECLICKINWEBVIEW ;
  698. shellstate.fWin95Classic =
  699. shellstate.fDoubleClickInWebView = !pMstr->bShellSingleClick ;
  700. // update the WIN95CLASSIC member only if we've chosen single-click.
  701. if( pMstr->bShellSingleClick )
  702. dwFlags |= SSF_WIN95CLASSIC ;
  703. SHGetSetSettings( &shellstate, dwFlags, TRUE ) ;
  704. ShellClick_Refresh( pMstr ) ;
  705. pMstr->bOrigShellSingleClick = pMstr->bShellSingleClick ;
  706. }
  707. HourGlass(FALSE);
  708. break;
  709. }
  710. case ( PSN_RESET ) :
  711. {
  712. SetDoubleClickTime(pMstr->OrigDblClkSpeed);
  713. break;
  714. }
  715. default :
  716. {
  717. return (FALSE);
  718. }
  719. }
  720. break;
  721. }
  722. case ( WM_HELP ) : // F1
  723. {
  724. WinHelp( ((LPHELPINFO)lParam)->hItemHandle,
  725. HELP_FILE,
  726. HELP_WM_HELP,
  727. (DWORD_PTR)(LPTSTR)aMouseButHelpIds );
  728. break;
  729. }
  730. case ( WM_CONTEXTMENU ) : // right mouse click
  731. {
  732. WinHelp( (HWND) wParam,
  733. HELP_FILE,
  734. HELP_CONTEXTMENU,
  735. (DWORD_PTR)(LPTSTR)aMouseButHelpIds );
  736. break;
  737. }
  738. case ( WM_DISPLAYCHANGE ) :
  739. case ( WM_WININICHANGE ) :
  740. case ( WM_SYSCOLORCHANGE ) :
  741. {
  742. SHPropagateMessage(hDlg, message, wParam, lParam, TRUE);
  743. return TRUE;
  744. }
  745. default :
  746. {
  747. return (FALSE);
  748. }
  749. }
  750. return (TRUE);
  751. }
  752. ////////////////////////////////////////////////////////////////////////////
  753. //
  754. // ShellClick_UpdateUI
  755. //
  756. // Assigns the appropriate icon for shell single/double click
  757. //
  758. ////////////////////////////////////////////////////////////////////////////
  759. void ShellClick_UpdateUI(
  760. HWND hDlg,
  761. PMOUSEBUTSTR pMstr)
  762. {
  763. HICON hicon = pMstr->bShellSingleClick ? pMstr->hIconSglClick :
  764. pMstr->hIconDblClick ;
  765. SendMessage( GetDlgItem( hDlg, MOUSE_CLICKICON ), STM_SETICON,
  766. (WPARAM)hicon, 0L ) ;
  767. }
  768. ////////////////////////////////////////////////////////////////////////////
  769. //
  770. // IsShellWindow
  771. //
  772. // Determines whether the specified window is a shell folder window.
  773. //
  774. ////////////////////////////////////////////////////////////////////////////
  775. #define c_szExploreClass TEXT("ExploreWClass")
  776. #define c_szIExploreClass TEXT("IEFrame")
  777. #ifdef IE3CLASSNAME
  778. #define c_szCabinetClass TEXT("IEFrame")
  779. #else
  780. #define c_szCabinetClass TEXT("CabinetWClass")
  781. #endif
  782. BOOL IsShellWindow( HWND hwnd )
  783. {
  784. TCHAR szClass[32];
  785. GetClassName(hwnd, szClass, ARRAYSIZE(szClass));
  786. return (lstrcmp(szClass, c_szCabinetClass) == 0) ||
  787. (lstrcmp(szClass, c_szExploreClass) == 0) ||
  788. (lstrcmp(szClass, c_szIExploreClass) == 0) ;
  789. }
  790. //The following value is taken from shdocvw\rcids.h
  791. #ifndef FCIDM_REFRESH
  792. #define FCIDM_REFRESH 0xA220
  793. #endif // FCIDM_REFRESH
  794. ////////////////////////////////////////////////////////////////////////////
  795. //
  796. // ShellClick_RefreshEnumProc
  797. //
  798. // EnumWindow callback for shell refresh.
  799. //
  800. ////////////////////////////////////////////////////////////////////////////
  801. BOOL CALLBACK ShellClick_RefreshEnumProc( HWND hwnd, LPARAM lParam )
  802. {
  803. if( IsShellWindow(hwnd) )
  804. PostMessage(hwnd, WM_COMMAND, FCIDM_REFRESH, 0L);
  805. return(TRUE);
  806. }
  807. ////////////////////////////////////////////////////////////////////////////
  808. //
  809. // ShellClick_Refresh
  810. //
  811. // Re-renders the contents of all shell folder windows.
  812. //
  813. ////////////////////////////////////////////////////////////////////////////
  814. void ShellClick_Refresh( PMOUSEBUTSTR pMstr )
  815. {
  816. HWND hwndDesktop = FindWindowEx(NULL, NULL, TEXT(STR_DESKTOPCLASS), NULL);
  817. if( NULL != hwndDesktop )
  818. PostMessage( hwndDesktop, WM_COMMAND, FCIDM_REFRESH, 0L );
  819. EnumWindows( ShellClick_RefreshEnumProc, 0L ) ;
  820. }