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.

4281 lines
129 KiB

  1. //---------------------------------------------------------------------------
  2. #include "ctlspriv.h"
  3. #include "scroll.h"
  4. #if defined(_UXTHEME_)
  5. // non-client scrollbar
  6. #include "nctheme.h"
  7. #include "scrollp.h"
  8. #else
  9. // scrollbar control
  10. #include "usrctl32.h"
  11. #endif _UXTHEME_
  12. // comment this out to visually match user32 scrollbar:
  13. //#define _VISUAL_DELTA_
  14. #ifdef _VISUAL_DELTA_
  15. #define CARET_BORDERWIDTH 2
  16. #endif _VISUAL_DELTA_
  17. //-------------------------------------------------------------------------//
  18. #define FNID_SCROLLBAR 0x0000029A // UxScrollBarWndProc;
  19. #define GetOwner(hwnd) GetWindow(hwnd, GW_OWNER)
  20. #define HW(x) x
  21. #define HWq(x) x
  22. #define RIPERR0(s1,s2,errno)
  23. #define RIPMSG1(errno,fmt,arg1)
  24. #define RIPMSG2(errno,fmt,arg1,arg2)
  25. #define RIPMSG3(errno,fmt,arg1,arg2,arg3)
  26. #define RIP_VERBOSE()
  27. #define ClrWF ClearWindowState
  28. #define SetWF SetWindowState
  29. #define Lock(phwnd, hwnd) InterlockedExchangePointer((PVOID*)(phwnd), (PVOID)hwnd)
  30. #define Unlock(phwnd) Lock(phwnd, NULL)
  31. #define CheckLock(hwnd)
  32. #define ThreadLock(w,t)
  33. #define ThreadUnlock(t)
  34. #define VALIDATECLASSANDSIZE
  35. #define DTTIME (MulDiv( GetDoubleClickTime(), 4, 5 ))
  36. #define _KillSystemTimer KillTimer
  37. #define _SetSystemTimer SetTimer
  38. #define IsWinEventNotifyDeferredOK() TRUE
  39. #define IsWinEventNotifyDeferred() FALSE
  40. //-------------------------------------------------------------------------//
  41. // scroll type flags userk.h
  42. #define SCROLL_NORMAL 0
  43. #define SCROLL_DIRECT 1
  44. #define SCROLL_MENU 2
  45. //-------------------------------------------------------------------------//
  46. // internal Scrollbar state/style bits
  47. //#define SBFSIZEBOXTOPLEFT 0x0C02
  48. //#define SBFSIZEBOXBOTTOMRIGHT 0x0C04
  49. //#define SBFSIZEBOX 0x0C08
  50. #define SBFSIZEGRIP 0x0C10
  51. //----------------------------------//
  52. // Scrollbar arrow disable flags
  53. #define LTUPFLAG 0x0001 // Left/Up arrow disable flag.
  54. #define RTDNFLAG 0x0002 // Right/Down arrow disable flag.
  55. //----------------------------------//
  56. // function forwards
  57. UINT _SysToChar(UINT message, LPARAM lParam);
  58. //-------------------------------------------------------------------------//
  59. // private hittest codes
  60. //#define HTEXSCROLLFIRST 60
  61. #define HTSCROLLUP 60
  62. #define HTSCROLLDOWN 61
  63. #define HTSCROLLUPPAGE 62
  64. #define HTSCROLLDOWNPAGE 63
  65. #define HTSCROLLTHUMB 64
  66. //#define HTEXSCROLLLAST 64
  67. //#define HTEXMENUFIRST 65
  68. //#define HTMDISYSMENU 65
  69. //#define HTMDIMAXBUTTON 66
  70. //#define HTMDIMINBUTTON 67
  71. //#define HTMDICLOSE 68
  72. //#define HTMENUITEM 69
  73. //#define HTEXMENULAST 69
  74. #define IDSYS_SCROLL 0x0000FFFEL // timer ID, user.h
  75. typedef HWND SBHWND;
  76. typedef HMENU PMENU;
  77. //-------------------------------------------------------------------------//
  78. // SBDATA
  79. typedef struct tagSBDATA
  80. {
  81. int posMin;
  82. int posMax;
  83. int page;
  84. int pos;
  85. } SBDATA, *PSBDATA;
  86. //-------------------------------------------------------------------------//
  87. // SBINFO is the set of values that hang off of a window structure,
  88. // if the window has scrollbars.
  89. typedef struct tagSBINFO
  90. {
  91. int WSBflags;
  92. SBDATA Horz;
  93. SBDATA Vert;
  94. } SBINFO, * PSBINFO;
  95. //-------------------------------------------------------------------------//
  96. // SBCALC
  97. // Scrollbar metrics block.
  98. typedef struct tagSBCALC
  99. {
  100. SBDATA data; /* this must be first -- we cast structure pointers */
  101. int pxTop;
  102. int pxBottom;
  103. int pxLeft;
  104. int pxRight;
  105. int cpxThumb;
  106. int pxUpArrow;
  107. int pxDownArrow;
  108. int pxStart; /* Initial position of thumb */
  109. int pxThumbBottom;
  110. int pxThumbTop;
  111. int cpx;
  112. int pxMin;
  113. } SBCALC, *PSBCALC;
  114. //-------------------------------------------------------------------------//
  115. // SBTRACK
  116. // Scrollbar thumb-tracking state block.
  117. typedef struct tagSBTRACK {
  118. DWORD fHitOld : 1;
  119. DWORD fTrackVert : 1;
  120. DWORD fCtlSB : 1;
  121. DWORD fTrackRecalc: 1;
  122. HWND hwndTrack;
  123. HWND hwndSB;
  124. HWND hwndSBNotify;
  125. RECT rcTrack;
  126. VOID (CALLBACK *pfnSB)(HWND, UINT, WPARAM, LPARAM, PSBCALC);
  127. UINT cmdSB;
  128. UINT_PTR hTimerSB;
  129. int dpxThumb; /* Offset from mouse point to start of thumb box */
  130. int pxOld; /* Previous position of thumb */
  131. int posOld;
  132. int posNew;
  133. int nBar;
  134. PSBCALC pSBCalc;
  135. } SBTRACK, *PSBTRACK;
  136. //-------------------------------------------------------------------------//
  137. // Window scrollbars, control base.
  138. class CUxScrollBar
  139. //-------------------------------------------------------------------------//
  140. {
  141. public:
  142. CUxScrollBar();
  143. virtual ~CUxScrollBar() {}
  144. virtual BOOL IsCtl() const { return FALSE;}
  145. operator HWND() { return _hwnd; }
  146. static CUxScrollBar* Calc( HWND hwnd, PSBCALC pSBCalc, LPRECT prcOverrideClient, BOOL fVert);
  147. virtual void Calc2( PSBCALC pSBCalc, LPRECT lprc, CONST PSBDATA pw, BOOL fVert);
  148. virtual void DoScroll( HWND hwndNotify, int cmd, int pos, BOOL fVert );
  149. virtual void ClearTrack() { ZeroMemory( &_track, sizeof(_track) ); }
  150. SBTRACK* GetTrack() { return &_track; }
  151. SBINFO* GetInfo() { return &_info; }
  152. HTHEME GetTheme() { return _hTheme; }
  153. BOOL IsAttaching() { return _fAttaching; }
  154. INT GetHotComponent(BOOL fVert) { return fVert ? _htVert : _htHorz; }
  155. VOID SetHotComponent(INT ht, BOOL fVert) { (fVert ? _htVert : _htHorz) = ht; }
  156. virtual void ChangeSBTheme();
  157. virtual BOOL FreshenSBData( int nBar, BOOL fRedraw );
  158. // UxScrollBar API.
  159. static CUxScrollBar* Attach( HWND hwnd, BOOL bCtl, BOOL fRedraw );
  160. static CUxScrollBar* FromHwnd( HWND hwnd );
  161. static void Detach( HWND hwnd );
  162. static SBTRACK* GetSBTrack( HWND hwnd );
  163. static void ClearSBTrack( HWND hwnd );
  164. static SBINFO* GetSBInfo( HWND hwnd );
  165. static HTHEME GetSBTheme( HWND hwnd );
  166. static INT GetSBHotComponent( HWND hwnd, BOOL fVert);
  167. protected:
  168. HWND _hwnd;
  169. SBTRACK _track;
  170. SBINFO _info;
  171. INT _htVert; // Scroll bar part the mouse is currently over
  172. INT _htHorz; // Scroll bar part the mouse is currently over
  173. HTHEME _hTheme;// Handle to theme manager
  174. BOOL _fAttaching;
  175. };
  176. //-------------------------------------------------------------------------//
  177. // Scrollbar control
  178. class CUxScrollBarCtl : public CUxScrollBar
  179. //-------------------------------------------------------------------------//
  180. {
  181. public:
  182. CUxScrollBarCtl();
  183. virtual BOOL IsCtl() const { return TRUE;}
  184. BOOL AddRemoveDisableFlags( UINT wAdd, UINT wRemove );
  185. // UxScrollBarCtl API.
  186. static CUxScrollBarCtl* FromHwnd( HWND hwnd );
  187. static UINT GetDisableFlags( HWND hwnd );
  188. static SBCALC* GetCalc( HWND hwnd );
  189. static BOOL AddRemoveDisableFlags( HWND, UINT, UINT );
  190. static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
  191. BOOL _fVert;
  192. UINT _wDisableFlags; // Indicates which arrow is disabled;
  193. SBCALC _calc;
  194. };
  195. //-------------------------------------------------------------------------//
  196. // IsScrollBarControl
  197. #ifdef PORTPORT
  198. #define IsScrollBarControl(h) (GETFNID(h) == FNID_SCROLLBAR)
  199. #else //PORTPORT
  200. inline BOOL IsScrollBarControl(HWND hwnd) {
  201. return CUxScrollBarCtl::FromHwnd( hwnd ) != NULL;
  202. }
  203. #endif //PORTPORT
  204. //-------------------------------------------------------------------------//
  205. // Forwards:
  206. void DrawScrollBar( HWND hwnd, HDC hdc, LPRECT prcOverrideClient, BOOL fVert);
  207. HWND SizeBoxHwnd( HWND hwnd );
  208. VOID _DrawPushButton( HWND hwnd, HDC hdc, LPRECT lprc, UINT state, UINT flags, BOOL fVert);
  209. UINT _GetWndSBDisableFlags(HWND, BOOL);
  210. void CALLBACK _TrackThumb( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, PSBCALC pSBCalc);
  211. void CALLBACK _TrackBox( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, PSBCALC pSBCalc);
  212. void _RedrawFrame( HWND hwnd );
  213. BOOL _FChildVisible( HWND hwnd );
  214. LONG _SetScrollBar( HWND hwnd, int code, LPSCROLLINFO lpsi, BOOL fRedraw);
  215. HBRUSH _UxGrayBrush(VOID);
  216. //-------------------------------------------------------------------------//
  217. BOOL WINAPI InitScrollBarClass( HINSTANCE hInst )
  218. {
  219. WNDCLASSEX wc = {0};
  220. wc.cbSize = sizeof(wc);
  221. wc.style = CS_GLOBALCLASS|CS_PARENTDC|CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
  222. wc.lpfnWndProc = CUxScrollBarCtl::WndProc;
  223. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  224. wc.hInstance = hInst;
  225. wc.lpszClassName = WC_SCROLLBAR;
  226. wc.cbWndExtra = max(sizeof(CUxScrollBar), sizeof(CUxScrollBarCtl));
  227. RegisterClassEx(&wc);
  228. // Don't care if it fails, dynamic registration will prevail
  229. return TRUE;
  230. }
  231. //-------------------------------------------------------------------------//
  232. // CUxScrollBar impl
  233. //-------------------------------------------------------------------------//
  234. //-------------------------------------------------------------------------//
  235. CUxScrollBar::CUxScrollBar()
  236. : _hwnd(NULL),
  237. _hTheme(NULL),
  238. _htVert(HTNOWHERE),
  239. _htHorz(HTNOWHERE),
  240. _fAttaching(FALSE)
  241. {
  242. ClearTrack();
  243. ZeroMemory( &_info, sizeof(_info) );
  244. _info.Vert.posMax = 100; // ported from _InitPwSB
  245. _info.Horz.posMax = 100; // ported from _InitPwSB
  246. }
  247. //-------------------------------------------------------------------------//
  248. CUxScrollBar* CUxScrollBar::Attach( HWND hwnd, BOOL bCtl, BOOL fRedraw )
  249. {
  250. CUxScrollBar* psb = FromHwnd( hwnd );
  251. if( NULL == psb )
  252. {
  253. psb = bCtl ? new CUxScrollBarCtl : new CUxScrollBar;
  254. if( psb != NULL )
  255. {
  256. ASSERT( psb->IsCtl() == bCtl );
  257. if( (! hwnd) || (! SetProp( hwnd, MAKEINTATOM(GetThemeAtom(THEMEATOM_SCROLLBAR)), (HANDLE)psb ) ))
  258. {
  259. delete psb;
  260. psb = NULL;
  261. }
  262. else
  263. {
  264. psb->_hwnd = hwnd;
  265. psb->_fAttaching = TRUE;
  266. if (psb->IsCtl())
  267. {
  268. psb->_hTheme = OpenThemeData(hwnd, L"ScrollBar");
  269. }
  270. else
  271. {
  272. psb->_hTheme = OpenNcThemeData(hwnd, L"ScrollBar");
  273. //
  274. // window SBs must grovel for state data each
  275. // time attached [scotthan]
  276. //
  277. SCROLLINFO si;
  278. ZeroMemory(&si, sizeof(si));
  279. si.cbSize = sizeof(si);
  280. si.fMask = SIF_ALL;
  281. if (GetScrollInfo(hwnd, SB_VERT, &si))
  282. {
  283. si.fMask |= SIF_DISABLENOSCROLL;
  284. _SetScrollBar(hwnd, SB_VERT, &si, FALSE);
  285. }
  286. ZeroMemory(&si, sizeof(si));
  287. si.cbSize = sizeof(si);
  288. si.fMask = SIF_ALL;
  289. if (GetScrollInfo(hwnd, SB_HORZ, &si))
  290. {
  291. si.fMask |= SIF_DISABLENOSCROLL;
  292. _SetScrollBar(hwnd, SB_HORZ, &si, FALSE);
  293. }
  294. }
  295. psb->_fAttaching = FALSE;
  296. }
  297. }
  298. }
  299. return psb;
  300. }
  301. //-------------------------------------------------------------------------//
  302. CUxScrollBar* CUxScrollBar::FromHwnd( HWND hwnd )
  303. {
  304. if (! hwnd)
  305. return NULL;
  306. return (CUxScrollBar*)GetProp( hwnd, MAKEINTATOM(GetThemeAtom(THEMEATOM_SCROLLBAR)));
  307. }
  308. //-------------------------------------------------------------------------//
  309. void CUxScrollBar::Detach( HWND hwnd )
  310. {
  311. CUxScrollBar* psb = FromHwnd( hwnd );
  312. if ( psb == NULL || !psb->_fAttaching )
  313. {
  314. if (hwnd)
  315. {
  316. RemoveProp( hwnd, MAKEINTATOM(GetThemeAtom(THEMEATOM_SCROLLBAR)));
  317. }
  318. if( psb != NULL )
  319. {
  320. if ( psb->_hTheme )
  321. {
  322. CloseThemeData(psb->_hTheme);
  323. }
  324. delete psb;
  325. }
  326. }
  327. }
  328. //-------------------------------------------------------------------------//
  329. void WINAPI AttachScrollBars( HWND hwnd )
  330. {
  331. ASSERT( GetWindowLong( hwnd, GWL_STYLE ) & (WS_HSCROLL|WS_VSCROLL) );
  332. CUxScrollBar::Attach( hwnd, FALSE, FALSE );
  333. }
  334. //-------------------------------------------------------------------------//
  335. void WINAPI DetachScrollBars( HWND hwnd )
  336. {
  337. CUxScrollBar::Detach( hwnd );
  338. }
  339. //-------------------------------------------------------------------------//
  340. SBTRACK* CUxScrollBar::GetSBTrack( HWND hwnd )
  341. {
  342. CUxScrollBar* psb = FromHwnd( hwnd );
  343. if( psb )
  344. return &psb->_track;
  345. return NULL;
  346. }
  347. //-------------------------------------------------------------------------//
  348. void CUxScrollBar::ClearSBTrack( HWND hwnd )
  349. {
  350. CUxScrollBar* psb = FromHwnd( hwnd );
  351. if( psb )
  352. psb->ClearTrack();
  353. }
  354. //-------------------------------------------------------------------------//
  355. SBINFO* CUxScrollBar::GetSBInfo( HWND hwnd )
  356. {
  357. CUxScrollBar* psb = FromHwnd( hwnd );
  358. if( psb )
  359. return &psb->_info;
  360. return NULL;
  361. }
  362. //-------------------------------------------------------------------------//
  363. HTHEME CUxScrollBar::GetSBTheme( HWND hwnd )
  364. {
  365. CUxScrollBar* psb = FromHwnd( hwnd );
  366. if( psb )
  367. return psb->_hTheme;
  368. return NULL;
  369. }
  370. //-------------------------------------------------------------------------//
  371. INT CUxScrollBar::GetSBHotComponent( HWND hwnd, BOOL fVert )
  372. {
  373. CUxScrollBar* psb = FromHwnd( hwnd );
  374. if( psb )
  375. return psb->GetHotComponent(fVert);
  376. return 0;
  377. }
  378. //-------------------------------------------------------------------------//
  379. BOOL CUxScrollBar::FreshenSBData( int nBar, BOOL fRedraw )
  380. {
  381. #ifdef __POLL_FOR_SCROLLINFO__
  382. ASSERT(IsWindow(_hwnd));
  383. if( !IsCtl() )
  384. {
  385. // Note scrollbar ctls don't go stale because
  386. // they receive SBM notifications
  387. SCROLLINFO si;
  388. si.cbSize = sizeof(si);
  389. si.fMask = SIF_ALL;
  390. switch(nBar)
  391. {
  392. case SB_VERT:
  393. case SB_HORZ:
  394. if( GetScrollInfo( _hwnd, nBar, &si ) )
  395. {
  396. _SetScrollBar( _hwnd, nBar, &si, fRedraw );
  397. }
  398. break;
  399. case SB_BOTH:
  400. return FreshenSBData( SB_VERT, fRedraw ) &&
  401. FreshenSBData( SB_HORZ, fRedraw );
  402. break;
  403. default: return FALSE;
  404. }
  405. }
  406. #endif __POLL_FOR_SCROLLINFO__
  407. return TRUE;
  408. }
  409. //-------------------------------------------------------------------------//
  410. void CUxScrollBar::ChangeSBTheme()
  411. {
  412. if ( _hTheme )
  413. {
  414. CloseThemeData(_hTheme);
  415. }
  416. _hTheme = NULL;
  417. if (IsCtl())
  418. _hTheme = OpenThemeData(_hwnd, L"ScrollBar");
  419. else
  420. _hTheme = OpenNcThemeData(_hwnd, L"ScrollBar");
  421. }
  422. //-------------------------------------------------------------------------//
  423. // CUxScrollBarCtl impl
  424. //-------------------------------------------------------------------------//
  425. //-------------------------------------------------------------------------//
  426. CUxScrollBarCtl::CUxScrollBarCtl()
  427. : _wDisableFlags(0), _fVert(FALSE)
  428. {
  429. ZeroMemory( &_calc, sizeof(_calc) );
  430. }
  431. //-------------------------------------------------------------------------//
  432. CUxScrollBarCtl* CUxScrollBarCtl::FromHwnd( HWND hwnd )
  433. {
  434. CUxScrollBarCtl* psb = (CUxScrollBarCtl*)CUxScrollBar::FromHwnd( hwnd );
  435. if( psb )
  436. return psb->IsCtl() ? psb : NULL;
  437. return NULL;
  438. }
  439. //-------------------------------------------------------------------------//
  440. UINT CUxScrollBarCtl::GetDisableFlags( HWND hwnd )
  441. {
  442. CUxScrollBarCtl* psb = FromHwnd( hwnd );
  443. if( psb )
  444. return psb->_wDisableFlags;
  445. return 0;
  446. }
  447. //-------------------------------------------------------------------------//
  448. SBCALC* CUxScrollBarCtl::GetCalc( HWND hwnd )
  449. {
  450. CUxScrollBarCtl* psb = FromHwnd( hwnd );
  451. if( psb )
  452. return &psb->_calc;
  453. return NULL;
  454. }
  455. //-------------------------------------------------------------------------//
  456. // CUxScrollBarCtl::AddRemoveDisableFlags() - static
  457. BOOL CUxScrollBarCtl::AddRemoveDisableFlags( HWND hwnd, UINT wAdd, UINT wRemove )
  458. {
  459. CUxScrollBarCtl* psb = FromHwnd( hwnd );
  460. if( psb )
  461. return psb->AddRemoveDisableFlags( wAdd, wRemove );
  462. return FALSE;
  463. }
  464. //-------------------------------------------------------------------------//
  465. // CUxScrollBarCtl::AddRemoveDisableFlags() - instance member
  466. BOOL CUxScrollBarCtl::AddRemoveDisableFlags( UINT wAdd, UINT wRemove )
  467. {
  468. // returns TRUE if flags changed, otherwise FALSE.
  469. UINT wOld = _wDisableFlags;
  470. _wDisableFlags |= wAdd;
  471. _wDisableFlags &= ~wRemove;
  472. return _wDisableFlags != wOld;
  473. }
  474. //-------------------------------------------------------------------------//
  475. // CUxScrollBar::Calc(). computes metrics for window SBs only.
  476. // derives rect and calls Calc2.
  477. CUxScrollBar* CUxScrollBar::Calc(
  478. HWND hwnd,
  479. PSBCALC pSBCalc,
  480. LPRECT prcOverrideClient,
  481. BOOL fVert)
  482. {
  483. RECT rcT;
  484. #ifdef USE_MIRRORING
  485. int cx, iTemp;
  486. #endif
  487. //
  488. // Get client rectangle in window-relative coords.
  489. // We know that window scrollbars always align to the right
  490. // and to the bottom of the client area.
  491. //
  492. WINDOWINFO wi;
  493. wi.cbSize = sizeof(wi);
  494. if( !GetWindowInfo( hwnd, &wi ) )
  495. return NULL;
  496. OffsetRect( &wi.rcClient, -wi.rcWindow.left, -wi.rcWindow.top );
  497. #ifdef USE_MIRRORING
  498. if (TestWF(hwnd, WEFLAYOUTRTL)) {
  499. cx = wi.rcWindow.right - wi.rcWindow.left;
  500. iTemp = wi.rcClient.left;
  501. wi.rcClient.left = cx - wi.rcClient.right;
  502. wi.rcClient.right = cx - iTemp;
  503. }
  504. #endif
  505. if (fVert) {
  506. // Only add on space if vertical scrollbar is really there.
  507. if (TestWF(hwnd, WEFLEFTSCROLL)) {
  508. rcT.right = rcT.left = wi.rcClient.left;
  509. if (TestWF(hwnd, WFVPRESENT))
  510. rcT.left -= SYSMET(CXVSCROLL);
  511. } else {
  512. rcT.right = rcT.left = wi.rcClient.right;
  513. if (TestWF(hwnd, WFVPRESENT))
  514. rcT.right += SYSMET(CXVSCROLL);
  515. }
  516. rcT.top = wi.rcClient.top;
  517. rcT.bottom = wi.rcClient.bottom;
  518. } else {
  519. // Only add on space if horizontal scrollbar is really there.
  520. rcT.bottom = rcT.top = wi.rcClient.bottom;
  521. if (TestWF(hwnd, WFHPRESENT))
  522. rcT.bottom += SYSMET(CYHSCROLL);
  523. rcT.left = wi.rcClient.left;
  524. rcT.right = wi.rcClient.right;
  525. }
  526. if (prcOverrideClient)
  527. {
  528. rcT = *prcOverrideClient;
  529. }
  530. // If InitPwSB stuff fails (due to our heap being full) there isn't anything reasonable
  531. // we can do here, so just let it go through. We won't fault but the scrollbar won't work
  532. // properly either...
  533. CUxScrollBar* psb = CUxScrollBar::Attach( hwnd, FALSE, FALSE );
  534. if( psb )
  535. {
  536. SBDATA* pData = fVert ? &psb->_info.Vert : &psb->_info.Horz;
  537. if( psb )
  538. psb->Calc2( pSBCalc, &rcT, pData, fVert );
  539. return psb;
  540. }
  541. return NULL;
  542. }
  543. //-------------------------------------------------------------------------//
  544. // CUxScrollBar::Calc2(). computes metrics for window SBs or SB ctls.
  545. void CUxScrollBar::Calc2( PSBCALC pSBCalc, LPRECT lprc, CONST PSBDATA pw, BOOL fVert)
  546. {
  547. int cpx;
  548. DWORD dwRange;
  549. int denom;
  550. if (fVert) {
  551. pSBCalc->pxTop = lprc->top;
  552. pSBCalc->pxBottom = lprc->bottom;
  553. pSBCalc->pxLeft = lprc->left;
  554. pSBCalc->pxRight = lprc->right;
  555. pSBCalc->cpxThumb = SYSMET(CYVSCROLL);
  556. } else {
  557. /*
  558. * For horiz scroll bars, "left" & "right" are "top" and "bottom",
  559. * and vice versa.
  560. */
  561. pSBCalc->pxTop = lprc->left;
  562. pSBCalc->pxBottom = lprc->right;
  563. pSBCalc->pxLeft = lprc->top;
  564. pSBCalc->pxRight = lprc->bottom;
  565. pSBCalc->cpxThumb = SYSMET(CXHSCROLL);
  566. }
  567. pSBCalc->data.pos = pw->pos;
  568. pSBCalc->data.page = pw->page;
  569. pSBCalc->data.posMin = pw->posMin;
  570. pSBCalc->data.posMax = pw->posMax;
  571. dwRange = ((DWORD)(pSBCalc->data.posMax - pSBCalc->data.posMin)) + 1;
  572. //
  573. // For the case of short scroll bars that don't have enough
  574. // room to fit the full-sized up and down arrows, shorten
  575. // their sizes to make 'em fit
  576. //
  577. cpx = min((pSBCalc->pxBottom - pSBCalc->pxTop) / 2, pSBCalc->cpxThumb);
  578. pSBCalc->pxUpArrow = pSBCalc->pxTop + cpx;
  579. pSBCalc->pxDownArrow = pSBCalc->pxBottom - cpx;
  580. if ((pw->page != 0) && (dwRange != 0)) {
  581. // JEFFBOG -- This is the one and only place where we should
  582. // see 'range'. Elsewhere it should be 'range - page'.
  583. /*
  584. * The minimun thumb size used to depend on the frame/edge metrics.
  585. * People that increase the scrollbar width/height expect the minimun
  586. * to grow with proportianally. So NT5 bases the minimun on
  587. * CXH/YVSCROLL, which is set by default in cpxThumb.
  588. */
  589. /*
  590. * i is used to keep the macro "max" from executing MulDiv twice.
  591. */
  592. int i = MulDiv(pSBCalc->pxDownArrow - pSBCalc->pxUpArrow,
  593. pw->page, dwRange);
  594. pSBCalc->cpxThumb = max(pSBCalc->cpxThumb / 2, i);
  595. }
  596. pSBCalc->pxMin = pSBCalc->pxTop + cpx;
  597. pSBCalc->cpx = pSBCalc->pxBottom - cpx - pSBCalc->cpxThumb - pSBCalc->pxMin;
  598. denom = dwRange - (pw->page ? pw->page : 1);
  599. if (denom)
  600. pSBCalc->pxThumbTop = MulDiv(pw->pos - pw->posMin,
  601. pSBCalc->cpx, denom) +
  602. pSBCalc->pxMin;
  603. else
  604. pSBCalc->pxThumbTop = pSBCalc->pxMin - 1;
  605. pSBCalc->pxThumbBottom = pSBCalc->pxThumbTop + pSBCalc->cpxThumb;
  606. }
  607. //-------------------------------------------------------------------------//
  608. void CUxScrollBar::DoScroll( HWND hwndNotify, int cmd, int pos, BOOL fVert )
  609. {
  610. HWND hwnd = _hwnd;
  611. //
  612. // Send scroll notification to the scrollbar owner. If this is a control
  613. // the lParam is the control's handle, NULL otherwise.
  614. //
  615. SendMessage(hwndNotify,
  616. (UINT)(fVert ? WM_VSCROLL : WM_HSCROLL),
  617. MAKELONG(cmd, pos),
  618. (LPARAM)(IsCtl() ? _hwnd : NULL));
  619. //
  620. // The hwnd can have it's scrollbar removed as the result
  621. // of the previous sendmessge.
  622. //
  623. if( CUxScrollBar::GetSBTrack(hwnd) && !IsCtl() )
  624. {
  625. FreshenSBData( fVert ? SB_VERT : SB_HORZ, TRUE );
  626. }
  627. }
  628. /*
  629. * Now it is possible to selectively Enable/Disable just one arrow of a Window
  630. * scroll bar; Various bits in the 7th word in the rgwScroll array indicates which
  631. * one of these arrows are disabled; The following masks indicate which bit of the
  632. * word indicates which arrow;
  633. */
  634. #define WSB_HORZ_LF 0x0001 // Represents the Left arrow of the horizontal scroll bar.
  635. #define WSB_HORZ_RT 0x0002 // Represents the Right arrow of the horizontal scroll bar.
  636. #define WSB_VERT_UP 0x0004 // Represents the Up arrow of the vert scroll bar.
  637. #define WSB_VERT_DN 0x0008 // Represents the Down arrow of the vert scroll bar.
  638. #define WSB_VERT (WSB_VERT_UP | WSB_VERT_DN)
  639. #define WSB_HORZ (WSB_HORZ_LF | WSB_HORZ_RT)
  640. void DrawCtlThumb( SBHWND );
  641. /*
  642. * RETURN_IF_PSBTRACK_INVALID:
  643. * This macro tests whether the pSBTrack we have is invalid, which can happen
  644. * if it gets freed during a callback.
  645. * This protects agains the original pSBTrack being freed and no new one
  646. * being allocated or a new one being allocated at a different address.
  647. * This does not protect against the original pSBTrack being freed and a new
  648. * one being allocated at the same address.
  649. * If pSBTrack has changed, we assert that there is not already a new one
  650. * because we are really not expecting this.
  651. */
  652. #define RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd) \
  653. if ((pSBTrack) != CUxScrollBar::GetSBTrack(hwnd)) { \
  654. ASSERT(CUxScrollBar::GetSBTrack(hwnd) == NULL); \
  655. return; \
  656. }
  657. /*
  658. * REEVALUATE_PSBTRACK
  659. * This macro just refreshes the local variable pSBTrack, in case it has
  660. * been changed during a callback. After performing this operation, pSBTrack
  661. * should be tested to make sure it is not now NULL.
  662. */
  663. #if (defined(DBG) || defined(DEBUG) || defined(_DEBUG))
  664. #define REEVALUATE_PSBTRACK(pSBTrack, hwnd, str) \
  665. if ((pSBTrack) != CUxScrollBar::GetSBTrack(hwnd)) { \
  666. RIPMSG3(RIP_WARNING, \
  667. "%s: pSBTrack changed from %#p to %#p", \
  668. (str), (pSBTrack), CUxScrollBar::GetSBTrack(hwnd)); \
  669. } \
  670. (pSBTrack) = CUxScrollBar::GetSBTrack(hwnd)
  671. #else
  672. #define REEVALUATE_PSBTRACK(pSBTrack, hwnd, str) \
  673. (pSBTrack) = CUxScrollBar::GetSBTrack(hwnd)
  674. #endif
  675. /***************************************************************************\
  676. * HitTestScrollBar
  677. *
  678. * 11/15/96 vadimg ported from Memphis sources
  679. \***************************************************************************/
  680. int HitTestScrollBar(HWND hwnd, BOOL fVert, POINT pt)
  681. {
  682. UINT wDisable;
  683. int px;
  684. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  685. CUxScrollBarCtl* psbCtl = CUxScrollBarCtl::FromHwnd( hwnd );
  686. BOOL fCtl = psbCtl != NULL;
  687. SBCALC SBCalc = {0};
  688. SBCALC *pSBCalc = NULL;
  689. if (fCtl) {
  690. wDisable = psbCtl->_wDisableFlags;
  691. } else {
  692. RECT rcWindow;
  693. GetWindowRect( hwnd, &rcWindow );
  694. #ifdef USE_MIRRORING
  695. //
  696. // Reflect the click coordinates on the horizontal
  697. // scroll bar if the window is mirrored
  698. //
  699. if (TestWF(hwnd,WEFLAYOUTRTL) && !fVert) {
  700. pt.x = rcWindow.right - pt.x;
  701. }
  702. else
  703. #endif
  704. pt.x -= rcWindow.left;
  705. pt.y -= rcWindow.top;
  706. wDisable = _GetWndSBDisableFlags(hwnd, fVert);
  707. }
  708. if ((wDisable & SB_DISABLE_MASK) == SB_DISABLE_MASK) {
  709. return HTERROR;
  710. }
  711. if (fCtl) {
  712. pSBCalc = CUxScrollBarCtl::GetCalc(hwnd);
  713. } else {
  714. pSBCalc = &SBCalc;
  715. psb->FreshenSBData( SB_BOTH, FALSE );
  716. psb->Calc(hwnd, pSBCalc, NULL, fVert);
  717. }
  718. px = fVert ? pt.y : pt.x;
  719. if( pSBCalc )
  720. {
  721. if (px < pSBCalc->pxUpArrow) {
  722. if (wDisable & LTUPFLAG) {
  723. return HTERROR;
  724. }
  725. return HTSCROLLUP;
  726. } else if (px >= pSBCalc->pxDownArrow) {
  727. if (wDisable & RTDNFLAG) {
  728. return HTERROR;
  729. }
  730. return HTSCROLLDOWN;
  731. } else if (px < pSBCalc->pxThumbTop) {
  732. return HTSCROLLUPPAGE;
  733. } else if (px < pSBCalc->pxThumbBottom) {
  734. return HTSCROLLTHUMB;
  735. } else if (px < pSBCalc->pxDownArrow) {
  736. return HTSCROLLDOWNPAGE;
  737. }
  738. }
  739. return HTERROR;
  740. }
  741. BOOL _SBGetParms(
  742. HWND hwnd,
  743. int code,
  744. PSBDATA pw,
  745. LPSCROLLINFO lpsi)
  746. {
  747. PSBTRACK pSBTrack;
  748. pSBTrack = CUxScrollBar::GetSBTrack(hwnd);
  749. if (lpsi->fMask & SIF_RANGE) {
  750. lpsi->nMin = pw->posMin;
  751. lpsi->nMax = pw->posMax;
  752. }
  753. if (lpsi->fMask & SIF_PAGE)
  754. lpsi->nPage = pw->page;
  755. if (lpsi->fMask & SIF_POS) {
  756. lpsi->nPos = pw->pos;
  757. }
  758. if (lpsi->fMask & SIF_TRACKPOS)
  759. {
  760. if (pSBTrack && (pSBTrack->nBar == code) && (pSBTrack->hwndTrack == hwnd)) {
  761. // posNew is in the context of psbiSB's window and bar code
  762. lpsi->nTrackPos = pSBTrack->posNew;
  763. } else {
  764. lpsi->nTrackPos = pw->pos;
  765. }
  766. }
  767. return ((lpsi->fMask & SIF_ALL) ? TRUE : FALSE);
  768. }
  769. //-------------------------------------------------------------------------//
  770. BOOL WINAPI ThemeGetScrollInfo( HWND hwnd, int nBar, LPSCROLLINFO psi )
  771. {
  772. CUxScrollBar* psb = CUxScrollBar::FromHwnd(hwnd);
  773. if((psb != NULL) && (psb->IsAttaching() == FALSE))
  774. {
  775. #ifdef DEBUG
  776. if( psb->IsCtl() )
  777. {
  778. ASSERT(FALSE); // controls cooperate through an SBM_GETSCROLLINFO message.
  779. }
  780. else
  781. #endif DEBUG
  782. {
  783. SBINFO* psbi;
  784. if( (psbi = psb->GetInfo()) != NULL )
  785. {
  786. SBDATA* psbd = SB_VERT == nBar ? &psbi->Vert :
  787. SB_HORZ == nBar ? &psbi->Horz : NULL;
  788. if( psbd )
  789. return _SBGetParms( hwnd, nBar, psbd, psi );
  790. }
  791. }
  792. }
  793. return FALSE;
  794. }
  795. /***************************************************************************\
  796. * _GetWndSBDisableFlags
  797. *
  798. * This returns the scroll bar Disable flags of the scroll bars of a
  799. * given Window.
  800. *
  801. *
  802. * History:
  803. * 4-18-91 MikeHar Ported for the 31 merge
  804. \***************************************************************************/
  805. UINT _GetWndSBDisableFlags(
  806. HWND hwnd, // The window whose scroll bar Disable Flags are to be returned;
  807. BOOL fVert) // If this is TRUE, it means Vertical scroll bar.
  808. {
  809. PSBINFO pw;
  810. if ((pw = CUxScrollBar::GetSBInfo( hwnd )) == NULL) {
  811. RIPERR0(ERROR_NO_SCROLLBARS, RIP_VERBOSE, "");
  812. return 0;
  813. }
  814. return (fVert ? (pw->WSBflags & WSB_VERT) >> 2 : pw->WSBflags & WSB_HORZ);
  815. }
  816. /***************************************************************************\
  817. * xxxEnableSBCtlArrows()
  818. *
  819. * This function can be used to selectively Enable/Disable
  820. * the arrows of a scroll bar Control
  821. *
  822. * History:
  823. * 04-18-91 MikeHar Ported for the 31 merge
  824. \***************************************************************************/
  825. BOOL xxxEnableSBCtlArrows(
  826. HWND hwnd,
  827. UINT wArrows)
  828. {
  829. UINT wOldFlags = CUxScrollBarCtl::GetDisableFlags( hwnd ); // Get the original status
  830. BOOL bChanged = FALSE;
  831. if (wArrows == ESB_ENABLE_BOTH) { // Enable both the arrows
  832. bChanged = CUxScrollBarCtl::AddRemoveDisableFlags( hwnd, 0, SB_DISABLE_MASK );
  833. } else {
  834. bChanged = CUxScrollBarCtl::AddRemoveDisableFlags( hwnd, wArrows, 0 );
  835. }
  836. /*
  837. * Check if the status has changed because of this call
  838. */
  839. if (!bChanged)
  840. return FALSE;
  841. /*
  842. * Else, redraw the scroll bar control to reflect the new state
  843. */
  844. if (IsWindowVisible(hwnd))
  845. InvalidateRect(hwnd, NULL, TRUE);
  846. UINT wNewFlags = CUxScrollBarCtl::GetDisableFlags(hwnd);
  847. // state change notifications
  848. if ((wOldFlags & ESB_DISABLE_UP) != (wNewFlags & ESB_DISABLE_UP))
  849. {
  850. NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_CLIENT, INDEX_SCROLLBAR_UP);
  851. }
  852. if ((wOldFlags & ESB_DISABLE_DOWN) != (wNewFlags & ESB_DISABLE_DOWN))
  853. {
  854. NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_CLIENT, INDEX_SCROLLBAR_DOWN);
  855. }
  856. return TRUE;
  857. }
  858. /***************************************************************************\
  859. * xxxEnableWndSBArrows()
  860. *
  861. * This function can be used to selectively Enable/Disable
  862. * the arrows of a Window Scroll bar(s)
  863. *
  864. * History:
  865. * 4-18-91 MikeHar Ported for the 31 merge
  866. \***************************************************************************/
  867. BOOL xxxEnableWndSBArrows(
  868. HWND hwnd,
  869. UINT wSBflags,
  870. UINT wArrows)
  871. {
  872. INT wOldFlags;
  873. PSBINFO pw;
  874. BOOL bRetValue = FALSE;
  875. HDC hdc;
  876. CheckLock(hwnd);
  877. ASSERT(IsWinEventNotifyDeferredOK());
  878. if ((pw = CUxScrollBar::GetSBInfo( hwnd )) != NULL)
  879. {
  880. wOldFlags = pw->WSBflags;
  881. }
  882. else
  883. {
  884. // Originally everything is enabled; Check to see if this function is
  885. // asked to disable anything; Otherwise, no change in status; So, must
  886. // return immediately;
  887. if(!wArrows)
  888. return FALSE; // No change in status!
  889. wOldFlags = 0; // Both are originally enabled;
  890. CUxScrollBar::Attach( hwnd, FALSE, FALSE );
  891. if((pw = CUxScrollBar::GetSBInfo(hwnd)) == NULL) // Allocate the pSBInfo for hWnd
  892. return FALSE;
  893. }
  894. hdc = GetWindowDC(hwnd);
  895. if (hdc != NULL)
  896. {
  897. /*
  898. * First Take care of the Horizontal Scroll bar, if one exists.
  899. */
  900. if((wSBflags == SB_HORZ) || (wSBflags == SB_BOTH)) {
  901. if(wArrows == ESB_ENABLE_BOTH) // Enable both the arrows
  902. pw->WSBflags &= ~SB_DISABLE_MASK;
  903. else
  904. pw->WSBflags |= wArrows;
  905. /*
  906. * Update the display of the Horizontal Scroll Bar;
  907. */
  908. if(pw->WSBflags != wOldFlags) {
  909. bRetValue = TRUE;
  910. wOldFlags = pw->WSBflags;
  911. if (TestWF(hwnd, WFHPRESENT) && !TestWF(hwnd, WFMINIMIZED) &&
  912. IsWindowVisible(hwnd)) {
  913. DrawScrollBar(hwnd, hdc, NULL, FALSE); // Horizontal Scroll Bar.
  914. }
  915. }
  916. // Left button
  917. if ((wOldFlags & ESB_DISABLE_LEFT) != (pw->WSBflags & ESB_DISABLE_LEFT))
  918. {
  919. NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_HSCROLL, INDEX_SCROLLBAR_UP);
  920. }
  921. // Right button
  922. if ((wOldFlags & ESB_DISABLE_RIGHT) != (pw->WSBflags & ESB_DISABLE_RIGHT))
  923. {
  924. NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_HSCROLL, INDEX_SCROLLBAR_DOWN);
  925. }
  926. }
  927. // Then take care of the Vertical Scroll bar, if one exists.
  928. if ((wSBflags == SB_VERT) || (wSBflags == SB_BOTH))
  929. {
  930. if (wArrows == ESB_ENABLE_BOTH)
  931. {
  932. // Enable both the arrows
  933. pw->WSBflags &= ~(SB_DISABLE_MASK << 2);
  934. }
  935. else
  936. {
  937. pw->WSBflags |= (wArrows << 2);
  938. }
  939. // Update the display of the Vertical Scroll Bar;
  940. if(pw->WSBflags != wOldFlags)
  941. {
  942. bRetValue = TRUE;
  943. if (TestWF(hwnd, WFVPRESENT) && !TestWF(hwnd, WFMINIMIZED) && IsWindowVisible(hwnd))
  944. {
  945. // Vertical Scroll Bar
  946. DrawScrollBar(hwnd, hdc, NULL, TRUE);
  947. }
  948. // Up button
  949. if ((wOldFlags & (ESB_DISABLE_UP << 2)) != (pw->WSBflags & (ESB_DISABLE_UP << 2)))
  950. {
  951. NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_VSCROLL, INDEX_SCROLLBAR_UP);
  952. }
  953. // Down button
  954. if ((wOldFlags & (ESB_DISABLE_DOWN << 2)) != (pw->WSBflags & (ESB_DISABLE_DOWN << 2)))
  955. {
  956. NotifyWinEvent(EVENT_OBJECT_STATECHANGE, hwnd, OBJID_VSCROLL, INDEX_SCROLLBAR_DOWN);
  957. }
  958. }
  959. }
  960. ReleaseDC(hwnd,hdc);
  961. }
  962. return bRetValue;
  963. }
  964. /***************************************************************************\
  965. * EnableScrollBar()
  966. *
  967. * This function can be used to selectively Enable/Disable
  968. * the arrows of a scroll bar; It could be used with Windows Scroll
  969. * bars as well as scroll bar controls
  970. *
  971. * History:
  972. * 4-18-91 MikeHar Ported for the 31 merge
  973. \***************************************************************************/
  974. BOOL xxxEnableScrollBar(
  975. HWND hwnd,
  976. UINT wSBflags, // Whether it is a Window Scroll Bar; if so, HORZ or VERT?
  977. // Possible values are SB_HORZ, SB_VERT, SB_CTL or SB_BOTH
  978. UINT wArrows) // Which arrows must be enabled/disabled:
  979. // ESB_ENABLE_BOTH = > Enable both arrows.
  980. // ESB_DISABLE_LTUP = > Disable Left/Up arrow;
  981. // ESB_DISABLE_RTDN = > DIsable Right/Down arrow;
  982. // ESB_DISABLE_BOTH = > Disable both the arrows;
  983. {
  984. #define ES_NOTHING 0
  985. #define ES_DISABLE 1
  986. #define ES_ENABLE 2
  987. UINT wOldFlags;
  988. UINT wEnableWindow;
  989. CheckLock(hwnd);
  990. if(wSBflags != SB_CTL) {
  991. return xxxEnableWndSBArrows(hwnd, wSBflags, wArrows);
  992. }
  993. /*
  994. * Let us assume that we don't have to call EnableWindow
  995. */
  996. wEnableWindow = ES_NOTHING;
  997. wOldFlags = CUxScrollBarCtl::GetDisableFlags( hwnd ) & (UINT)SB_DISABLE_MASK;
  998. /*
  999. * Check if the present state of the arrows is exactly the same
  1000. * as what the caller wants:
  1001. */
  1002. if (wOldFlags == wArrows)
  1003. return FALSE ; // If so, nothing needs to be done;
  1004. /*
  1005. * Check if the caller wants to disable both the arrows
  1006. */
  1007. if (wArrows == ESB_DISABLE_BOTH) {
  1008. wEnableWindow = ES_DISABLE; // Yes! So, disable the whole SB Ctl.
  1009. } else {
  1010. /*
  1011. * Check if the caller wants to enable both the arrows
  1012. */
  1013. if(wArrows == ESB_ENABLE_BOTH) {
  1014. /*
  1015. * We need to enable the SB Ctl only if it was already disabled.
  1016. */
  1017. if(wOldFlags == ESB_DISABLE_BOTH)
  1018. wEnableWindow = ES_ENABLE;// EnableWindow(.., TRUE);
  1019. } else {
  1020. /*
  1021. * Now, Caller wants to disable only one arrow;
  1022. * Check if one of the arrows was already disabled and we want
  1023. * to disable the other;If so, the whole SB Ctl will have to be
  1024. * disabled; Check if this is the case:
  1025. */
  1026. if((wOldFlags | wArrows) == ESB_DISABLE_BOTH)
  1027. wEnableWindow = ES_DISABLE; // EnableWindow(, FALSE);
  1028. }
  1029. }
  1030. if(wEnableWindow != ES_NOTHING) {
  1031. /*
  1032. * EnableWindow returns old state of the window; We must return
  1033. * TRUE only if the Old state is different from new state.
  1034. */
  1035. if(EnableWindow(hwnd, (BOOL)(wEnableWindow == ES_ENABLE))) {
  1036. return !(TestWF(hwnd, WFDISABLED));
  1037. } else {
  1038. return TestWF(hwnd, WFDISABLED);
  1039. }
  1040. }
  1041. return (BOOL)SendMessage(hwnd, SBM_ENABLE_ARROWS, (DWORD)wArrows, 0);
  1042. #undef ES_NOTHING
  1043. #undef ES_DISABLE
  1044. #undef ES_ENABLE
  1045. }
  1046. //-------------------------------------------------------------------------
  1047. BOOL WINAPI ThemeEnableScrollBar( HWND hwnd, UINT nSBFlags, UINT nArrows )
  1048. {
  1049. return xxxEnableScrollBar( hwnd, nSBFlags, nArrows );
  1050. }
  1051. //-------------------------------------------------------------------------
  1052. //
  1053. // DrawSizeBox() - paints the scrollbar sizebox/gripper given top, left
  1054. // point in window coords.
  1055. //
  1056. void DrawSizeBox(HWND hwnd, HDC hdc, int x, int y)
  1057. {
  1058. RECT rc;
  1059. SetRect(&rc, x, y, x + SYSMET(CXVSCROLL), y + SYSMET(CYHSCROLL));
  1060. FillRect(hdc, &rc, GetSysColorBrush(COLOR_3DFACE));
  1061. //
  1062. // If we have a scrollbar control, or the sizebox is not associated with
  1063. // a sizeable window, draw the flat gray sizebox. Otherwise, use the
  1064. // sizing grip.
  1065. //
  1066. if ((IsScrollBarControl(hwnd) && TestWF(hwnd, SBFSIZEGRIP)) || SizeBoxHwnd(hwnd))
  1067. {
  1068. HTHEME hTheme = CUxScrollBar::GetSBTheme(hwnd);
  1069. if (!hTheme)
  1070. {
  1071. // Blt out the grip bitmap.
  1072. DrawFrameControl( hdc, &rc, DFC_SCROLL,
  1073. TestWF(hwnd, WEFLEFTSCROLL) ? DFCS_SCROLLSIZEGRIPRIGHT : DFCS_SCROLLSIZEGRIP );
  1074. //user: BitBltSysBmp(hdc, x, y, TestWF(hwnd, WEFLEFTSCROLL) ? OBI_NCGRIP_L : OBI_NCGRIP);
  1075. }
  1076. else
  1077. {
  1078. DrawThemeBackground(hTheme, hdc, SBP_SIZEBOX, TestWF(hwnd, WEFLEFTSCROLL) ? SZB_LEFTALIGN : SZB_RIGHTALIGN, &rc, 0);
  1079. }
  1080. }
  1081. }
  1082. //-------------------------------------------------------------------------
  1083. //
  1084. // _DrawSizeBoxFromFrame
  1085. //
  1086. // Calculates position and draws of sizebox/gripper at fixed offset from
  1087. // perimeter of host window frame.
  1088. //
  1089. // This, combined with implementation of DrawSizeBox(),
  1090. // was the original DrawSize() port. Needed to expost method to
  1091. // draw sizebox at absolute position. [scotthan]
  1092. //
  1093. void _DrawSizeBoxFromFrame(HWND hwnd, HDC hdc, int cxFrame,int cyFrame )
  1094. {
  1095. int x, y;
  1096. RECT rcWindow;
  1097. GetWindowRect(hwnd, &rcWindow);
  1098. if (TestWF(hwnd, WEFLEFTSCROLL))
  1099. {
  1100. x = cxFrame;
  1101. }
  1102. else
  1103. {
  1104. x = rcWindow.right - rcWindow.left - cxFrame - SYSMET(CXVSCROLL);
  1105. }
  1106. y = rcWindow.bottom - rcWindow.top - cyFrame - SYSMET(CYHSCROLL);
  1107. DrawSizeBox(hwnd, hdc, x, y);
  1108. }
  1109. //-------------------------------------------------------------------------
  1110. HBRUSH ScrollBar_GetControlColor(
  1111. HWND hwndOwner,
  1112. HWND hwndCtl,
  1113. HDC hdc,
  1114. UINT uMsg,
  1115. BOOL* pfOwnerBrush)
  1116. {
  1117. HBRUSH hbrRet = (HBRUSH)DefWindowProc(hwndOwner, uMsg, (WPARAM)hdc, (LPARAM)hwndCtl);
  1118. BOOL fOwnerBrush = FALSE;
  1119. if (hwndOwner && (GetWindowThreadProcessId(hwndOwner, NULL) == GetCurrentThreadId()))
  1120. {
  1121. HBRUSH hbrOwner = (HBRUSH)SendMessage(hwndOwner, uMsg, (WPARAM)hdc, (LPARAM)hwndCtl);
  1122. if (hbrOwner && (hbrOwner != hbrRet))
  1123. {
  1124. fOwnerBrush = TRUE;
  1125. hbrRet = hbrOwner;
  1126. }
  1127. }
  1128. if (pfOwnerBrush)
  1129. {
  1130. *pfOwnerBrush = fOwnerBrush;
  1131. }
  1132. return hbrRet;
  1133. }
  1134. //-------------------------------------------------------------------------
  1135. HBRUSH ScrollBar_GetControlBrush(HWND hwnd, HDC hdc, UINT uMsg, BOOL *pfOwnerBrush)
  1136. {
  1137. HWND hwndSend;
  1138. hwndSend = TESTFLAG(GetWindowStyle(hwnd), WS_POPUP) ? GetOwner(hwnd) : GetParent(hwnd);
  1139. if (hwndSend == NULL)
  1140. {
  1141. hwndSend = hwnd;
  1142. }
  1143. return ScrollBar_GetControlColor(hwndSend, hwnd, hdc, uMsg, pfOwnerBrush);
  1144. }
  1145. //-------------------------------------------------------------------------
  1146. HBRUSH ScrollBar_GetColorObjects(HWND hwnd, HDC hdc, BOOL *pfOwnerBrush)
  1147. {
  1148. HBRUSH hbrRet;
  1149. CheckLock(hwnd);
  1150. // Use the scrollbar color even if the scrollbar is disabeld.
  1151. if (!IsScrollBarControl(hwnd))
  1152. {
  1153. hbrRet = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLORSCROLLBAR, (WPARAM)hdc, (LPARAM)HWq(hwnd));
  1154. }
  1155. else
  1156. {
  1157. // B#12770 - GetControlBrush sends a WM_CTLCOLOR message to the
  1158. // owner. If the app doesn't process the message, DefWindowProc32
  1159. // will always return the appropriate system brush. If the app.
  1160. // returns an invalid object, GetControlBrush will call DWP for
  1161. // the default brush. Thus hbrRet doesn't need any validation
  1162. // here.
  1163. hbrRet = ScrollBar_GetControlBrush(hwnd, hdc, WM_CTLCOLORSCROLLBAR, pfOwnerBrush);
  1164. }
  1165. return hbrRet;
  1166. }
  1167. //-------------------------------------------------------------------------
  1168. //
  1169. // ScrollBar_PaintTrack
  1170. //
  1171. // Draws lines & middle of thumb groove
  1172. // Note that pw points into prc. Moreover, note that both pw & prc are
  1173. // pointers, so *prc better not be on the stack.
  1174. //
  1175. void ScrollBar_PaintTrack(HWND hwnd, HDC hdc, HBRUSH hbr, LPRECT prc, BOOL fVert, INT iPartId, BOOL fOwnerBrush)
  1176. {
  1177. HTHEME hTheme = CUxScrollBar::GetSBTheme(hwnd);
  1178. // If the scrollbar is unthemed or
  1179. // #374054 we've been passed an brush defined by the owner, paint
  1180. // the shaft using the brush
  1181. if ((hTheme == NULL) || (fOwnerBrush == TRUE))
  1182. {
  1183. if ((hbr == SYSHBR(3DHILIGHT)) || (hbr == SYSHBR(SCROLLBAR)) || (hbr == _UxGrayBrush()) )
  1184. {
  1185. FillRect(hdc, prc, hbr);
  1186. }
  1187. else
  1188. {
  1189. #ifdef PORTPORT // we need SystemParametersInfo for _UxGrayBrush
  1190. // Draw sides
  1191. CopyRect(&rc, prc);
  1192. DrawEdge(hdc, &rc, EDGE_SUNKEN, BF_ADJUST | BF_FLAT |
  1193. (fVert ? BF_LEFT | BF_RIGHT : BF_TOP | BF_BOTTOM));
  1194. #endif PORTPORT
  1195. // Fill middle
  1196. FillRect(hdc, prc, hbr);
  1197. }
  1198. }
  1199. else
  1200. {
  1201. INT iStateId;
  1202. INT ht = CUxScrollBar::GetSBHotComponent(hwnd, fVert);
  1203. if ((CUxScrollBarCtl::GetDisableFlags(hwnd) & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
  1204. {
  1205. iStateId = SCRBS_DISABLED;
  1206. }
  1207. else if ((((iPartId == SBP_LOWERTRACKHORZ) || (iPartId == SBP_LOWERTRACKVERT)) && (ht == HTSCROLLUPPAGE)) ||
  1208. (((iPartId == SBP_UPPERTRACKHORZ) || (iPartId == SBP_UPPERTRACKVERT)) && (ht == HTSCROLLDOWNPAGE)))
  1209. {
  1210. iStateId = SCRBS_HOT;
  1211. }
  1212. else
  1213. {
  1214. iStateId = SCRBS_NORMAL;
  1215. }
  1216. DrawThemeBackground(hTheme, hdc, iPartId, iStateId, prc, 0);
  1217. }
  1218. }
  1219. /***************************************************************************\
  1220. * CalcTrackDragRect
  1221. *
  1222. * Give the rectangle for a scrollbar in pSBTrack->pSBCalc,
  1223. * calculate pSBTrack->rcTrack, the rectangle where tracking
  1224. * may occur without cancelling the thumbdrag operation.
  1225. *
  1226. \***************************************************************************/
  1227. void CalcTrackDragRect(PSBTRACK pSBTrack) {
  1228. int cx;
  1229. int cy;
  1230. LPINT pwX, pwY;
  1231. //
  1232. // Point pwX and pwY at the parts of the rectangle
  1233. // corresponding to pSBCalc->pxLeft, pxTop, etc.
  1234. //
  1235. // pSBTrack->pSBCalc->pxLeft is the left edge of a vertical
  1236. // scrollbar and the top edge of horizontal one.
  1237. // pSBTrack->pSBCalc->pxTop is the top of a vertical
  1238. // scrollbar and the left of horizontal one.
  1239. // etc...
  1240. //
  1241. // Point pwX and pwY to the corresponding parts
  1242. // of pSBTrack->rcTrack.
  1243. //
  1244. pwX = pwY = (LPINT)&pSBTrack->rcTrack;
  1245. if (pSBTrack->fTrackVert) {
  1246. cy = SYSMET(CYVTHUMB);
  1247. pwY++;
  1248. } else {
  1249. cy = SYSMET(CXHTHUMB);
  1250. pwX++;
  1251. }
  1252. /*
  1253. * Later5.0 GerardoB: People keep complaining about this tracking region
  1254. * being too narrow so let's make it wider while PM decides what to do
  1255. * about it.
  1256. * We also used to have some hard coded min and max values but that should
  1257. * depend on some metric, if at all needed.
  1258. */
  1259. cx = (pSBTrack->pSBCalc->pxRight - pSBTrack->pSBCalc->pxLeft) * 8;
  1260. cy *= 2;
  1261. *(pwX + 0) = pSBTrack->pSBCalc->pxLeft - cx;
  1262. *(pwY + 0) = pSBTrack->pSBCalc->pxTop - cy;
  1263. *(pwX + 2) = pSBTrack->pSBCalc->pxRight + cx;
  1264. *(pwY + 2) = pSBTrack->pSBCalc->pxBottom + cy;
  1265. }
  1266. void RecalcTrackRect(PSBTRACK pSBTrack) {
  1267. LPINT pwX, pwY;
  1268. RECT rcSB;
  1269. if (!pSBTrack->fCtlSB)
  1270. CUxScrollBar::Calc(pSBTrack->hwndTrack, pSBTrack->pSBCalc, NULL, pSBTrack->fTrackVert);
  1271. pwX = (LPINT)&rcSB;
  1272. pwY = pwX + 1;
  1273. if (!pSBTrack->fTrackVert)
  1274. pwX = pwY--;
  1275. *(pwX + 0) = pSBTrack->pSBCalc->pxLeft;
  1276. *(pwY + 0) = pSBTrack->pSBCalc->pxTop;
  1277. *(pwX + 2) = pSBTrack->pSBCalc->pxRight;
  1278. *(pwY + 2) = pSBTrack->pSBCalc->pxBottom;
  1279. switch(pSBTrack->cmdSB) {
  1280. case SB_LINEUP:
  1281. *(pwY + 2) = pSBTrack->pSBCalc->pxUpArrow;
  1282. break;
  1283. case SB_LINEDOWN:
  1284. *(pwY + 0) = pSBTrack->pSBCalc->pxDownArrow;
  1285. break;
  1286. case SB_PAGEUP:
  1287. *(pwY + 0) = pSBTrack->pSBCalc->pxUpArrow;
  1288. *(pwY + 2) = pSBTrack->pSBCalc->pxThumbTop;
  1289. break;
  1290. case SB_THUMBPOSITION:
  1291. CalcTrackDragRect(pSBTrack);
  1292. break;
  1293. case SB_PAGEDOWN:
  1294. *(pwY + 0) = pSBTrack->pSBCalc->pxThumbBottom;
  1295. *(pwY + 2) = pSBTrack->pSBCalc->pxDownArrow;
  1296. break;
  1297. }
  1298. if (pSBTrack->cmdSB != SB_THUMBPOSITION) {
  1299. CopyRect(&pSBTrack->rcTrack, &rcSB);
  1300. }
  1301. }
  1302. //-------------------------------------------------------------------------
  1303. void DrawThumb2(
  1304. HWND hwnd,
  1305. PSBCALC pSBCalc,
  1306. HDC hdc,
  1307. HBRUSH hbr,
  1308. BOOL fVert,
  1309. UINT wDisable, // Disabled flags for the scroll bar
  1310. BOOL fOwnerBrush)
  1311. {
  1312. int *pLength;
  1313. int *pWidth;
  1314. RECT rcSB;
  1315. PSBTRACK pSBTrack;
  1316. HTHEME hTheme = CUxScrollBar::GetSBTheme(hwnd);
  1317. //
  1318. // Bail out if the scrollbar has an empty rect
  1319. //
  1320. if ((pSBCalc->pxTop >= pSBCalc->pxBottom) || (pSBCalc->pxLeft >= pSBCalc->pxRight))
  1321. {
  1322. return;
  1323. }
  1324. pLength = (LPINT)&rcSB;
  1325. if (fVert)
  1326. {
  1327. pWidth = pLength++;
  1328. }
  1329. else
  1330. {
  1331. pWidth = pLength + 1;
  1332. }
  1333. pWidth[0] = pSBCalc->pxLeft;
  1334. pWidth[2] = pSBCalc->pxRight;
  1335. // If were're not themed and both buttons are disabled OR there isn't
  1336. // enough room to draw a thumb just draw the track and run.
  1337. //
  1338. // When we are themed the thumb can be drawn disabled.
  1339. if (((wDisable & LTUPFLAG) && (wDisable & RTDNFLAG)) ||
  1340. ((pSBCalc->pxDownArrow - pSBCalc->pxUpArrow) < pSBCalc->cpxThumb))
  1341. {
  1342. // draw the entire track
  1343. pLength[0] = pSBCalc->pxUpArrow;
  1344. pLength[2] = pSBCalc->pxDownArrow;
  1345. ScrollBar_PaintTrack(hwnd, hdc, hbr, &rcSB, fVert, fVert ? SBP_LOWERTRACKVERT : SBP_LOWERTRACKHORZ, fOwnerBrush);
  1346. return;
  1347. }
  1348. if (pSBCalc->pxUpArrow < pSBCalc->pxThumbTop)
  1349. {
  1350. // draw the track above the thumb
  1351. pLength[0] = pSBCalc->pxUpArrow;
  1352. pLength[2] = pSBCalc->pxThumbTop;
  1353. ScrollBar_PaintTrack(hwnd, hdc, hbr, &rcSB, fVert, fVert ? SBP_LOWERTRACKVERT : SBP_LOWERTRACKHORZ, fOwnerBrush);
  1354. }
  1355. if (pSBCalc->pxThumbBottom < pSBCalc->pxDownArrow)
  1356. {
  1357. // draw the track below the thumb
  1358. pLength[0] = pSBCalc->pxThumbBottom;
  1359. pLength[2] = pSBCalc->pxDownArrow;
  1360. ScrollBar_PaintTrack(hwnd, hdc, hbr, &rcSB, fVert, fVert ? SBP_UPPERTRACKVERT : SBP_UPPERTRACKHORZ, fOwnerBrush);
  1361. }
  1362. //
  1363. // Draw elevator
  1364. //
  1365. pLength[0] = pSBCalc->pxThumbTop;
  1366. pLength[2] = pSBCalc->pxThumbBottom;
  1367. // Not soft!
  1368. _DrawPushButton(hwnd, hdc, &rcSB, 0, 0, fVert);
  1369. #ifdef _VISUAL_DELTA_
  1370. InflateRect( &rcSB, -CARET_BORDERWIDTH, -CARET_BORDERWIDTH);
  1371. DrawEdge( hdc, &rcSB, EDGE_SUNKEN, BF_RECT );
  1372. #endif _VISUAL_DELTA_
  1373. /*
  1374. * If we're tracking a page scroll, then we've obliterated the hilite.
  1375. * We need to correct the hiliting rectangle, and rehilite it.
  1376. */
  1377. pSBTrack = CUxScrollBar::GetSBTrack(hwnd);
  1378. if (pSBTrack && (pSBTrack->cmdSB == SB_PAGEUP || pSBTrack->cmdSB == SB_PAGEDOWN) &&
  1379. (hwnd == pSBTrack->hwndTrack) &&
  1380. (BOOL)pSBTrack->fTrackVert == fVert) {
  1381. if (pSBTrack->fTrackRecalc) {
  1382. RecalcTrackRect(pSBTrack);
  1383. pSBTrack->fTrackRecalc = FALSE;
  1384. }
  1385. pLength = (int *)&pSBTrack->rcTrack;
  1386. if (fVert)
  1387. pLength++;
  1388. if (pSBTrack->cmdSB == SB_PAGEUP)
  1389. pLength[2] = pSBCalc->pxThumbTop;
  1390. else
  1391. pLength[0] = pSBCalc->pxThumbBottom;
  1392. if (pLength[0] < pLength[2])
  1393. {
  1394. if (!hTheme)
  1395. {
  1396. InvertRect(hdc, &pSBTrack->rcTrack);
  1397. }
  1398. else
  1399. {
  1400. DrawThemeBackground(hTheme,
  1401. hdc,
  1402. pSBTrack->cmdSB == SB_PAGEUP ?
  1403. (fVert ? SBP_LOWERTRACKVERT : SBP_LOWERTRACKHORZ) :
  1404. (fVert ? SBP_UPPERTRACKVERT : SBP_UPPERTRACKHORZ),
  1405. SCRBS_PRESSED,
  1406. &pSBTrack->rcTrack,
  1407. 0);
  1408. }
  1409. }
  1410. }
  1411. }
  1412. /***************************************************************************\
  1413. * xxxDrawSB2
  1414. *
  1415. *
  1416. *
  1417. * History:
  1418. \***************************************************************************/
  1419. void xxxDrawSB2(
  1420. HWND hwnd,
  1421. PSBCALC pSBCalc,
  1422. HDC hdc,
  1423. BOOL fVert,
  1424. UINT wDisable)
  1425. {
  1426. int cLength;
  1427. int cWidth;
  1428. int *pwX;
  1429. int *pwY;
  1430. HBRUSH hbr;
  1431. HBRUSH hbrSave;
  1432. int cpxArrow;
  1433. RECT rc, rcSB;
  1434. COLORREF crText, crBk;
  1435. HTHEME hTheme;
  1436. INT ht;
  1437. INT iStateId;
  1438. BOOL fOwnerBrush = FALSE;
  1439. CheckLock(hwnd);
  1440. cLength = (pSBCalc->pxBottom - pSBCalc->pxTop) / 2;
  1441. cWidth = (pSBCalc->pxRight - pSBCalc->pxLeft);
  1442. if ((cLength <= 0) || (cWidth <= 0)) {
  1443. return;
  1444. }
  1445. if (fVert)
  1446. {
  1447. cpxArrow = SYSMET(CYVSCROLL);
  1448. }
  1449. else
  1450. {
  1451. cpxArrow = SYSMET(CXHSCROLL);
  1452. }
  1453. // Save background and DC color, since they get changed in
  1454. // ScrollBar_GetColorObjects. Restore before we return.
  1455. crBk = GetBkColor(hdc);
  1456. crText = GetTextColor(hdc);
  1457. hbr = ScrollBar_GetColorObjects(hwnd, hdc, &fOwnerBrush);
  1458. if (cLength > cpxArrow)
  1459. {
  1460. cLength = cpxArrow;
  1461. }
  1462. pwX = (int *)&rcSB;
  1463. pwY = pwX + 1;
  1464. if (!fVert)
  1465. {
  1466. pwX = pwY--;
  1467. }
  1468. pwX[0] = pSBCalc->pxLeft;
  1469. pwY[0] = pSBCalc->pxTop;
  1470. pwX[2] = pSBCalc->pxRight;
  1471. pwY[2] = pSBCalc->pxBottom;
  1472. hbrSave = SelectBrush(hdc, SYSHBR(BTNTEXT));
  1473. //
  1474. // BOGUS
  1475. // Draw scrollbar arrows as disabled if the scrollbar itself is
  1476. // disabled OR if the window it is a part of is disabled?
  1477. //
  1478. hTheme = CUxScrollBar::GetSBTheme(hwnd);
  1479. ht = CUxScrollBar::GetSBHotComponent(hwnd, fVert);
  1480. if (fVert)
  1481. {
  1482. // up button
  1483. CopyRect(&rc, &rcSB);
  1484. rc.bottom = rc.top + cLength;
  1485. if (!hTheme)
  1486. {
  1487. DrawFrameControl(hdc, &rc, DFC_SCROLL,
  1488. DFCS_SCROLLUP | ((wDisable & LTUPFLAG) ? DFCS_INACTIVE : 0));
  1489. }
  1490. else
  1491. {
  1492. iStateId = (wDisable & LTUPFLAG) ? ABS_UPDISABLED : (ht == HTSCROLLUP) ? ABS_UPHOT : ABS_UPNORMAL;
  1493. DrawThemeBackground(hTheme, hdc, SBP_ARROWBTN, iStateId, &rc, 0);
  1494. }
  1495. // down button
  1496. rc.bottom = rcSB.bottom;
  1497. rc.top = rcSB.bottom - cLength;
  1498. if (!hTheme)
  1499. {
  1500. DrawFrameControl(hdc, &rc, DFC_SCROLL,
  1501. DFCS_SCROLLDOWN | ((wDisable & RTDNFLAG) ? DFCS_INACTIVE : 0));
  1502. }
  1503. else
  1504. {
  1505. iStateId = (wDisable & RTDNFLAG) ? ABS_DOWNDISABLED : (ht == HTSCROLLDOWN) ? ABS_DOWNHOT : ABS_DOWNNORMAL;
  1506. DrawThemeBackground(hTheme, hdc, SBP_ARROWBTN, iStateId, &rc, 0);
  1507. }
  1508. }
  1509. else
  1510. {
  1511. // left button
  1512. CopyRect(&rc, &rcSB);
  1513. rc.right = rc.left + cLength;
  1514. if (!hTheme)
  1515. {
  1516. DrawFrameControl(hdc, &rc, DFC_SCROLL,
  1517. DFCS_SCROLLLEFT | ((wDisable & LTUPFLAG) ? DFCS_INACTIVE : 0));
  1518. }
  1519. else
  1520. {
  1521. iStateId = (wDisable & LTUPFLAG) ? ABS_LEFTDISABLED : (ht == HTSCROLLUP) ? ABS_LEFTHOT : ABS_LEFTNORMAL;
  1522. DrawThemeBackground(hTheme, hdc, SBP_ARROWBTN, iStateId, &rc, 0);
  1523. }
  1524. // right button
  1525. rc.right = rcSB.right;
  1526. rc.left = rcSB.right - cLength;
  1527. if (!hTheme)
  1528. {
  1529. DrawFrameControl(hdc, &rc, DFC_SCROLL,
  1530. DFCS_SCROLLRIGHT | ((wDisable & RTDNFLAG) ? DFCS_INACTIVE : 0));
  1531. }
  1532. else
  1533. {
  1534. iStateId = (wDisable & RTDNFLAG) ? ABS_RIGHTDISABLED : (ht == HTSCROLLDOWN) ? ABS_RIGHTHOT : ABS_RIGHTNORMAL;
  1535. DrawThemeBackground(hTheme, hdc, SBP_ARROWBTN, iStateId, &rc, 0);
  1536. }
  1537. }
  1538. hbrSave = SelectBrush(hdc, hbrSave);
  1539. DrawThumb2(hwnd, pSBCalc, hdc, hbr, fVert, wDisable, fOwnerBrush);
  1540. SelectBrush(hdc, hbrSave);
  1541. SetBkColor(hdc, crBk);
  1542. SetTextColor(hdc, crText);
  1543. }
  1544. /***************************************************************************\
  1545. * zzzSetSBCaretPos
  1546. *
  1547. *
  1548. *
  1549. * History:
  1550. \***************************************************************************/
  1551. void zzzSetSBCaretPos(
  1552. SBHWND hwndSB)
  1553. {
  1554. if (GetFocus() == hwndSB) {
  1555. CUxScrollBarCtl* psb = CUxScrollBarCtl::FromHwnd( hwndSB );
  1556. if( psb )
  1557. {
  1558. int x = (psb->_fVert ? psb->_calc.pxLeft : psb->_calc.pxThumbTop) + SYSMET(CXEDGE);
  1559. int y = (psb->_fVert ? psb->_calc.pxThumbTop : psb->_calc.pxLeft) + SYSMET(CYEDGE);
  1560. #ifdef _VISUAL_DELTA_
  1561. x += CARET_BORDERWIDTH;
  1562. y += CARET_BORDERWIDTH;
  1563. #endif _VISUAL_DELTA_
  1564. SetCaretPos( x, y );
  1565. }
  1566. }
  1567. }
  1568. /***************************************************************************\
  1569. * SBCtlSetup
  1570. *
  1571. *
  1572. *
  1573. * History:
  1574. \***************************************************************************/
  1575. CUxScrollBarCtl* SBCtlSetup(
  1576. SBHWND hwndSB)
  1577. {
  1578. RECT rc;
  1579. GetClientRect( hwndSB, &rc );
  1580. CUxScrollBarCtl* psb = (CUxScrollBarCtl*)CUxScrollBar::Attach( hwndSB, TRUE, FALSE );
  1581. if( psb )
  1582. {
  1583. psb->Calc2( &psb->_calc, &rc, &psb->_calc.data, psb->_fVert );
  1584. }
  1585. return psb;
  1586. }
  1587. /***************************************************************************\
  1588. * HotTrackSB
  1589. *
  1590. \***************************************************************************/
  1591. #ifdef COLOR_HOTTRACKING
  1592. DWORD GetTrackFlags(int ht, BOOL fDraw)
  1593. {
  1594. if (fDraw) {
  1595. switch(ht) {
  1596. case HTSCROLLUP:
  1597. case HTSCROLLUPPAGE:
  1598. return LTUPFLAG;
  1599. case HTSCROLLDOWN:
  1600. case HTSCROLLDOWNPAGE:
  1601. return RTDNFLAG;
  1602. case HTSCROLLTHUMB:
  1603. return LTUPFLAG | RTDNFLAG;
  1604. default:
  1605. return 0;
  1606. }
  1607. } else {
  1608. return 0;
  1609. }
  1610. }
  1611. void xxxHotTrackSBCtl(SBHWND hwndSB, int ht, BOOL fDraw)
  1612. {
  1613. DWORD dwTrack = GetTrackFlags(ht, fDraw);
  1614. HDC hdc;
  1615. CheckLock(hwndSB);
  1616. SBCtlSetup(hwndSB);
  1617. hdc = _GetDCEx((HWND)hwndSB, NULL, DCX_WINDOW | DCX_USESTYLE | DCX_CACHE);
  1618. xxxDrawSB2((HWND)hwndSB, &psb->_calc, hdc, psb->_fVert, psb->_wDisableFlags, dwTrack);
  1619. ReleaseDC(hwnd, hdc);
  1620. }
  1621. #endif // COLOR_HOTTRACKING
  1622. BOOL SBSetParms(PSBDATA pw, LPSCROLLINFO lpsi, LPBOOL lpfScroll, LPLONG lplres)
  1623. {
  1624. // pass the struct because we modify the struct but don't want that
  1625. // modified version to get back to the calling app
  1626. BOOL fChanged = FALSE;
  1627. if (lpsi->fMask & SIF_RETURNOLDPOS)
  1628. // save previous position
  1629. *lplres = pw->pos;
  1630. if (lpsi->fMask & SIF_RANGE) {
  1631. // if the range MAX is below the range MIN -- then treat is as a
  1632. // zero range starting at the range MIN.
  1633. if (lpsi->nMax < lpsi->nMin)
  1634. lpsi->nMax = lpsi->nMin;
  1635. if ((pw->posMin != lpsi->nMin) || (pw->posMax != lpsi->nMax)) {
  1636. pw->posMin = lpsi->nMin;
  1637. pw->posMax = lpsi->nMax;
  1638. if (!(lpsi->fMask & SIF_PAGE)) {
  1639. lpsi->fMask |= SIF_PAGE;
  1640. lpsi->nPage = pw->page;
  1641. }
  1642. if (!(lpsi->fMask & SIF_POS)) {
  1643. lpsi->fMask |= SIF_POS;
  1644. lpsi->nPos = pw->pos;
  1645. }
  1646. fChanged = TRUE;
  1647. }
  1648. }
  1649. if (lpsi->fMask & SIF_PAGE) {
  1650. DWORD dwMaxPage = (DWORD) abs(pw->posMax - pw->posMin) + 1;
  1651. // Clip page to 0, posMax - posMin + 1
  1652. if (lpsi->nPage > dwMaxPage)
  1653. lpsi->nPage = dwMaxPage;
  1654. if (pw->page != (int)(lpsi->nPage)) {
  1655. pw->page = lpsi->nPage;
  1656. if (!(lpsi->fMask & SIF_POS)) {
  1657. lpsi->fMask |= SIF_POS;
  1658. lpsi->nPos = pw->pos;
  1659. }
  1660. fChanged = TRUE;
  1661. }
  1662. }
  1663. if (lpsi->fMask & SIF_POS) {
  1664. int iMaxPos = pw->posMax - ((pw->page) ? pw->page - 1 : 0);
  1665. // Clip pos to posMin, posMax - (page - 1).
  1666. if (lpsi->nPos < pw->posMin)
  1667. lpsi->nPos = pw->posMin;
  1668. else if (lpsi->nPos > iMaxPos)
  1669. lpsi->nPos = iMaxPos;
  1670. if (pw->pos != lpsi->nPos) {
  1671. pw->pos = lpsi->nPos;
  1672. fChanged = TRUE;
  1673. }
  1674. }
  1675. if (!(lpsi->fMask & SIF_RETURNOLDPOS)) {
  1676. // Return the new position
  1677. *lplres = pw->pos;
  1678. }
  1679. /*
  1680. * This was added by JimA as Cairo merge but will conflict
  1681. * with the documentation for SetScrollPos
  1682. */
  1683. /*
  1684. else if (*lplres == pw->pos)
  1685. *lplres = 0;
  1686. */
  1687. if (lpsi->fMask & SIF_RANGE) {
  1688. *lpfScroll = (pw->posMin != pw->posMax);
  1689. if (*lpfScroll)
  1690. goto checkPage;
  1691. } else if (lpsi->fMask & SIF_PAGE)
  1692. checkPage:
  1693. *lpfScroll = (pw->page <= (pw->posMax - pw->posMin));
  1694. return fChanged;
  1695. }
  1696. /***************************************************************************\
  1697. *
  1698. * DrawCtlThumb()
  1699. *
  1700. \***************************************************************************/
  1701. void DrawCtlThumb(SBHWND hwnd)
  1702. {
  1703. HBRUSH hbr, hbrSave;
  1704. HDC hdc = (HDC) GetWindowDC(hwnd);
  1705. if ( hdc != NULL )
  1706. {
  1707. CUxScrollBarCtl* psb = SBCtlSetup(hwnd);
  1708. if (psb)
  1709. {
  1710. BOOL fOwnerBrush = FALSE;
  1711. hbr = ScrollBar_GetColorObjects(hwnd, hdc, &fOwnerBrush);
  1712. hbrSave = SelectBrush(hdc, hbr);
  1713. DrawThumb2(hwnd, &psb->_calc, hdc, hbr, psb->_fVert, psb->_wDisableFlags, fOwnerBrush);
  1714. SelectBrush(hdc, hbrSave);
  1715. }
  1716. ReleaseDC(hwnd, hdc);
  1717. }
  1718. }
  1719. //-------------------------------------------------------------------------
  1720. void xxxDrawThumb(HWND hwnd, PSBCALC pSBCalc, BOOL fVert)
  1721. {
  1722. HBRUSH hbr, hbrSave;
  1723. HDC hdc;
  1724. UINT wDisableFlags;
  1725. SBCALC SBCalc;
  1726. CheckLock(hwnd);
  1727. if (!pSBCalc)
  1728. {
  1729. pSBCalc = &SBCalc;
  1730. }
  1731. CUxScrollBar::Calc( hwnd, pSBCalc, NULL, fVert );
  1732. wDisableFlags = _GetWndSBDisableFlags(hwnd, fVert);
  1733. hdc = GetWindowDC(hwnd);
  1734. if ( hdc != NULL )
  1735. {
  1736. BOOL fOwnerBrush = FALSE;
  1737. hbr = ScrollBar_GetColorObjects(hwnd, hdc, &fOwnerBrush);
  1738. hbrSave = SelectBrush(hdc, hbr);
  1739. DrawThumb2(hwnd, pSBCalc, hdc, hbr, fVert, wDisableFlags, fOwnerBrush);
  1740. SelectBrush(hdc, hbrSave);
  1741. ReleaseDC(hwnd, hdc);
  1742. }
  1743. }
  1744. //-------------------------------------------------------------------------
  1745. UINT _GetArrowEnableFlags(HWND hwnd, BOOL fVert)
  1746. {
  1747. SCROLLBARINFO sbi = {0};
  1748. UINT uFlags = ESB_ENABLE_BOTH;
  1749. sbi.cbSize = sizeof(sbi);
  1750. if ( GetScrollBarInfo(hwnd, fVert ? OBJID_VSCROLL : OBJID_HSCROLL, &sbi) )
  1751. {
  1752. if ( TESTFLAG(sbi.rgstate[INDEX_SCROLLBAR_UP], (STATE_SYSTEM_UNAVAILABLE|STATE_SYSTEM_INVISIBLE)) )
  1753. {
  1754. uFlags |= ESB_DISABLE_UP;
  1755. }
  1756. if ( TESTFLAG(sbi.rgstate[INDEX_SCROLLBAR_DOWN], (STATE_SYSTEM_UNAVAILABLE|STATE_SYSTEM_INVISIBLE)) )
  1757. {
  1758. uFlags |= ESB_DISABLE_DOWN;
  1759. }
  1760. }
  1761. return uFlags;
  1762. }
  1763. /***************************************************************************\
  1764. * _SetScrollBar
  1765. *
  1766. *
  1767. *
  1768. * History:
  1769. \***************************************************************************/
  1770. LONG _SetScrollBar(
  1771. HWND hwnd,
  1772. int code,
  1773. LPSCROLLINFO lpsi,
  1774. BOOL fRedraw)
  1775. {
  1776. BOOL fVert;
  1777. PSBDATA pw;
  1778. PSBINFO pSBInfo;
  1779. BOOL fOldScroll;
  1780. BOOL fScroll;
  1781. WORD wfScroll;
  1782. LONG lres;
  1783. BOOL fNewScroll;
  1784. CheckLock(hwnd);
  1785. ASSERT(IsWinEventNotifyDeferredOK());
  1786. if (fRedraw)
  1787. // window must be visible to redraw
  1788. fRedraw = IsWindowVisible(hwnd);
  1789. if (code == SB_CTL)
  1790. #ifdef FE_SB // xxxSetScrollBar()
  1791. // scroll bar control; send the control a message
  1792. if(GETPTI(hwnd)->TIF_flags & TIF_16BIT) {
  1793. //
  1794. // If the target application is 16bit apps, we don't pass win40's message.
  1795. // This fix for Ichitaro v6.3. It eats the message. It never forwards
  1796. // the un-processed messages to original windows procedure via
  1797. // CallWindowProc().
  1798. //
  1799. // Is this from xxxSetScrollPos() ?
  1800. if(lpsi->fMask == (SIF_POS|SIF_RETURNOLDPOS)) {
  1801. return (int)SendMessage(hwnd, SBM_SETPOS, lpsi->nPos, fRedraw);
  1802. // Is this from xxxSetScrollRange() ?
  1803. } else if(lpsi->fMask == SIF_RANGE) {
  1804. SendMessage(hwnd, SBM_SETRANGE, lpsi->nMin, lpsi->nMax);
  1805. return TRUE;
  1806. // Others...
  1807. } else {
  1808. return (LONG)SendMessage(hwnd, SBM_SETSCROLLINFO, (WPARAM) fRedraw, (LPARAM) lpsi);
  1809. }
  1810. } else {
  1811. return (LONG)SendMessage(hwnd, SBM_SETSCROLLINFO, (WPARAM) fRedraw, (LPARAM) lpsi);
  1812. }
  1813. #else
  1814. // scroll bar control; send the control a message
  1815. return (LONG)SendMessage(hwnd, SBM_SETSCROLLINFO, (WPARAM) fRedraw, (LPARAM) lpsi);
  1816. #endif // FE_SB
  1817. fVert = (code != SB_HORZ);
  1818. wfScroll = (WORD)((fVert) ? WFVSCROLL : WFHSCROLL);
  1819. fScroll = fOldScroll = (TestWF(hwnd, wfScroll)) ? TRUE : FALSE;
  1820. /*
  1821. * Don't do anything if we're setting position of a nonexistent scroll bar.
  1822. */
  1823. if (!(lpsi->fMask & SIF_RANGE) && !fOldScroll && (CUxScrollBar::GetSBInfo( hwnd ) == NULL)) {
  1824. RIPERR0(ERROR_NO_SCROLLBARS, RIP_VERBOSE, "");
  1825. return 0;
  1826. }
  1827. pSBInfo = CUxScrollBar::GetSBInfo( hwnd );
  1828. fNewScroll = !pSBInfo;
  1829. if (fNewScroll) {
  1830. CUxScrollBar* psb = CUxScrollBar::Attach( hwnd, FALSE, fRedraw );
  1831. if( NULL == psb )
  1832. return 0;
  1833. pSBInfo = psb->GetInfo();
  1834. }
  1835. pw = (fVert) ? &(pSBInfo->Vert) : &(pSBInfo->Horz);
  1836. if (!SBSetParms(pw, lpsi, &fScroll, &lres) && !fNewScroll)
  1837. {
  1838. // no change -- but if REDRAW is specified and there's a scrollbar,
  1839. // redraw the thumb
  1840. if (fOldScroll && fRedraw)
  1841. {
  1842. goto redrawAfterSet;
  1843. }
  1844. if (lpsi->fMask & SIF_DISABLENOSCROLL)
  1845. {
  1846. xxxEnableWndSBArrows(hwnd, code, _GetArrowEnableFlags(hwnd, fVert));
  1847. }
  1848. return lres;
  1849. }
  1850. ClrWF(hwnd, wfScroll);
  1851. if (fScroll)
  1852. SetWF(hwnd, wfScroll);
  1853. else if (!TestWF(hwnd, (WFHSCROLL | WFVSCROLL)))
  1854. {
  1855. // if neither scroll bar is set and both ranges are 0, then free up the
  1856. // scroll info
  1857. CUxScrollBar::Detach( hwnd );
  1858. }
  1859. if (lpsi->fMask & SIF_DISABLENOSCROLL)
  1860. {
  1861. if (fOldScroll)
  1862. {
  1863. SetWF(hwnd, wfScroll);
  1864. xxxEnableWndSBArrows(hwnd, code, _GetArrowEnableFlags(hwnd, fVert));
  1865. }
  1866. }
  1867. else if (fOldScroll ^ fScroll)
  1868. {
  1869. PSBTRACK pSBTrack = CUxScrollBar::GetSBTrack(hwnd);
  1870. if (pSBTrack && (hwnd == pSBTrack->hwndTrack))
  1871. {
  1872. pSBTrack->fTrackRecalc = TRUE;
  1873. }
  1874. _RedrawFrame(hwnd);
  1875. // Note: after xxx, pSBTrack may no longer be valid (but we return now)
  1876. return lres;
  1877. }
  1878. if (fScroll && fRedraw && (fVert ? TestWF(hwnd, WFVPRESENT) : TestWF(hwnd, WFHPRESENT)))
  1879. {
  1880. PSBTRACK pSBTrack;
  1881. redrawAfterSet:
  1882. NotifyWinEvent(EVENT_OBJECT_VALUECHANGE,
  1883. hwnd,
  1884. (fVert ? OBJID_VSCROLL : OBJID_HSCROLL),
  1885. INDEX_SCROLLBAR_SELF);
  1886. pSBTrack = CUxScrollBar::GetSBTrack(hwnd);
  1887. // Bail out if the caller is trying to change the position of
  1888. // a scrollbar that is in the middle of tracking. We'll hose
  1889. // TrackThumb() otherwise.
  1890. if (pSBTrack && (hwnd == pSBTrack->hwndTrack) &&
  1891. ((BOOL)(pSBTrack->fTrackVert) == fVert) &&
  1892. (pSBTrack->pfnSB == _TrackThumb)) {
  1893. return lres;
  1894. }
  1895. xxxDrawThumb(hwnd, NULL, fVert);
  1896. // Note: after xxx, pSBTrack may no longer be valid (but we return now)
  1897. }
  1898. return lres;
  1899. }
  1900. //-------------------------------------------------------------------------//
  1901. LONG WINAPI ThemeSetScrollInfo( HWND hwnd, int nBar, LPCSCROLLINFO psi, BOOL bRedraw )
  1902. {
  1903. return _SetScrollBar( hwnd, nBar, (LPSCROLLINFO)psi, bRedraw );
  1904. }
  1905. //-------------------------------------------------------------------------//
  1906. BOOL WINAPI ScrollBar_MouseMove( HWND hwnd, LPPOINT ppt, BOOL fVert )
  1907. {
  1908. BOOL fRet = FALSE;
  1909. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  1910. if (psb)
  1911. {
  1912. int htScroll = (ppt != NULL) ? HitTestScrollBar(hwnd, fVert, *ppt) : HTNOWHERE;
  1913. //
  1914. // Redraw the scroll bar if the mouse is over something different
  1915. //
  1916. if (htScroll != psb->GetHotComponent(fVert))
  1917. {
  1918. HDC hdc;
  1919. //
  1920. // save the hittest code of the Scrollbar element the mouse is
  1921. // currently over
  1922. //
  1923. psb->SetHotComponent(htScroll, fVert);
  1924. hdc = GetDCEx(hwnd, NULL, DCX_USESTYLE|DCX_WINDOW|DCX_LOCKWINDOWUPDATE);
  1925. if (hdc != NULL)
  1926. {
  1927. DrawScrollBar(hwnd, hdc, NULL, fVert);
  1928. ReleaseDC(hwnd, hdc);
  1929. }
  1930. fRet = TRUE;
  1931. }
  1932. }
  1933. return fRet;
  1934. }
  1935. //-------------------------------------------------------------------------//
  1936. void DrawScrollBar(HWND hwnd, HDC hdc, LPRECT prcOverrideClient, BOOL fVert)
  1937. {
  1938. SBCALC SBCalc = {0};
  1939. PSBCALC pSBCalc;
  1940. PSBTRACK pSBTrack = CUxScrollBar::GetSBTrack(hwnd);
  1941. CheckLock(hwnd);
  1942. if (pSBTrack && (hwnd == pSBTrack->hwndTrack) && (pSBTrack->fCtlSB == FALSE)
  1943. && (fVert == (BOOL)pSBTrack->fTrackVert))
  1944. {
  1945. pSBCalc = pSBTrack->pSBCalc;
  1946. }
  1947. else
  1948. {
  1949. pSBCalc = &SBCalc;
  1950. }
  1951. CUxScrollBar::Calc(hwnd, pSBCalc, prcOverrideClient, fVert);
  1952. xxxDrawSB2(hwnd, pSBCalc, hdc, fVert, _GetWndSBDisableFlags(hwnd, fVert));
  1953. }
  1954. /***************************************************************************\
  1955. * SBPosFromPx
  1956. *
  1957. * Compute scroll bar position from pixel location
  1958. *
  1959. * History:
  1960. \***************************************************************************/
  1961. int SBPosFromPx(
  1962. PSBCALC pSBCalc,
  1963. int px)
  1964. {
  1965. if (px < pSBCalc->pxMin) {
  1966. return pSBCalc->data.posMin;
  1967. }
  1968. if (px >= pSBCalc->pxMin + pSBCalc->cpx) {
  1969. return (pSBCalc->data.posMax - (pSBCalc->data.page ? pSBCalc->data.page - 1 : 0));
  1970. }
  1971. if (pSBCalc->cpx)
  1972. return (pSBCalc->data.posMin + MulDiv(pSBCalc->data.posMax - pSBCalc->data.posMin -
  1973. (pSBCalc->data.page ? pSBCalc->data.page - 1 : 0),
  1974. px - pSBCalc->pxMin, pSBCalc->cpx));
  1975. else
  1976. return (pSBCalc->data.posMin - 1);
  1977. }
  1978. /***************************************************************************\
  1979. * InvertScrollHilite
  1980. *
  1981. *
  1982. *
  1983. * History:
  1984. \***************************************************************************/
  1985. void InvertScrollHilite(
  1986. HWND hwnd,
  1987. PSBTRACK pSBTrack)
  1988. {
  1989. HDC hdc;
  1990. /*
  1991. * Don't invert if the thumb is all the way at the top or bottom
  1992. * or you will end up inverting the line between the arrow and the thumb.
  1993. */
  1994. if (!IsRectEmpty(&pSBTrack->rcTrack))
  1995. {
  1996. if (pSBTrack->fTrackRecalc) {
  1997. RecalcTrackRect(pSBTrack);
  1998. pSBTrack->fTrackRecalc = FALSE;
  1999. }
  2000. hdc = (HDC)GetWindowDC(hwnd);
  2001. if( hdc )
  2002. {
  2003. HTHEME hTheme = CUxScrollBar::GetSBTheme(hwnd);
  2004. if (!hTheme)
  2005. {
  2006. InvertRect(hdc, &pSBTrack->rcTrack);
  2007. }
  2008. else
  2009. {
  2010. DrawThemeBackground(hTheme,
  2011. hdc,
  2012. pSBTrack->cmdSB == SB_PAGEUP ?
  2013. (pSBTrack->fTrackVert ? SBP_LOWERTRACKVERT : SBP_LOWERTRACKHORZ) :
  2014. (pSBTrack->fTrackVert ? SBP_UPPERTRACKVERT : SBP_UPPERTRACKHORZ),
  2015. SCRBS_NORMAL,
  2016. &pSBTrack->rcTrack,
  2017. 0);
  2018. }
  2019. ReleaseDC(hwnd, hdc);
  2020. }
  2021. }
  2022. }
  2023. /***************************************************************************\
  2024. * xxxDoScroll
  2025. *
  2026. * Sends scroll notification to the scroll bar owner
  2027. *
  2028. * History:
  2029. \***************************************************************************/
  2030. void xxxDoScroll(
  2031. HWND hwnd,
  2032. HWND hwndNotify,
  2033. int cmd,
  2034. int pos,
  2035. BOOL fVert
  2036. )
  2037. {
  2038. //
  2039. // Send scroll notification to the scrollbar owner. If this is a control
  2040. // the lParam is the control's handle, NULL otherwise.
  2041. //
  2042. SendMessage(hwndNotify,
  2043. (UINT)(fVert ? WM_VSCROLL : WM_HSCROLL),
  2044. MAKELONG(cmd, pos),
  2045. (LPARAM)(IsScrollBarControl(hwnd) ? hwnd : NULL));
  2046. }
  2047. /***************************************************************************\
  2048. * xxxMoveThumb
  2049. *
  2050. * History:
  2051. \***************************************************************************/
  2052. void xxxMoveThumb(
  2053. HWND hwnd,
  2054. PSBCALC pSBCalc,
  2055. int px)
  2056. {
  2057. HBRUSH hbr, hbrSave;
  2058. HDC hdc;
  2059. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  2060. PSBTRACK pSBTrack = psb->GetTrack();
  2061. CheckLock(hwnd);
  2062. if ((pSBTrack == NULL) || (px == pSBTrack->pxOld))
  2063. return;
  2064. pxReCalc:
  2065. pSBTrack->posNew = SBPosFromPx(pSBCalc, px);
  2066. /* Tentative position changed -- notify the guy. */
  2067. if (pSBTrack->posNew != pSBTrack->posOld) {
  2068. if (pSBTrack->hwndSBNotify != NULL) {
  2069. psb->DoScroll(pSBTrack->hwndSBNotify, SB_THUMBTRACK, pSBTrack->posNew, pSBTrack->fTrackVert
  2070. );
  2071. }
  2072. // After xxxDoScroll, re-evaluate pSBTrack
  2073. REEVALUATE_PSBTRACK(pSBTrack, hwnd, "xxxMoveThumb(1)");
  2074. if ((pSBTrack == NULL) || (pSBTrack->pfnSB == NULL))
  2075. return;
  2076. pSBTrack->posOld = pSBTrack->posNew;
  2077. //
  2078. // Anything can happen after the SendMessage above!
  2079. // Make sure that the SBINFO structure contains data for the
  2080. // window being tracked -- if not, recalculate data in SBINFO
  2081. //
  2082. // CheckScrollRecalc(hwnd, pSBState, pSBCalc);
  2083. // when we yield, our range can get messed with
  2084. // so make sure we handle this
  2085. if (px >= pSBCalc->pxMin + pSBCalc->cpx)
  2086. {
  2087. px = pSBCalc->pxMin + pSBCalc->cpx;
  2088. goto pxReCalc;
  2089. }
  2090. }
  2091. hdc = GetWindowDC(hwnd);
  2092. if ( hdc != NULL )
  2093. {
  2094. BOOL fOwnerBrush = FALSE;
  2095. pSBCalc->pxThumbTop = px;
  2096. pSBCalc->pxThumbBottom = pSBCalc->pxThumbTop + pSBCalc->cpxThumb;
  2097. // at this point, the disable flags are always going to be 0 --
  2098. // we're in the middle of tracking.
  2099. hbr = ScrollBar_GetColorObjects(hwnd, hdc, &fOwnerBrush);
  2100. hbrSave = SelectBrush(hdc, hbr);
  2101. // After ScrollBar_GetColorObjects, re-evaluate pSBTrack
  2102. REEVALUATE_PSBTRACK(pSBTrack, hwnd, "xxxMoveThumb(2)");
  2103. if (pSBTrack == NULL)
  2104. {
  2105. RIPMSG1(RIP_ERROR, "Did we use to leak hdc %#p?", hdc) ;
  2106. ReleaseDC(hwnd, hdc);
  2107. return;
  2108. }
  2109. DrawThumb2(hwnd, pSBCalc, hdc, hbr, pSBTrack->fTrackVert, 0, fOwnerBrush);
  2110. SelectBrush(hdc, hbrSave);
  2111. ReleaseDC(hwnd, hdc);
  2112. }
  2113. pSBTrack->pxOld = px;
  2114. }
  2115. /***************************************************************************\
  2116. * zzzDrawInvertScrollArea
  2117. *
  2118. *
  2119. *
  2120. * History:
  2121. \***************************************************************************/
  2122. void zzzDrawInvertScrollArea(
  2123. HWND hwnd,
  2124. PSBTRACK pSBTrack,
  2125. BOOL fHit,
  2126. UINT cmd)
  2127. {
  2128. HDC hdc;
  2129. RECT rcTemp;
  2130. int cx, cy;
  2131. HTHEME hTheme;
  2132. if ((cmd != SB_LINEUP) && (cmd != SB_LINEDOWN))
  2133. {
  2134. // not hitting on arrow -- just invert the area and return
  2135. InvertScrollHilite(hwnd, pSBTrack);
  2136. if (cmd == SB_PAGEUP)
  2137. {
  2138. if (fHit)
  2139. SetWF(hwnd, WFPAGEUPBUTTONDOWN);
  2140. else
  2141. ClrWF(hwnd, WFPAGEUPBUTTONDOWN);
  2142. }
  2143. else
  2144. {
  2145. if (fHit)
  2146. SetWF(hwnd, WFPAGEDNBUTTONDOWN);
  2147. else
  2148. ClrWF(hwnd, WFPAGEDNBUTTONDOWN);
  2149. }
  2150. NotifyWinEvent(EVENT_OBJECT_STATECHANGE,
  2151. hwnd,
  2152. (pSBTrack->fCtlSB ? OBJID_CLIENT : (pSBTrack->fTrackVert ? OBJID_VSCROLL : OBJID_HSCROLL)),
  2153. ((cmd == SB_PAGEUP) ? INDEX_SCROLLBAR_UPPAGE : INDEX_SCROLLBAR_DOWNPAGE));
  2154. // Note: after zzz, pSBTrack may no longer be valid (but we return now)
  2155. return;
  2156. }
  2157. if (pSBTrack->fTrackRecalc) {
  2158. RecalcTrackRect(pSBTrack);
  2159. pSBTrack->fTrackRecalc = FALSE;
  2160. }
  2161. CopyRect(&rcTemp, &pSBTrack->rcTrack);
  2162. hdc = GetWindowDC(hwnd);
  2163. if( hdc != NULL )
  2164. {
  2165. if (pSBTrack->fTrackVert) {
  2166. cx = SYSMET(CXVSCROLL);
  2167. cy = SYSMET(CYVSCROLL);
  2168. } else {
  2169. cx = SYSMET(CXHSCROLL);
  2170. cy = SYSMET(CYHSCROLL);
  2171. }
  2172. hTheme = CUxScrollBar::GetSBTheme(hwnd);
  2173. if (!hTheme)
  2174. {
  2175. DrawFrameControl(hdc, &rcTemp, DFC_SCROLL,
  2176. ((pSBTrack->fTrackVert) ? DFCS_SCROLLVERT : DFCS_SCROLLHORZ) |
  2177. ((fHit) ? DFCS_PUSHED | DFCS_FLAT : 0) |
  2178. ((cmd == SB_LINEUP) ? DFCS_SCROLLMIN : DFCS_SCROLLMAX));
  2179. }
  2180. else
  2181. {
  2182. INT iStateId;
  2183. // Determine the pressed state of the button
  2184. iStateId = fHit ? SCRBS_PRESSED : SCRBS_NORMAL;
  2185. // Determine which kind of button it is.
  2186. // NOTE: (phellyar) this is dependant on the order of
  2187. // the ARROWBTNSTATE enum
  2188. if (pSBTrack->fTrackVert)
  2189. {
  2190. if (cmd == SB_LINEUP)
  2191. {
  2192. // Up button states are the first four entries
  2193. // in the enum
  2194. iStateId += 0;
  2195. }
  2196. else
  2197. {
  2198. // Down button states are the second four entries
  2199. // in the enum
  2200. iStateId += 4;
  2201. }
  2202. }
  2203. else
  2204. {
  2205. if (cmd == SB_LINEUP)
  2206. {
  2207. // Left button states are the third four entries
  2208. // in the enum
  2209. iStateId += 8;
  2210. }
  2211. else
  2212. {
  2213. // Right button states are the last four entries
  2214. // in the enum
  2215. iStateId += 12;
  2216. }
  2217. }
  2218. DrawThemeBackground(hTheme, hdc, SBP_ARROWBTN, iStateId, &rcTemp, 0);
  2219. }
  2220. ReleaseDC(hwnd, hdc);
  2221. }
  2222. if (cmd == SB_LINEUP) {
  2223. if (fHit)
  2224. SetWF(hwnd, WFLINEUPBUTTONDOWN);
  2225. else
  2226. ClrWF(hwnd, WFLINEUPBUTTONDOWN);
  2227. } else {
  2228. if (fHit)
  2229. SetWF(hwnd, WFLINEDNBUTTONDOWN);
  2230. else
  2231. ClrWF(hwnd, WFLINEDNBUTTONDOWN);
  2232. }
  2233. NotifyWinEvent(EVENT_OBJECT_STATECHANGE,
  2234. hwnd,
  2235. (pSBTrack->fCtlSB ? OBJID_CLIENT : (pSBTrack->fTrackVert ? OBJID_VSCROLL : OBJID_HSCROLL)),
  2236. (cmd == SB_LINEUP ? INDEX_SCROLLBAR_UP : INDEX_SCROLLBAR_DOWN));
  2237. // Note: after zzz, pSBTrack may no longer be valid (but we return now)
  2238. }
  2239. /***************************************************************************\
  2240. * xxxEndScroll
  2241. *
  2242. *
  2243. *
  2244. * History:
  2245. \***************************************************************************/
  2246. void xxxEndScroll(
  2247. HWND hwnd,
  2248. BOOL fCancel)
  2249. {
  2250. UINT oldcmd;
  2251. PSBTRACK pSBTrack;
  2252. CheckLock(hwnd);
  2253. ASSERT(!IsWinEventNotifyDeferred());
  2254. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  2255. ASSERT(psb != NULL);
  2256. pSBTrack = psb->GetTrack();
  2257. if (pSBTrack && GetCapture() == hwnd && pSBTrack->pfnSB != NULL) {
  2258. oldcmd = pSBTrack->cmdSB;
  2259. pSBTrack->cmdSB = 0;
  2260. ReleaseCapture();
  2261. // After ReleaseCapture, revalidate pSBTrack
  2262. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2263. if (pSBTrack->pfnSB == _TrackThumb) {
  2264. if (fCancel) {
  2265. pSBTrack->posOld = pSBTrack->pSBCalc->data.pos;
  2266. }
  2267. /*
  2268. * DoScroll does thread locking on these two pwnds -
  2269. * this is ok since they are not used after this
  2270. * call.
  2271. */
  2272. if (pSBTrack->hwndSBNotify != NULL) {
  2273. psb->DoScroll( pSBTrack->hwndSBNotify,
  2274. SB_THUMBPOSITION, pSBTrack->posOld, pSBTrack->fTrackVert
  2275. );
  2276. // After xxxDoScroll, revalidate pSBTrack
  2277. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2278. }
  2279. if (pSBTrack->fCtlSB) {
  2280. DrawCtlThumb((SBHWND) hwnd);
  2281. } else {
  2282. xxxDrawThumb(hwnd, pSBTrack->pSBCalc, pSBTrack->fTrackVert);
  2283. // Note: after xxx, pSBTrack may no longer be valid
  2284. }
  2285. } else if (pSBTrack->pfnSB == _TrackBox) {
  2286. DWORD lParam;
  2287. POINT ptMsg;
  2288. RECT rcWindow;
  2289. if (pSBTrack->hTimerSB != 0) {
  2290. _KillSystemTimer(hwnd, IDSYS_SCROLL);
  2291. pSBTrack->hTimerSB = 0;
  2292. }
  2293. lParam = GetMessagePos();
  2294. GetWindowRect( hwnd, &rcWindow );
  2295. #ifdef USE_MIRRORING
  2296. if (TestWF(hwnd, WEFLAYOUTRTL)) {
  2297. ptMsg.x = rcWindow.right - GET_X_LPARAM(lParam);
  2298. } else
  2299. #endif
  2300. {
  2301. ptMsg.x = GET_X_LPARAM(lParam) - rcWindow.left;
  2302. }
  2303. ptMsg.y = GET_Y_LPARAM(lParam) - rcWindow.top;
  2304. if (PtInRect(&pSBTrack->rcTrack, ptMsg)) {
  2305. zzzDrawInvertScrollArea(hwnd, pSBTrack, FALSE, oldcmd);
  2306. // Note: after zzz, pSBTrack may no longer be valid
  2307. }
  2308. }
  2309. /*
  2310. * Always send SB_ENDSCROLL message.
  2311. *
  2312. * DoScroll does thread locking on these two pwnds -
  2313. * this is ok since they are not used after this
  2314. * call.
  2315. */
  2316. // After xxxDrawThumb or zzzDrawInvertScrollArea, revalidate pSBTrack
  2317. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2318. if (pSBTrack->hwndSBNotify != NULL) {
  2319. psb->DoScroll( pSBTrack->hwndSBNotify,
  2320. SB_ENDSCROLL, 0, pSBTrack->fTrackVert);
  2321. // After xxxDoScroll, revalidate pSBTrack
  2322. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2323. }
  2324. ClrWF(hwnd, WFSCROLLBUTTONDOWN);
  2325. ClrWF(hwnd, WFVERTSCROLLTRACK);
  2326. NotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND,
  2327. hwnd,
  2328. (pSBTrack->fCtlSB ? OBJID_CLIENT : (pSBTrack->fTrackVert ? OBJID_VSCROLL : OBJID_HSCROLL)),
  2329. INDEXID_CONTAINER);
  2330. // After NotifyWinEvent, revalidate pSBTrack
  2331. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2332. // If this is a Scroll Bar Control, turn the caret back on.
  2333. if (pSBTrack->hwndSB != NULL)
  2334. {
  2335. ShowCaret(pSBTrack->hwndSB);
  2336. // After zzz, revalidate pSBTrack
  2337. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2338. }
  2339. pSBTrack->pfnSB = NULL;
  2340. /*
  2341. * Unlock structure members so they are no longer holding down windows.
  2342. */
  2343. Unlock(&pSBTrack->hwndSB);
  2344. Unlock(&pSBTrack->hwndSBNotify);
  2345. Unlock(&pSBTrack->hwndTrack);
  2346. CUxScrollBar::ClearSBTrack( hwnd );
  2347. }
  2348. }
  2349. //-------------------------------------------------------------------------//
  2350. VOID CALLBACK xxxContScroll(HWND hwnd, UINT message, UINT_PTR ID, DWORD dwTime)
  2351. {
  2352. UNREFERENCED_PARAMETER(message);
  2353. UNREFERENCED_PARAMETER(ID);
  2354. UNREFERENCED_PARAMETER(dwTime);
  2355. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  2356. if ( psb != NULL )
  2357. {
  2358. PSBTRACK pSBTrack = psb->GetTrack();
  2359. if ( pSBTrack != NULL )
  2360. {
  2361. LONG pt;
  2362. RECT rcWindow;
  2363. CheckLock(hwnd);
  2364. pt = GetMessagePos();
  2365. GetWindowRect( hwnd, &rcWindow );
  2366. if (TestWF(hwnd, WEFLAYOUTRTL))
  2367. {
  2368. pt = MAKELONG(rcWindow.right - GET_X_LPARAM(pt), GET_Y_LPARAM(pt) - rcWindow.top);
  2369. }
  2370. else
  2371. {
  2372. pt = MAKELONG( GET_X_LPARAM(pt) - rcWindow.left, GET_Y_LPARAM(pt) - rcWindow.top);
  2373. }
  2374. _TrackBox(hwnd, WM_NULL, 0, pt, NULL);
  2375. // After _TrackBox, revalidate pSBTrack
  2376. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2377. if (pSBTrack->fHitOld)
  2378. {
  2379. pSBTrack->hTimerSB = _SetSystemTimer(hwnd, IDSYS_SCROLL, DTTIME/8, xxxContScroll);
  2380. // DoScroll does thread locking on these two pwnds -
  2381. // this is ok since they are not used after this call.
  2382. if (pSBTrack->hwndSBNotify != NULL)
  2383. {
  2384. psb->DoScroll(pSBTrack->hwndSBNotify, pSBTrack->cmdSB, 0, pSBTrack->fTrackVert);
  2385. // Note: after xxx, pSBTrack may no longer be valid (but we return now)
  2386. }
  2387. }
  2388. }
  2389. }
  2390. }
  2391. //-------------------------------------------------------------------------//
  2392. void CALLBACK _TrackBox(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, PSBCALC pSBCalc)
  2393. {
  2394. CUxScrollBar* psb = CUxScrollBar::FromHwnd(hwnd);
  2395. UNREFERENCED_PARAMETER(wParam);
  2396. UNREFERENCED_PARAMETER(pSBCalc);
  2397. CheckLock(hwnd);
  2398. ASSERT(IsWinEventNotifyDeferredOK());
  2399. if ( psb )
  2400. {
  2401. PSBTRACK pSBTrack = psb->GetTrack();
  2402. if ( pSBTrack )
  2403. {
  2404. BOOL fHit;
  2405. POINT ptHit;
  2406. int cmsTimer;
  2407. if ((uMsg != WM_NULL) && (HIBYTE(uMsg) != HIBYTE(WM_MOUSEFIRST)))
  2408. {
  2409. return;
  2410. }
  2411. if (pSBTrack->fTrackRecalc)
  2412. {
  2413. RecalcTrackRect(pSBTrack);
  2414. pSBTrack->fTrackRecalc = FALSE;
  2415. }
  2416. ptHit.x = GET_X_LPARAM(lParam);
  2417. ptHit.y = GET_Y_LPARAM(lParam);
  2418. fHit = PtInRect(&pSBTrack->rcTrack, ptHit);
  2419. if (fHit != (BOOL)pSBTrack->fHitOld)
  2420. {
  2421. zzzDrawInvertScrollArea(hwnd, pSBTrack, fHit, pSBTrack->cmdSB);
  2422. // After zzz, pSBTrack may no longer be valid
  2423. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2424. }
  2425. cmsTimer = DTTIME/8;
  2426. switch (uMsg)
  2427. {
  2428. case WM_LBUTTONUP:
  2429. xxxEndScroll(hwnd, FALSE);
  2430. // Note: after xxx, pSBTrack may no longer be valid
  2431. break;
  2432. case WM_LBUTTONDOWN:
  2433. pSBTrack->hTimerSB = 0;
  2434. cmsTimer = DTTIME;
  2435. //
  2436. // FALL THRU
  2437. //
  2438. case WM_MOUSEMOVE:
  2439. if (fHit && fHit != (BOOL)pSBTrack->fHitOld)
  2440. {
  2441. //
  2442. // We moved back into the normal rectangle: reset timer
  2443. //
  2444. pSBTrack->hTimerSB = _SetSystemTimer(hwnd, IDSYS_SCROLL,
  2445. cmsTimer, xxxContScroll);
  2446. //
  2447. // DoScroll does thread locking on these two pwnds -
  2448. // this is ok since they are not used after this
  2449. // call.
  2450. //
  2451. if (pSBTrack->hwndSBNotify != NULL)
  2452. {
  2453. psb->DoScroll( pSBTrack->hwndSBNotify, pSBTrack->cmdSB,
  2454. 0, pSBTrack->fTrackVert);
  2455. // Note: after xxx, pSBTrack may no longer be valid
  2456. }
  2457. }
  2458. break;
  2459. }
  2460. // After xxxDoScroll or xxxEndScroll, revalidate pSBTrack
  2461. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2462. pSBTrack->fHitOld = fHit;
  2463. }
  2464. }
  2465. }
  2466. /***************************************************************************\
  2467. * _TrackThumb
  2468. *
  2469. *
  2470. *
  2471. * History:
  2472. \***************************************************************************/
  2473. void CALLBACK _TrackThumb(
  2474. HWND hwnd,
  2475. UINT message,
  2476. WPARAM wParam,
  2477. LPARAM lParam,
  2478. PSBCALC pSBCalc)
  2479. {
  2480. int px;
  2481. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  2482. ASSERT(psb);
  2483. PSBTRACK pSBTrack = psb->GetTrack();
  2484. POINT pt;
  2485. UNREFERENCED_PARAMETER(wParam);
  2486. CheckLock(hwnd);
  2487. if (HIBYTE(message) != HIBYTE(WM_MOUSEFIRST))
  2488. return;
  2489. if (pSBTrack == NULL)
  2490. return;
  2491. // Make sure that the SBINFO structure contains data for the
  2492. // window being tracked -- if not, recalculate data in SBINFO
  2493. // CheckScrollRecalc(hwnd, pSBState, pSBCalc);
  2494. if (pSBTrack->fTrackRecalc) {
  2495. RecalcTrackRect(pSBTrack);
  2496. pSBTrack->fTrackRecalc = FALSE;
  2497. }
  2498. pt.y = GET_Y_LPARAM(lParam);
  2499. pt.x = GET_X_LPARAM(lParam);
  2500. if (!PtInRect(&pSBTrack->rcTrack, pt))
  2501. px = pSBCalc->pxStart;
  2502. else {
  2503. px = (pSBTrack->fTrackVert ? pt.y : pt.x) + pSBTrack->dpxThumb;
  2504. if (px < pSBCalc->pxMin)
  2505. px = pSBCalc->pxMin;
  2506. else if (px >= pSBCalc->pxMin + pSBCalc->cpx)
  2507. px = pSBCalc->pxMin + pSBCalc->cpx;
  2508. }
  2509. xxxMoveThumb(hwnd, pSBCalc, px);
  2510. /*
  2511. * We won't get the WM_LBUTTONUP message if we got here through
  2512. * the scroll menu, so test the button state directly.
  2513. */
  2514. if (message == WM_LBUTTONUP || GetKeyState(VK_LBUTTON) >= 0) {
  2515. xxxEndScroll(hwnd, FALSE);
  2516. }
  2517. }
  2518. /***************************************************************************\
  2519. * _ClientToWindow
  2520. * History:
  2521. \***************************************************************************/
  2522. BOOL _ClientToWindow( HWND hwnd, LPPOINT ppt )
  2523. {
  2524. WINDOWINFO wi;
  2525. wi.cbSize = sizeof(wi);
  2526. if( GetWindowInfo( hwnd, &wi ) )
  2527. {
  2528. ppt->x += (wi.rcClient.left - wi.rcWindow.left);
  2529. ppt->y += (wi.rcClient.top - wi.rcWindow.top);
  2530. return TRUE;
  2531. }
  2532. return FALSE;
  2533. }
  2534. /***************************************************************************\
  2535. * xxxSBTrackLoop
  2536. *
  2537. *
  2538. *
  2539. * History:
  2540. \***************************************************************************/
  2541. void xxxSBTrackLoop(
  2542. HWND hwnd,
  2543. LPARAM lParam,
  2544. PSBCALC pSBCalc)
  2545. {
  2546. MSG msg;
  2547. UINT cmd;
  2548. VOID (*pfnSB)(HWND, UINT, WPARAM, LPARAM, PSBCALC);
  2549. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  2550. PSBTRACK pSBTrack = psb->GetSBTrack(hwnd);
  2551. CheckLock(hwnd);
  2552. ASSERT(IsWinEventNotifyDeferredOK());
  2553. if (pSBTrack == NULL)
  2554. // mode cancelled -- exit track loop
  2555. return;
  2556. pfnSB = pSBTrack->pfnSB;
  2557. if (pfnSB == NULL)
  2558. // mode cancelled -- exit track loop
  2559. return;
  2560. if (pSBTrack->fTrackVert)
  2561. SetWF(hwnd, WFVERTSCROLLTRACK);
  2562. NotifyWinEvent(EVENT_SYSTEM_SCROLLINGSTART,
  2563. hwnd,
  2564. (pSBTrack->fCtlSB ? OBJID_CLIENT : (pSBTrack->fTrackVert ? OBJID_VSCROLL : OBJID_HSCROLL)),
  2565. INDEXID_CONTAINER);
  2566. // Note: after xxx, pSBTrack may no longer be valid
  2567. (*pfnSB)(hwnd, WM_LBUTTONDOWN, 0, lParam, pSBCalc);
  2568. // Note: after xxx, pSBTrack may no longer be valid
  2569. while (GetCapture() == hwnd) {
  2570. if (!GetMessage(&msg, NULL, 0, 0)) {
  2571. // Note: after xxx, pSBTrack may no longer be valid
  2572. break;
  2573. }
  2574. if (!CallMsgFilter(&msg, MSGF_SCROLLBAR))
  2575. {
  2576. BOOL bTrackMsg = FALSE;
  2577. cmd = msg.message;
  2578. lParam = msg.lParam;
  2579. if (msg.hwnd == HWq(hwnd))
  2580. {
  2581. if( cmd >= WM_MOUSEFIRST && cmd <= WM_MOUSELAST )
  2582. {
  2583. if( !psb->IsCtl() )
  2584. {
  2585. POINT pt;
  2586. pt.x = GET_X_LPARAM(msg.lParam);
  2587. pt.y = GET_Y_LPARAM(msg.lParam);
  2588. _ClientToWindow( hwnd, &pt );
  2589. lParam = MAKELPARAM(pt.x, pt.y);
  2590. }
  2591. bTrackMsg = TRUE;
  2592. }
  2593. else if( cmd >= WM_KEYFIRST && cmd <= WM_KEYLAST )
  2594. {
  2595. cmd = _SysToChar(cmd, msg.lParam);
  2596. bTrackMsg = TRUE;
  2597. }
  2598. }
  2599. if( bTrackMsg )
  2600. {
  2601. // After NotifyWinEvent, pfnSB, TranslateMessage or
  2602. // DispatchMessage, re-evaluate pSBTrack.
  2603. REEVALUATE_PSBTRACK(pSBTrack, hwnd, "xxxTrackLoop");
  2604. if ((pSBTrack == NULL) || (NULL == (pfnSB = pSBTrack->pfnSB)))
  2605. // mode cancelled -- exit track loop
  2606. return;
  2607. (*pfnSB)(hwnd, cmd, msg.wParam, lParam, pSBCalc);
  2608. }
  2609. else
  2610. {
  2611. TranslateMessage(&msg);
  2612. DispatchMessage(&msg);
  2613. }
  2614. }
  2615. }
  2616. }
  2617. /***************************************************************************\
  2618. * _SBTrackInit
  2619. *
  2620. * History:
  2621. \***************************************************************************/
  2622. void _SBTrackInit(
  2623. HWND hwnd,
  2624. LPARAM lParam,
  2625. int curArea,
  2626. UINT uType)
  2627. {
  2628. int px;
  2629. LPINT pwX;
  2630. LPINT pwY;
  2631. UINT wDisable; // Scroll bar disable flags;
  2632. SBCALC SBCalc = {0};
  2633. PSBCALC pSBCalc;
  2634. RECT rcSB;
  2635. PSBTRACK pSBTrack;
  2636. CheckLock(hwnd);
  2637. #ifdef PORTPORT // unneccessary dbgchk w/ port
  2638. if (CUxScrollBar::GetSBTrack(hwnd)) {
  2639. RIPMSG1(RIP_WARNING, "_SBTrackInit: CUxScrollBar::GetSBTrack(hwnd) == %#p",
  2640. CUxScrollBar::GetSBTrack(hwnd));
  2641. return;
  2642. }
  2643. #endif PORTPORT
  2644. CUxScrollBar* psb = CUxScrollBar::Attach( hwnd, !curArea, TRUE );
  2645. if (!psb)
  2646. {
  2647. return;
  2648. }
  2649. CUxScrollBarCtl* psbCtl = psb->IsCtl() ? (CUxScrollBarCtl*)psb : NULL;
  2650. pSBTrack = psb->GetTrack();
  2651. if (pSBTrack == NULL)
  2652. return;
  2653. pSBTrack->hTimerSB = 0;
  2654. pSBTrack->fHitOld = FALSE;
  2655. pSBTrack->pfnSB = _TrackBox;
  2656. pSBTrack->hwndTrack = NULL;
  2657. pSBTrack->hwndSB = NULL;
  2658. pSBTrack->hwndSBNotify = NULL;
  2659. Lock(&pSBTrack->hwndTrack, hwnd); // pSBTrack->hwndTrack = hwnd;
  2660. pSBTrack->fCtlSB = (!curArea);
  2661. if (pSBTrack->fCtlSB)
  2662. {
  2663. /*
  2664. * This is a scroll bar control.
  2665. */
  2666. ASSERT(psbCtl != NULL);
  2667. pSBTrack->hwndSB = hwnd; //Lock(&pSBTrack->hwndSB, hwnd);
  2668. pSBTrack->fTrackVert = psbCtl->_fVert;
  2669. Lock(&pSBTrack->hwndSBNotify, GetParent(hwnd)); // pSBTrack->hwndSBNotify = GetParent( hwnd );
  2670. wDisable = psbCtl->_wDisableFlags;
  2671. pSBCalc = &psbCtl->_calc;
  2672. pSBTrack->nBar = SB_CTL;
  2673. } else {
  2674. /*
  2675. * This is a scroll bar that is part of the window frame.
  2676. */
  2677. RECT rcWindow;
  2678. GetWindowRect( hwnd, &rcWindow );
  2679. int x = GET_X_LPARAM(lParam);
  2680. int y = GET_Y_LPARAM(lParam);
  2681. #ifdef USE_MIRRORING
  2682. //
  2683. // Mirror the window coord of the scroll bar,
  2684. // if it is a mirrored one
  2685. //
  2686. if (TestWF(hwnd,WEFLAYOUTRTL)) {
  2687. lParam = MAKELONG(
  2688. rcWindow.right - x,
  2689. y - rcWindow.top);
  2690. }
  2691. else {
  2692. #endif
  2693. lParam = MAKELONG( x - rcWindow.left, y - rcWindow.top);
  2694. #ifdef USE_MIRRORING
  2695. }
  2696. #endif
  2697. Lock(&pSBTrack->hwndSBNotify, hwnd); // pSBTrack->hwndSBNotify = hwnd; //
  2698. Lock(&pSBTrack->hwndSB, NULL); // pSBTrack->hwndSB = NULL;
  2699. pSBTrack->fTrackVert = (curArea - HTHSCROLL);
  2700. wDisable = _GetWndSBDisableFlags(hwnd, pSBTrack->fTrackVert);
  2701. pSBCalc = &SBCalc;
  2702. pSBTrack->nBar = (curArea - HTHSCROLL) ? SB_VERT : SB_HORZ;
  2703. }
  2704. pSBTrack->pSBCalc = pSBCalc;
  2705. /*
  2706. * Check if the whole scroll bar is disabled
  2707. */
  2708. if((wDisable & SB_DISABLE_MASK) == SB_DISABLE_MASK) {
  2709. CUxScrollBar::Detach( hwnd );
  2710. return; // It is a disabled scroll bar; So, do not respond.
  2711. }
  2712. if (!pSBTrack->fCtlSB) {
  2713. psb->FreshenSBData( pSBTrack->nBar, FALSE );
  2714. CUxScrollBar::Calc(hwnd, pSBCalc, NULL, pSBTrack->fTrackVert);
  2715. }
  2716. pwX = (LPINT)&rcSB;
  2717. pwY = pwX + 1;
  2718. if (!pSBTrack->fTrackVert)
  2719. pwX = pwY--;
  2720. px = (pSBTrack->fTrackVert ? GET_Y_LPARAM(lParam) : GET_X_LPARAM(lParam));
  2721. *(pwX + 0) = pSBCalc->pxLeft;
  2722. *(pwY + 0) = pSBCalc->pxTop;
  2723. *(pwX + 2) = pSBCalc->pxRight;
  2724. *(pwY + 2) = pSBCalc->pxBottom;
  2725. pSBTrack->cmdSB = (UINT)-1;
  2726. if (px < pSBCalc->pxUpArrow) {
  2727. /*
  2728. * The click occurred on Left/Up arrow; Check if it is disabled
  2729. */
  2730. if(wDisable & LTUPFLAG) {
  2731. if(pSBTrack->fCtlSB) { // If this is a scroll bar control,
  2732. ShowCaret(pSBTrack->hwndSB); // show the caret before returning;
  2733. // After ShowCaret, revalidate pSBTrack
  2734. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2735. }
  2736. CUxScrollBar::Detach( hwnd );
  2737. return; // Yes! disabled. Do not respond.
  2738. }
  2739. // LINEUP -- make rcSB the Up Arrow's Rectangle
  2740. pSBTrack->cmdSB = SB_LINEUP;
  2741. *(pwY + 2) = pSBCalc->pxUpArrow;
  2742. } else if (px >= pSBCalc->pxDownArrow) {
  2743. /*
  2744. * The click occurred on Right/Down arrow; Check if it is disabled
  2745. */
  2746. if (wDisable & RTDNFLAG) {
  2747. if (pSBTrack->fCtlSB) { // If this is a scroll bar control,
  2748. ShowCaret(pSBTrack->hwndSB); // show the caret before returning;
  2749. // After ShowCaret, revalidate pSBTrack
  2750. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2751. }
  2752. CUxScrollBar::Detach( hwnd );
  2753. return;// Yes! disabled. Do not respond.
  2754. }
  2755. // LINEDOWN -- make rcSB the Down Arrow's Rectangle
  2756. pSBTrack->cmdSB = SB_LINEDOWN;
  2757. *(pwY + 0) = pSBCalc->pxDownArrow;
  2758. } else if (px < pSBCalc->pxThumbTop) {
  2759. // PAGEUP -- make rcSB the rectangle between Up Arrow and Thumb
  2760. pSBTrack->cmdSB = SB_PAGEUP;
  2761. *(pwY + 0) = pSBCalc->pxUpArrow;
  2762. *(pwY + 2) = pSBCalc->pxThumbTop;
  2763. } else if (px < pSBCalc->pxThumbBottom) {
  2764. DoThumbPos:
  2765. /*
  2766. * Elevator isn't there if there's no room.
  2767. */
  2768. if (pSBCalc->pxDownArrow - pSBCalc->pxUpArrow <= pSBCalc->cpxThumb) {
  2769. CUxScrollBar::Detach( hwnd );
  2770. return;
  2771. }
  2772. // THUMBPOSITION -- we're tracking with the thumb
  2773. pSBTrack->cmdSB = SB_THUMBPOSITION;
  2774. CalcTrackDragRect(pSBTrack);
  2775. pSBTrack->pfnSB = _TrackThumb;
  2776. pSBTrack->pxOld = pSBCalc->pxStart = pSBCalc->pxThumbTop;
  2777. pSBTrack->posNew = pSBTrack->posOld = pSBCalc->data.pos;
  2778. pSBTrack->dpxThumb = pSBCalc->pxStart - px;
  2779. SetCapture( hwnd ); //xxxCapture(PtiCurrent(), hwnd, WINDOW_CAPTURE);
  2780. // After xxxCapture, revalidate pSBTrack
  2781. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2782. /*
  2783. * DoScroll does thread locking on these two pwnds -
  2784. * this is ok since they are not used after this
  2785. * call.
  2786. */
  2787. if (pSBTrack->hwndSBNotify != NULL) {
  2788. psb->DoScroll( pSBTrack->hwndSBNotify, SB_THUMBTRACK,
  2789. pSBTrack->posOld, pSBTrack->fTrackVert
  2790. );
  2791. // Note: after xxx, pSBTrack may no longer be valid
  2792. }
  2793. } else if (px < pSBCalc->pxDownArrow) {
  2794. // PAGEDOWN -- make rcSB the rectangle between Thumb and Down Arrow
  2795. pSBTrack->cmdSB = SB_PAGEDOWN;
  2796. *(pwY + 0) = pSBCalc->pxThumbBottom;
  2797. *(pwY + 2) = pSBCalc->pxDownArrow;
  2798. }
  2799. /*
  2800. * If the shift key is down, we'll position the thumb directly so it's
  2801. * centered on the click point.
  2802. */
  2803. if ((uType == SCROLL_DIRECT && pSBTrack->cmdSB != SB_LINEUP && pSBTrack->cmdSB != SB_LINEDOWN) ||
  2804. (uType == SCROLL_MENU)) {
  2805. if (pSBTrack->cmdSB != SB_THUMBPOSITION) {
  2806. goto DoThumbPos;
  2807. }
  2808. pSBTrack->dpxThumb = -(pSBCalc->cpxThumb / 2);
  2809. }
  2810. SetCapture( hwnd ); // xxxCapture(PtiCurrent(), hwnd, WINDOW_CAPTURE);
  2811. // After xxxCapture, revalidate pSBTrack
  2812. RETURN_IF_PSBTRACK_INVALID(pSBTrack, hwnd);
  2813. if (pSBTrack->cmdSB != SB_THUMBPOSITION) {
  2814. CopyRect(&pSBTrack->rcTrack, &rcSB);
  2815. }
  2816. xxxSBTrackLoop(hwnd, lParam, pSBCalc);
  2817. // After xxx, re-evaluate pSBTrack
  2818. REEVALUATE_PSBTRACK(pSBTrack, hwnd, "xxxTrackLoop");
  2819. if (pSBTrack)
  2820. {
  2821. CUxScrollBar::ClearSBTrack( hwnd );
  2822. }
  2823. }
  2824. /***************************************************************************\
  2825. * HandleScrollCmd
  2826. *
  2827. * History: added to support and encap SB tracking initialization originating
  2828. * from WM_SYSCOMMAND::SC_VSCROLL/SC_HSCROLL [scotthan]
  2829. \***************************************************************************/
  2830. void WINAPI HandleScrollCmd( HWND hwnd, WPARAM wParam, LPARAM lParam )
  2831. {
  2832. UINT uArea = (UINT)(wParam & 0x0F);
  2833. _SBTrackInit( hwnd, lParam, uArea,
  2834. (GetKeyState(VK_SHIFT) < 0) ? SCROLL_DIRECT : SCROLL_NORMAL);
  2835. }
  2836. //-------------------------------------------------------------------------
  2837. HMENU ScrollBar_GetMenu(HWND hwnd, BOOL fVert)
  2838. {
  2839. static HMODULE hModUser = NULL;
  2840. HMENU hMenu = NULL;
  2841. if ( !hModUser )
  2842. {
  2843. hModUser = GetModuleHandle(TEXT("user32"));
  2844. }
  2845. #define ID_HSCROLLMENU 0x40
  2846. #define ID_VSCROLLMENU 0x50
  2847. if ( hModUser )
  2848. {
  2849. hMenu = LoadMenu(hModUser, MAKEINTRESOURCE((fVert ? ID_VSCROLLMENU : ID_HSCROLLMENU)));
  2850. if ( hMenu )
  2851. {
  2852. hMenu = GetSubMenu(hMenu, 0);
  2853. }
  2854. }
  2855. return hMenu;
  2856. }
  2857. //-------------------------------------------------------------------------
  2858. VOID ScrollBar_Menu(HWND hwndNotify, HWND hwnd, LPARAM lParam, BOOL fVert)
  2859. {
  2860. CUxScrollBar* psb = CUxScrollBar::FromHwnd( hwnd );
  2861. CUxScrollBarCtl* psbCtl = CUxScrollBarCtl::FromHwnd( hwnd );
  2862. BOOL fCtl = (psbCtl != NULL);
  2863. if ( psb || psbCtl )
  2864. {
  2865. UINT wDisable;
  2866. RECT rcWindow;
  2867. POINT pt;
  2868. GetWindowRect(hwnd, &rcWindow);
  2869. POINTSTOPOINT(pt, lParam);
  2870. if ( TestWF(hwnd, WEFLAYOUTRTL) && !fVert )
  2871. {
  2872. MIRROR_POINT(rcWindow, pt);
  2873. }
  2874. pt.x -= rcWindow.left;
  2875. pt.y -= rcWindow.top;
  2876. if ( fCtl )
  2877. {
  2878. wDisable = psbCtl->_wDisableFlags;
  2879. }
  2880. else
  2881. {
  2882. wDisable = _GetWndSBDisableFlags(hwndNotify, fVert);
  2883. }
  2884. // Make sure the scrollbar isn't disabled.
  2885. if ( (wDisable & SB_DISABLE_MASK) != SB_DISABLE_MASK)
  2886. {
  2887. HMENU hMenu = ScrollBar_GetMenu(hwndNotify, fVert);
  2888. // Put up a menu and scroll accordingly.
  2889. if (hMenu != NULL)
  2890. {
  2891. int iCmd;
  2892. iCmd = TrackPopupMenuEx(hMenu,
  2893. TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY,
  2894. GET_X_LPARAM(lParam),
  2895. GET_Y_LPARAM(lParam),
  2896. hwndNotify,
  2897. NULL);
  2898. DestroyMenu(hMenu);
  2899. if (iCmd)
  2900. {
  2901. if ((iCmd & 0x00FF) == SB_THUMBPOSITION)
  2902. {
  2903. if ( fCtl )
  2904. {
  2905. _SBTrackInit(hwnd, MAKELPARAM(pt.x, pt.y), 0, SCROLL_MENU);
  2906. }
  2907. else
  2908. {
  2909. _SBTrackInit(hwndNotify, lParam, fVert ? HTVSCROLL : HTHSCROLL, SCROLL_MENU);
  2910. }
  2911. }
  2912. else
  2913. {
  2914. xxxDoScroll(hwnd, hwndNotify, (iCmd & 0x00FF), 0, fVert);
  2915. xxxDoScroll(hwnd, hwndNotify, SB_ENDSCROLL, 0, fVert);
  2916. }
  2917. }
  2918. }
  2919. }
  2920. }
  2921. }
  2922. //-------------------------------------------------------------------------
  2923. LRESULT CUxScrollBarCtl::WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  2924. {
  2925. LONG l;
  2926. LONG lres = 0;
  2927. int cx, cy;
  2928. UINT cmd;
  2929. UINT uSide;
  2930. HDC hdc;
  2931. RECT rc;
  2932. POINT pt;
  2933. BOOL fSizeReal;
  2934. HBRUSH hbrSave;
  2935. BOOL fSize;
  2936. PAINTSTRUCT ps;
  2937. DWORD dwStyle;
  2938. SCROLLINFO si;
  2939. LPSCROLLINFO lpsi = &si;
  2940. BOOL fRedraw = FALSE;
  2941. BOOL fScroll;
  2942. CUxScrollBarCtl* psb = CUxScrollBarCtl::FromHwnd( hwnd );
  2943. if (!psb && uMsg != WM_NCCREATE)
  2944. {
  2945. goto CallDWP;
  2946. }
  2947. CheckLock(hwnd);
  2948. ASSERT(IsWinEventNotifyDeferredOK());
  2949. VALIDATECLASSANDSIZE(((HWND)hwnd), uMsg, wParam, lParam, FNID_SCROLLBAR, WM_CREATE);
  2950. dwStyle = GetWindowStyle(hwnd);
  2951. fSize = (((LOBYTE(dwStyle)) & (SBS_SIZEBOX | SBS_SIZEGRIP)) != 0);
  2952. switch (uMsg)
  2953. {
  2954. case WM_NCCREATE:
  2955. if( NULL == psb )
  2956. {
  2957. psb = (CUxScrollBarCtl*)CUxScrollBar::Attach( hwnd, TRUE, FALSE );
  2958. }
  2959. goto CallDWP;
  2960. case WM_NCDESTROY:
  2961. CUxScrollBar::Detach(hwnd);
  2962. psb = NULL;
  2963. goto CallDWP;
  2964. case WM_CREATE:
  2965. /*
  2966. * Guard against lParam being NULL since the thunk allows it [51986]
  2967. */
  2968. if (lParam)
  2969. {
  2970. rc.right = (rc.left = ((LPCREATESTRUCT)lParam)->x) +
  2971. ((LPCREATESTRUCT)lParam)->cx;
  2972. rc.bottom = (rc.top = ((LPCREATESTRUCT)lParam)->y) +
  2973. ((LPCREATESTRUCT)lParam)->cy;
  2974. // This is because we can't just rev CardFile -- we should fix the
  2975. // problem here in case anyone else happened to have some EXTRA
  2976. // scroll styles on their scroll bar controls (jeffbog 03/21/94)
  2977. if (!TestWF((HWND)hwnd, WFWIN40COMPAT))
  2978. dwStyle &= ~(WS_HSCROLL | WS_VSCROLL);
  2979. if (!fSize)
  2980. {
  2981. l = PtrToLong(((LPCREATESTRUCT)lParam)->lpCreateParams);
  2982. psb->_calc.data.pos = psb->_calc.data.posMin = LOWORD(l);
  2983. psb->_calc.data.posMax = HIWORD(l);
  2984. psb->_fVert = ((LOBYTE(dwStyle) & SBS_VERT) != 0);
  2985. psb->_calc.data.page = 0;
  2986. }
  2987. if (dwStyle & WS_DISABLED)
  2988. psb->_wDisableFlags = SB_DISABLE_MASK;
  2989. if (LOBYTE(dwStyle) & (SBS_TOPALIGN | SBS_BOTTOMALIGN)) {
  2990. if (fSize) {
  2991. if (LOBYTE(dwStyle) & SBS_SIZEBOXBOTTOMRIGHTALIGN) {
  2992. rc.left = rc.right - SYSMET(CXVSCROLL);
  2993. rc.top = rc.bottom - SYSMET(CYHSCROLL);
  2994. }
  2995. rc.right = rc.left + SYSMET(CXVSCROLL);
  2996. rc.bottom = rc.top + SYSMET(CYHSCROLL);
  2997. } else {
  2998. if (LOBYTE(dwStyle) & SBS_VERT) {
  2999. if (LOBYTE(dwStyle) & SBS_LEFTALIGN)
  3000. rc.right = rc.left + SYSMET(CXVSCROLL);
  3001. else
  3002. rc.left = rc.right - SYSMET(CXVSCROLL);
  3003. } else {
  3004. if (LOBYTE(dwStyle) & SBS_TOPALIGN)
  3005. rc.bottom = rc.top + SYSMET(CYHSCROLL);
  3006. else
  3007. rc.top = rc.bottom - SYSMET(CYHSCROLL);
  3008. }
  3009. }
  3010. MoveWindow((HWND)hwnd, rc.left, rc.top, rc.right - rc.left,
  3011. rc.bottom - rc.top, FALSE);
  3012. }
  3013. } /* if */
  3014. else {
  3015. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING,
  3016. "UxScrollBarCtlWndProc - NULL lParam for WM_CREATE\n") ;
  3017. } /* else */
  3018. break;
  3019. case WM_SIZE:
  3020. if (GetFocus() != (HWND)hwnd)
  3021. break;
  3022. // scroll bar has the focus -- recalc it's thumb caret size
  3023. // no need to DeferWinEventNotify() - see CreateCaret below.
  3024. DestroyCaret();
  3025. // | |
  3026. // | FALL THRU |
  3027. // V V
  3028. case WM_SETFOCUS:
  3029. {
  3030. // REVIEW (phellyar) Do we want themed scroll bars to have
  3031. // a caret?
  3032. if ( !psb->GetTheme() )
  3033. {
  3034. SBCtlSetup(hwnd);
  3035. RECT rcWindow;
  3036. GetWindowRect( hwnd, &rcWindow );
  3037. cx = (psb->_fVert ? rcWindow.right - rcWindow.left
  3038. : psb->_calc.cpxThumb) - 2 * SYSMET(CXEDGE);
  3039. cy = (psb->_fVert ? psb->_calc.cpxThumb
  3040. : rcWindow.bottom - rcWindow.top) - 2 * SYSMET(CYEDGE);
  3041. #ifdef _VISUAL_DELTA_
  3042. cx -= (CARET_BORDERWIDTH * 2);
  3043. cy -= (CARET_BORDERWIDTH * 2);
  3044. #endif _VISUAL_DELTA_
  3045. CreateCaret((HWND)hwnd, (HBITMAP)1, cx, cy);
  3046. zzzSetSBCaretPos(hwnd);
  3047. ShowCaret((HWND)hwnd);
  3048. }
  3049. break;
  3050. }
  3051. case WM_KILLFOCUS:
  3052. DestroyCaret();
  3053. break;
  3054. case WM_ERASEBKGND:
  3055. /*
  3056. * Do nothing, but don't let DefWndProc() do it either.
  3057. * It will be erased when its painted.
  3058. */
  3059. return (LONG)TRUE;
  3060. case WM_PRINTCLIENT:
  3061. case WM_PAINT:
  3062. if ((hdc = (HDC)wParam) == NULL) {
  3063. hdc = BeginPaint((HWND)hwnd, (LPPAINTSTRUCT)&ps);
  3064. }
  3065. if (!fSize) {
  3066. SBCtlSetup(hwnd);
  3067. xxxDrawSB2((HWND)hwnd, &psb->_calc, hdc, psb->_fVert, psb->_wDisableFlags);
  3068. } else {
  3069. fSizeReal = TestWF((HWND)hwnd, WFSIZEBOX);
  3070. if (!fSizeReal)
  3071. SetWF((HWND)hwnd, WFSIZEBOX);
  3072. _DrawSizeBoxFromFrame((HWND)hwnd, hdc, 0, 0);
  3073. if (!fSizeReal)
  3074. ClrWF((HWND)hwnd, WFSIZEBOX);
  3075. }
  3076. if (wParam == 0L)
  3077. EndPaint((HWND)hwnd, (LPPAINTSTRUCT)&ps);
  3078. break;
  3079. case WM_GETDLGCODE:
  3080. return DLGC_WANTARROWS;
  3081. case WM_CONTEXTMENU:
  3082. {
  3083. HWND hwndParent = GetParent(hwnd);
  3084. if (hwndParent)
  3085. {
  3086. ScrollBar_Menu(hwndParent, hwnd, lParam, psb->_fVert);
  3087. }
  3088. break;
  3089. }
  3090. case WM_NCHITTEST:
  3091. if (LOBYTE(dwStyle) & SBS_SIZEGRIP) {
  3092. #ifdef USE_MIRRORING
  3093. /*
  3094. * If the scroll bar is RTL mirrored, then
  3095. * mirror the hittest of the grip location.
  3096. */
  3097. if (TestWF((HWND)hwnd, WEFLAYOUTRTL))
  3098. return HTBOTTOMLEFT;
  3099. else
  3100. #endif
  3101. return HTBOTTOMRIGHT;
  3102. } else {
  3103. goto CallDWP;
  3104. }
  3105. break;
  3106. case WM_MOUSELEAVE:
  3107. psb->SetHotComponent(HTNOWHERE, psb->_fVert);
  3108. InvalidateRect(hwnd, NULL, TRUE);
  3109. break;
  3110. case WM_MOUSEMOVE:
  3111. {
  3112. INT ht;
  3113. if (psb->GetHotComponent(psb->_fVert) == 0)
  3114. {
  3115. TRACKMOUSEEVENT tme;
  3116. tme.cbSize = sizeof(TRACKMOUSEEVENT);
  3117. tme.dwFlags = TME_LEAVE;
  3118. tme.hwndTrack = hwnd;
  3119. tme.dwHoverTime = 0;
  3120. TrackMouseEvent(&tme);
  3121. }
  3122. pt.x = GET_X_LPARAM(lParam);
  3123. pt.y = GET_Y_LPARAM(lParam);
  3124. ht = HitTestScrollBar((HWND)hwnd, psb->_fVert, pt);
  3125. if (psb->GetHotComponent(psb->_fVert) != ht)
  3126. {
  3127. psb->SetHotComponent(ht, psb->_fVert);
  3128. InvalidateRect(hwnd, NULL, TRUE);
  3129. }
  3130. break;
  3131. }
  3132. case WM_LBUTTONDBLCLK:
  3133. cmd = SC_ZOOM;
  3134. if (fSize)
  3135. goto postmsg;
  3136. /*
  3137. *** FALL THRU **
  3138. */
  3139. case WM_LBUTTONDOWN:
  3140. //
  3141. // Note that SBS_SIZEGRIP guys normally won't ever see button
  3142. // downs. This is because they return HTBOTTOMRIGHT to
  3143. // WindowHitTest handling. This will walk up the parent chain
  3144. // to the first sizeable ancestor, bailing out at caption windows
  3145. // of course. That dude, if he exists, will handle the sizing
  3146. // instead.
  3147. //
  3148. if (!fSize) {
  3149. if (TestWF((HWND)hwnd, WFTABSTOP)) {
  3150. SetFocus((HWND)hwnd);
  3151. }
  3152. HideCaret((HWND)hwnd);
  3153. SBCtlSetup(hwnd);
  3154. /*
  3155. * SBCtlSetup enters SEM_SB, and _SBTrackInit leaves it.
  3156. */
  3157. _SBTrackInit((HWND)hwnd, lParam, 0, (GetKeyState(VK_SHIFT) < 0) ? SCROLL_DIRECT : SCROLL_NORMAL);
  3158. break;
  3159. } else {
  3160. cmd = SC_SIZE;
  3161. postmsg:
  3162. pt.x = GET_X_LPARAM(lParam);
  3163. pt.y = GET_Y_LPARAM(lParam);
  3164. ClientToScreen((HWND)hwnd, &pt);
  3165. lParam = MAKELONG(pt.x, pt.y);
  3166. /*
  3167. * convert HT value into a move value. This is bad,
  3168. * but this is purely temporary.
  3169. */
  3170. #ifdef USE_MIRRORING
  3171. if (TestWF(GetParent(hwnd),WEFLAYOUTRTL))
  3172. {
  3173. uSide = HTBOTTOMLEFT;
  3174. }
  3175. else
  3176. #endif
  3177. {
  3178. uSide = HTBOTTOMRIGHT;
  3179. }
  3180. ThreadLock(((HWND)hwnd)->hwndParent, &tlpwndParent);
  3181. SendMessage(GetParent(hwnd), WM_SYSCOMMAND,
  3182. (cmd | (uSide - HTSIZEFIRST + 1)), lParam);
  3183. ThreadUnlock(&tlpwndParent);
  3184. }
  3185. break;
  3186. case WM_KEYUP:
  3187. switch (wParam) {
  3188. case VK_HOME:
  3189. case VK_END:
  3190. case VK_PRIOR:
  3191. case VK_NEXT:
  3192. case VK_LEFT:
  3193. case VK_UP:
  3194. case VK_RIGHT:
  3195. case VK_DOWN:
  3196. /*
  3197. * Send end scroll uMsg when user up clicks on keyboard
  3198. * scrolling.
  3199. *
  3200. * DoScroll does thread locking on these two pwnds -
  3201. * this is ok since they are not used after this
  3202. * call.
  3203. */
  3204. xxxDoScroll( (HWND)hwnd, GetParent(hwnd),
  3205. SB_ENDSCROLL, 0, psb->_fVert
  3206. );
  3207. break;
  3208. default:
  3209. break;
  3210. }
  3211. break;
  3212. case WM_KEYDOWN:
  3213. switch (wParam) {
  3214. case VK_HOME:
  3215. wParam = SB_TOP;
  3216. goto KeyScroll;
  3217. case VK_END:
  3218. wParam = SB_BOTTOM;
  3219. goto KeyScroll;
  3220. case VK_PRIOR:
  3221. wParam = SB_PAGEUP;
  3222. goto KeyScroll;
  3223. case VK_NEXT:
  3224. wParam = SB_PAGEDOWN;
  3225. goto KeyScroll;
  3226. case VK_LEFT:
  3227. case VK_UP:
  3228. wParam = SB_LINEUP;
  3229. goto KeyScroll;
  3230. case VK_RIGHT:
  3231. case VK_DOWN:
  3232. wParam = SB_LINEDOWN;
  3233. KeyScroll:
  3234. /*
  3235. * DoScroll does thread locking on these two pwnds -
  3236. * this is ok since they are not used after this
  3237. * call.
  3238. */
  3239. xxxDoScroll((HWND)hwnd, GetParent(hwnd), (int)wParam, 0, psb->_fVert
  3240. );
  3241. break;
  3242. default:
  3243. break;
  3244. }
  3245. break;
  3246. case WM_ENABLE:
  3247. return SendMessage((HWND)hwnd, SBM_ENABLE_ARROWS,
  3248. (wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH), 0);
  3249. case SBM_ENABLE_ARROWS:
  3250. /*
  3251. * This is used to enable/disable the arrows in a SB ctrl
  3252. */
  3253. return (LONG)xxxEnableSBCtlArrows((HWND)hwnd, (UINT)wParam);
  3254. case SBM_GETPOS:
  3255. return (LONG)psb->_calc.data.pos;
  3256. case SBM_GETRANGE:
  3257. *((LPINT)wParam) = psb->_calc.data.posMin;
  3258. *((LPINT)lParam) = psb->_calc.data.posMax;
  3259. return MAKELRESULT(LOWORD(psb->_calc.data.posMin), LOWORD(psb->_calc.data.posMax));
  3260. case SBM_GETSCROLLINFO:
  3261. return (LONG)_SBGetParms((HWND)hwnd, SB_CTL, (PSBDATA)&psb->_calc, (LPSCROLLINFO) lParam);
  3262. case SBM_SETRANGEREDRAW:
  3263. fRedraw = TRUE;
  3264. case SBM_SETRANGE:
  3265. // Save the old values of Min and Max for return value
  3266. si.cbSize = sizeof(si);
  3267. // si.nMin = LOWORD(lParam);
  3268. // si.nMax = HIWORD(lParam);
  3269. si.nMin = (int)wParam;
  3270. si.nMax = (int)lParam;
  3271. si.fMask = SIF_RANGE | SIF_RETURNOLDPOS;
  3272. goto SetInfo;
  3273. case SBM_SETPOS:
  3274. fRedraw = (BOOL) lParam;
  3275. si.cbSize = sizeof(si);
  3276. si.fMask = SIF_POS | SIF_RETURNOLDPOS;
  3277. si.nPos = (int)wParam;
  3278. goto SetInfo;
  3279. case SBM_SETSCROLLINFO:
  3280. {
  3281. lpsi = (LPSCROLLINFO) lParam;
  3282. fRedraw = (BOOL) wParam;
  3283. SetInfo:
  3284. fScroll = TRUE;
  3285. lres = SBSetParms((PSBDATA)&psb->_calc, lpsi, &fScroll, &lres);
  3286. if (SBSetParms((PSBDATA)&psb->_calc, lpsi, &fScroll, &lres))
  3287. {
  3288. NotifyWinEvent(EVENT_OBJECT_VALUECHANGE, hwnd, OBJID_CLIENT, INDEX_SCROLLBAR_SELF);
  3289. }
  3290. if (!fRedraw)
  3291. return lres;
  3292. /*
  3293. * We must set the new position of the caret irrespective of
  3294. * whether the window is visible or not;
  3295. * Still, this will work only if the app has done a xxxSetScrollPos
  3296. * with fRedraw = TRUE;
  3297. * Fix for Bug #5188 --SANKAR-- 10-15-89
  3298. * No need to DeferWinEventNotify since hwnd is locked.
  3299. */
  3300. HideCaret((HWND)hwnd);
  3301. SBCtlSetup(hwnd);
  3302. zzzSetSBCaretPos(hwnd);
  3303. /*
  3304. ** The following ShowCaret() must be done after the DrawThumb2(),
  3305. ** otherwise this caret will be erased by DrawThumb2() resulting
  3306. ** in this bug:
  3307. ** Fix for Bug #9263 --SANKAR-- 02-09-90
  3308. *
  3309. */
  3310. /*
  3311. *********** ShowCaret((HWND)hwnd); ******
  3312. */
  3313. if (_FChildVisible((HWND)hwnd) && fRedraw)
  3314. {
  3315. UINT wDisable;
  3316. HBRUSH hbrUse;
  3317. if (!fScroll)
  3318. fScroll = !(lpsi->fMask & SIF_DISABLENOSCROLL);
  3319. wDisable = (fScroll) ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
  3320. xxxEnableScrollBar((HWND) hwnd, SB_CTL, wDisable);
  3321. hdc = GetWindowDC((HWND)hwnd);
  3322. if (hdc)
  3323. {
  3324. BOOL fOwnerBrush = FALSE;
  3325. hbrUse = ScrollBar_GetColorObjects(hwnd, hdc, &fOwnerBrush);
  3326. hbrSave = SelectBrush(hdc, hbrUse);
  3327. // Before we used to only hideshowthumb() if the mesage was
  3328. // not SBM_SETPOS. I am not sure why but this case was ever
  3329. // needed for win 3.x but on NT it resulted in trashing the border
  3330. // of the scrollbar when the app called SetScrollPos() during
  3331. // scrollbar tracking. - mikehar 8/26
  3332. DrawThumb2((HWND)hwnd, &psb->_calc, hdc, hbrUse, psb->_fVert, psb->_wDisableFlags, fOwnerBrush);
  3333. SelectBrush(hdc, hbrSave);
  3334. ReleaseDC(hwnd, hdc);
  3335. }
  3336. }
  3337. /*
  3338. * This ShowCaret() has been moved to this place from above
  3339. * Fix for Bug #9263 --SANKAR-- 02-09-90
  3340. */
  3341. ShowCaret((HWND)hwnd);
  3342. return lres;
  3343. }
  3344. case WM_GETOBJECT:
  3345. if(lParam == OBJID_QUERYCLASSNAMEIDX)
  3346. {
  3347. return MSAA_CLASSNAMEIDX_SCROLLBAR;
  3348. }
  3349. break;
  3350. case WM_THEMECHANGED:
  3351. psb->ChangeSBTheme();
  3352. InvalidateRect(hwnd, NULL, TRUE);
  3353. break;
  3354. default:
  3355. CallDWP:
  3356. return DefWindowProc((HWND)hwnd, uMsg, wParam, lParam);
  3357. }
  3358. return 0L;
  3359. }
  3360. //-------------------------------------------------------------------------//
  3361. // Globals
  3362. static HBRUSH g_hbrGray = NULL;
  3363. //-------------------------------------------------------------------------//
  3364. HBRUSH _UxGrayBrush(VOID)
  3365. {
  3366. if( NULL == g_hbrGray )
  3367. {
  3368. CONST static WORD patGray[8] = {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
  3369. HBITMAP hbmGray;
  3370. /*
  3371. * Create a gray brush to be used with GrayString
  3372. */
  3373. if( (hbmGray = CreateBitmap(8, 8, 1, 1, (LPBYTE)patGray)) != NULL )
  3374. {
  3375. g_hbrGray = CreatePatternBrush(hbmGray);
  3376. DeleteObject( hbmGray );
  3377. }
  3378. }
  3379. return g_hbrGray;
  3380. }
  3381. //-------------------------------------------------------------------------//
  3382. void _RedrawFrame( HWND hwnd )
  3383. {
  3384. CheckLock(hwnd);
  3385. /*
  3386. * We always want to call xxxSetWindowPos, even if invisible or iconic,
  3387. * because we need to make sure the WM_NCCALCSIZE message gets sent.
  3388. */
  3389. SetWindowPos( hwnd, NULL, 0, 0, 0, 0, SWP_NOZORDER |
  3390. SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_DRAWFRAME);
  3391. }
  3392. //-------------------------------------------------------------------------//
  3393. // from winmgr.c
  3394. BOOL _FChildVisible( HWND hwnd )
  3395. {
  3396. while (GetWindowStyle( hwnd ) & WS_CHILD )
  3397. {
  3398. if( NULL == (hwnd = GetParent(hwnd)) )
  3399. if (!TestWF(hwnd, WFVISIBLE))
  3400. return FALSE;
  3401. }
  3402. return TRUE;
  3403. }
  3404. //-------------------------------------------------------------------------//
  3405. //
  3406. // SizeBoxHwnd
  3407. //
  3408. // Returns the HWND that will be sized if the user drags in the given window's
  3409. // sizebox -- If NULL, then the sizebox is not needed
  3410. //
  3411. // Criteria for choosing what window will be sized:
  3412. // find first sizeable parent; if that parent is not maximized and the child's
  3413. // bottom, right corner is within a scroll bar height and width of the parent's
  3414. //
  3415. HWND SizeBoxHwnd(HWND hwnd)
  3416. {
  3417. BOOL bMirroredSizeBox = (BOOL)TestWF(hwnd, WEFLAYOUTRTL);
  3418. RECT rc;
  3419. int xbrChild;
  3420. int ybrChild;
  3421. GetWindowRect(hwnd, &rc);
  3422. xbrChild = bMirroredSizeBox ? rc.left : rc.right;
  3423. ybrChild = rc.bottom;
  3424. while (hwnd != HWND_DESKTOP)
  3425. {
  3426. if (TestWF(hwnd, WFSIZEBOX))
  3427. {
  3428. //
  3429. // First sizeable parent found
  3430. //
  3431. int xbrParent;
  3432. int ybrParent;
  3433. if (TestWF(hwnd, WFMAXIMIZED))
  3434. {
  3435. return NULL;
  3436. }
  3437. GetWindowRect(hwnd, &rc);
  3438. xbrParent = bMirroredSizeBox ? rc.left : rc.right;
  3439. ybrParent = rc.bottom;
  3440. //
  3441. // the sizebox dude is within an EDGE of the client's bottom
  3442. // right corner (left corner for mirrored windows), let this succeed.
  3443. // That way people who draw their own sunken clients will be happy.
  3444. //
  3445. if (bMirroredSizeBox)
  3446. {
  3447. if ((xbrChild - SYSMETRTL(CXFRAME) > xbrParent) || (ybrChild + SYSMETRTL(CYFRAME) < ybrParent))
  3448. {
  3449. //
  3450. // Child's bottom, left corner of SIZEBOX isn't close enough
  3451. // to bottom left of parent's client.
  3452. //
  3453. return NULL;
  3454. }
  3455. }
  3456. else
  3457. {
  3458. if ((xbrChild + SYSMETRTL(CXFRAME) < xbrParent) || (ybrChild + SYSMETRTL(CYFRAME) < ybrParent))
  3459. {
  3460. //
  3461. // Child's bottom, right corner of SIZEBOX isn't close enough
  3462. // to bottom right of parent's client.
  3463. //
  3464. return NULL;
  3465. }
  3466. }
  3467. return hwnd;
  3468. }
  3469. if (!TestWF(hwnd, WFCHILD) || TestWF(hwnd, WFCPRESENT))
  3470. {
  3471. break;
  3472. }
  3473. hwnd = GetParent(hwnd);
  3474. }
  3475. return NULL;
  3476. }
  3477. //-------------------------------------------------------------------------//
  3478. //
  3479. // _DrawPushButton
  3480. //
  3481. // From ntuser\rtl\draw.c
  3482. // Draws a push style button in the given state. Adjusts passed in rectangle
  3483. // if desired.
  3484. //
  3485. // Algorithm:
  3486. // Depending on the state we either draw
  3487. // - raised edge (undepressed)
  3488. // - sunken edge with extra shadow (depressed)
  3489. // If it is an option push button (a push button that is
  3490. // really a check button or a radio button like buttons
  3491. // in tool bars), and it is checked, then we draw it
  3492. // depressed with a different fill in the middle.
  3493. //
  3494. VOID _DrawPushButton(HWND hwnd, HDC hdc, LPRECT lprc, UINT state, UINT flags, BOOL fVert)
  3495. {
  3496. RECT rc;
  3497. HBRUSH hbrMiddle;
  3498. DWORD rgbBack = 0;
  3499. DWORD rgbFore = 0;
  3500. BOOL fDither;
  3501. HTHEME hTheme = CUxScrollBar::GetSBTheme(hwnd);
  3502. if ( !hTheme )
  3503. {
  3504. rc = *lprc;
  3505. DrawEdge(hdc,
  3506. &rc,
  3507. (state & (DFCS_PUSHED | DFCS_CHECKED)) ? EDGE_SUNKEN : EDGE_RAISED,
  3508. (UINT)(BF_ADJUST | BF_RECT | (flags & (BF_SOFT | BF_FLAT | BF_MONO))));
  3509. //
  3510. // BOGUS
  3511. // On monochrome, need to do something to make pushed buttons look
  3512. // better.
  3513. //
  3514. //
  3515. // Fill in middle. If checked, use dither brush (gray brush) with
  3516. // black becoming normal color.
  3517. //
  3518. fDither = FALSE;
  3519. if (state & DFCS_CHECKED)
  3520. {
  3521. if ((GetDeviceCaps(hdc, BITSPIXEL) /*gpsi->BitCount*/ < 8) || (SYSRGBRTL(3DHILIGHT) == RGB(255,255,255)))
  3522. {
  3523. hbrMiddle = _UxGrayBrush();
  3524. rgbBack = SetBkColor(hdc, SYSRGBRTL(3DHILIGHT));
  3525. rgbFore = SetTextColor(hdc, SYSRGBRTL(3DFACE));
  3526. fDither = TRUE;
  3527. }
  3528. else
  3529. {
  3530. hbrMiddle = SYSHBR(3DHILIGHT);
  3531. }
  3532. }
  3533. else
  3534. {
  3535. hbrMiddle = SYSHBR(3DFACE);
  3536. }
  3537. FillRect(hdc, &rc, hbrMiddle);
  3538. if (fDither)
  3539. {
  3540. SetBkColor(hdc, rgbBack);
  3541. SetTextColor(hdc, rgbFore);
  3542. }
  3543. if (flags & BF_ADJUST)
  3544. {
  3545. *lprc = rc;
  3546. }
  3547. }
  3548. else
  3549. {
  3550. INT iStateId;
  3551. INT iPartId;
  3552. SIZE sizeGrip;
  3553. RECT rcContent;
  3554. PSBTRACK pSBTrack = CUxScrollBar::GetSBTrack(hwnd);
  3555. if ((CUxScrollBarCtl::GetDisableFlags(hwnd) & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
  3556. {
  3557. iStateId = SCRBS_DISABLED;
  3558. }
  3559. else if (pSBTrack && ((BOOL)pSBTrack->fTrackVert == fVert) && (pSBTrack->cmdSB == SB_THUMBPOSITION))
  3560. {
  3561. iStateId = SCRBS_PRESSED;
  3562. }
  3563. else if (CUxScrollBar::GetSBHotComponent(hwnd, fVert) == HTSCROLLTHUMB)
  3564. {
  3565. iStateId = SCRBS_HOT;
  3566. }
  3567. else
  3568. {
  3569. iStateId = SCRBS_NORMAL;
  3570. }
  3571. iPartId = fVert ? SBP_THUMBBTNVERT : SBP_THUMBBTNHORZ;
  3572. //
  3573. // Draw the thumb
  3574. //
  3575. DrawThemeBackground(hTheme, hdc, iPartId, iStateId, lprc, 0);
  3576. //
  3577. // Lastly draw the little gripper image, if there is enough room
  3578. //
  3579. if ( SUCCEEDED(GetThemeBackgroundContentRect(hTheme, hdc, iPartId, iStateId, lprc, &rcContent)) )
  3580. {
  3581. iPartId = fVert ? SBP_GRIPPERVERT : SBP_GRIPPERHORZ;
  3582. if ( SUCCEEDED(GetThemePartSize(hTheme, hdc, iPartId, iStateId, &rcContent, TS_TRUE, &sizeGrip)) )
  3583. {
  3584. if ( (sizeGrip.cx < RECTWIDTH(&rcContent)) && (sizeGrip.cy < RECTHEIGHT(&rcContent)) )
  3585. {
  3586. DrawThemeBackground(hTheme, hdc, iPartId, iStateId, &rcContent, 0);
  3587. }
  3588. }
  3589. }
  3590. }
  3591. }
  3592. // user.h
  3593. #define CheckMsgFilter(wMsg, wMsgFilterMin, wMsgFilterMax) \
  3594. ( ((wMsgFilterMin) == 0 && (wMsgFilterMax) == 0xFFFFFFFF) \
  3595. || ( ((wMsgFilterMin) > (wMsgFilterMax)) \
  3596. ? (((wMsg) < (wMsgFilterMax)) || ((wMsg) > (wMsgFilterMin))) \
  3597. : (((wMsg) >= (wMsgFilterMin)) && ((wMsg) <= (wMsgFilterMax)))))
  3598. #define SYS_ALTERNATE 0x2000
  3599. #define SYS_PREVKEYSTATE 0x4000
  3600. // mnaccel.h
  3601. /***************************************************************************\
  3602. * _SysToChar
  3603. *
  3604. * EXIT: If the message was not made with the ALT key down, convert
  3605. * the message from a WM_SYSKEY* to a WM_KEY* message.
  3606. *
  3607. * IMPLEMENTATION:
  3608. * The 0x2000 bit in the hi word of lParam is set if the key was
  3609. * made with the ALT key down.
  3610. *
  3611. * History:
  3612. * 11/30/90 JimA Ported.
  3613. \***************************************************************************/
  3614. UINT _SysToChar(
  3615. UINT message,
  3616. LPARAM lParam)
  3617. {
  3618. if (CheckMsgFilter(message, WM_SYSKEYDOWN, WM_SYSDEADCHAR) &&
  3619. !(HIWORD(lParam) & SYS_ALTERNATE))
  3620. return (message - (WM_SYSKEYDOWN - WM_KEYDOWN));
  3621. return message;
  3622. }