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.

4288 lines
130 KiB

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