Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5282 lines
141 KiB

  1. #include "ctlspriv.h"
  2. #include "image.h"
  3. #define ANIMSTEPS 10
  4. #define ANIMSTEPTIME 5
  5. #define CX_CHEVRON (g_cxScrollbar)
  6. #define CX_OFFSET (2 * g_cxEdge)
  7. #define GRABWIDTH 5
  8. //*** RBC_* -- commands
  9. #define RBC_QUERY 0
  10. #define RBC_SET 1
  11. typedef struct tagREBARBAND
  12. {
  13. UINT fStyle;
  14. COLORREF clrFore;
  15. COLORREF clrBack;
  16. LPTSTR lpText;
  17. int cxText; // width of header text
  18. int iImage;
  19. int cxMinChild; // min width for hwndChild
  20. int cyMinChild; // min height for hwndChild
  21. int cxBmp;
  22. int cyBmp;
  23. int x; // left edge of band, relative to rebar
  24. int y; // top edge of band, relative to rebar
  25. int cx; // total width of band
  26. int cy; // height of band
  27. int cxRequest; // 'requested' width for band; either requested by host or used as temp var during size recalculation
  28. int cxMin; // min width for band
  29. int cxIdeal; // hwndChild's desired width
  30. int cyMaxChild; // hwndChild's max height
  31. int cyIntegral; // ??
  32. int cyChild; // this differs from cyMinChild only in RBBS_VARIABLEHEIGHT mode
  33. HWND hwndChild;
  34. HBITMAP hbmBack;
  35. UINT wID;
  36. LPARAM lParam;
  37. BOOL fChevron; // band is showing chevron button
  38. RECT rcChevron; // chevron button rect
  39. UINT wChevState; // chevron button state (DFCS_PUSHED, etc.)
  40. } RBB, *PRBB;
  41. class CReBar
  42. {
  43. public:
  44. private:
  45. void _CacheThemeInfo(BOOL fOpenNew);
  46. int _GetGripperWidth();
  47. void _Realize(HDC hdcParam, BOOL fBackground, BOOL fForceRepaint);
  48. LRESULT _SendNotify(UINT uBand, int iCode);
  49. BOOL _InvalidateRect(RECT* prc);
  50. static LRESULT s_DragCallback(HWND hwnd, UINT code, WPARAM wp, LPARAM lp);
  51. BOOL _CanBandMove(PRBB prbb);
  52. void _BandCalcMinWidth(PRBB prbb);
  53. BOOL _ShouldDrawGripper(PRBB prbb);
  54. BOOL _BandCalcTextExtent(PRBB prbb, HDC hdcIn);
  55. int _BandGetHeight(PRBB prbb);
  56. UINT _GetRowCount();
  57. int _GetLineHeight(UINT iStart, UINT iEnd);
  58. void _BandRecalcChevron(PRBB prbb, BOOL fChevron);
  59. void _ResizeChildren();
  60. BOOL _MoveBand(UINT iFrom, UINT iTo);
  61. int _Recalc(LPRECT prc, BOOL fForce = FALSE);
  62. void _ResizeNow();
  63. void _Resize(BOOL fForceHeightChange);
  64. void _SetRecalc(BOOL fRecalc);
  65. BOOL _SetRedraw(BOOL fRedraw);
  66. BOOL _AfterSetFont();
  67. BOOL _OnSetFont(HFONT hFont);
  68. BOOL _SetFont(WPARAM wParam);
  69. void _VertMungeGripperRect(LPRECT lprc);
  70. void _DrawChevron(PRBB prbb, HDC hdc);
  71. void _UpdateChevronState(PRBB prbb, WORD wControlState);
  72. void _DrawBand(PRBB prbb, HDC hdc);
  73. void _OnPaint(HDC hdcIn);
  74. void _BandTileBlt(PRBB prbb, int x, int y, int cx, int cy, HDC hdcDst, HDC hdcSrc);
  75. int _InternalHitTest(LPRBHITTESTINFO prbht, int x, int y);
  76. int _HitTest(LPRBHITTESTINFO prbht);
  77. BOOL _EraseBkgnd(HDC hdc, int iBand);
  78. BOOL _GetBarInfo(LPREBARINFO lprbi);
  79. BOOL _SetBarInfo(LPREBARINFO lprbi);
  80. BOOL _GetBandInfo(UINT uBand, LPREBARBANDINFO lprbbi);
  81. BOOL _ValidateBandInfo(LPREBARBANDINFO *pprbbi, LPREBARBANDINFO prbbi);
  82. BOOL _SetBandInfo(UINT uBand, LPREBARBANDINFO lprbbi, BOOL fAllowRecalc);
  83. BOOL _ReallocBands(UINT cBands);
  84. BOOL _RecalcFirst(int nCmd, PRBB prbbDelHide);
  85. BOOL _ShowBand(UINT uBand, BOOL fShow);
  86. BOOL _DeleteBand(UINT uBand);
  87. BOOL _InsertBand(UINT uBand, LPREBARBANDINFO lprbbi);
  88. PRBB _GetFirstInRow(PRBB prbbRow);
  89. PRBB _GetLastInRow(PRBB prbbRow, BOOL fStopAtFixed);
  90. PRBB _GetPrev(PRBB prbb, UINT uStyleSkip);
  91. PRBB _GetNext(PRBB prbb, UINT uStyleSkip);
  92. int _CountBands(UINT uStyleSkip);
  93. PRBB _EnumBand(int i, UINT uStyleSkip);
  94. int _MinX(PRBB prbb);
  95. int _MaxX(PRBB prbb);
  96. BOOL _MinimizeBand(UINT uBand, BOOL fAnim);
  97. BOOL _MaximizeBand(UINT uBand, BOOL fIdeal, BOOL fAnim);
  98. void _ToggleBand(BOOL fAnim);
  99. void _SetCursor(int x, int y, BOOL fMouseDown);
  100. BOOL _SetBandPos(PRBB prbb, int xLeft);
  101. BOOL _SetBandPosAnim(PRBB prbb, int xLeft);
  102. void _OnBeginDrag(UINT uBand);
  103. void _PassBreak(PRBB prbbSrc, PRBB prbbDest);
  104. void _GetClientRect(LPRECT prc);
  105. BOOL _RecalcIfMove(PRBB prbb);
  106. BOOL _RoomForBandVert(PRBB prbbSkip);
  107. BOOL _MakeNewRow(PRBB prbb, int y);
  108. void _DragBand(int x, int y);
  109. HPALETTE _SetPalette(HPALETTE hpal);
  110. BOOL _OnDestroy();
  111. void _InitPaletteHack();
  112. UINT _IDToIndex(UINT id);
  113. int _GetRowHeight(UINT uRow);
  114. int _GrowBand(PRBB prbb, int dy, BOOL fResize, int iLineHeight);
  115. int _SizeDifference(LPRECT prc);
  116. int _GetRowHeightExtra(PRBB *pprbb, PRBB prbbSkip);
  117. BOOL _BandsAtMinHeight();
  118. BOOL _SizeBandsToRect(LPRECT prc);
  119. void _SizeBandToRowHeight(int i, int uRowHeight);
  120. void _SizeBandsToRowHeight();
  121. BOOL _OkayToChangeBreak(PRBB prbb, UINT uMsg);
  122. LRESULT _SizeBarToRect(DWORD dwFlags, LPRECT prc);
  123. void _AutoSize();
  124. LRESULT _GetBandBorders(int wParam, LPRECT prc);
  125. void _OnStyleChanged(WPARAM wParam, LPSTYLESTRUCT lpss);
  126. void _OnMouseMove(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  127. void _OnPushChevron(HWND hwnd, PRBB prbb, LPARAM lParamNM);
  128. void _InvalidateBorders(PRBB prbb);
  129. void _OnCreate(HWND hwnd, LPCREATESTRUCT pcs);
  130. static LRESULT CALLBACK s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  131. LRESULT _WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  132. PRBB CReBar::_GetPrevVisible(PRBB prbb)
  133. {
  134. return _GetPrev(prbb, RBBS_HIDDEN);
  135. }
  136. PRBB CReBar::_GetNextVisible(PRBB prbb)
  137. {
  138. return _GetNext(prbb, RBBS_HIDDEN);
  139. }
  140. BOOL CReBar::_DragSize(int xLeft)
  141. {
  142. // adjust the captured band's starting location to the given location
  143. return _SetBandPos(_GetBand(_uCapture), xLeft);
  144. }
  145. int _FudgeWidth(int cx)
  146. {
  147. if (_UseBandBorders())
  148. cx += g_cxEdge;
  149. return cx + _mBand.cxLeftWidth + _mBand.cxRightWidth;
  150. }
  151. int _BandWidth(PRBB prbb)
  152. {
  153. ASSERT(!(prbb->fStyle & RBBS_HIDDEN));
  154. return _FudgeWidth(prbb->cx);
  155. }
  156. int _BandMinWidth(PRBB prbb)
  157. {
  158. ASSERT(!(prbb->fStyle & RBBS_HIDDEN));
  159. return _FudgeWidth(prbb->cxMin);
  160. }
  161. BOOL _UseBandBorders()
  162. {
  163. return _ci.style & RBS_BANDBORDERS;
  164. }
  165. BOOL _UseChevron(PRBB prbb)
  166. {
  167. return (prbb->fStyle & RBBS_USECHEVRON) &&
  168. !(prbb->fStyle & RBBS_FIXEDSIZE) &&
  169. (prbb->cxIdeal > prbb->cxMinChild);
  170. }
  171. BOOL _ShowText(PRBB prbb)
  172. {
  173. return !(prbb->fStyle & RBBS_HIDETITLE) && prbb->lpText && prbb->lpText[0];
  174. }
  175. BOOL _IsVertical()
  176. {
  177. return (_ci.style & CCS_VERT);
  178. }
  179. BOOL _IsVerticalGripper()
  180. {
  181. return _IsVertical() && (_ci.style & RBS_VERTICALGRIPPER);
  182. }
  183. PRBB _GetLastBand()
  184. {
  185. if (_cBands > 0)
  186. return _GetBand(_cBands - 1);
  187. return NULL;
  188. }
  189. BOOL _IsBandStartOfRow(PRBB prbb)
  190. {
  191. return (prbb->x == _mBand.cxLeftWidth) && !(prbb->fStyle & RBBS_HIDDEN);
  192. }
  193. PRBB _GetBand(UINT i)
  194. {
  195. _ValidateRangeInd(i);
  196. return &_rbbList[i];
  197. }
  198. UINT _BandToIndex(PRBB prbb)
  199. {
  200. return (UINT)(prbb - _rbbList);
  201. }
  202. int _GetHeaderWidth(PRBB prbb)
  203. {
  204. return (prbb->cxMin - (prbb->cxMinChild + (_UseChevron(prbb) ? CX_CHEVRON : 0)));
  205. }
  206. BOOL _IsBandVisible(PRBB prbb)
  207. {
  208. return !(prbb->fStyle & RBBS_HIDDEN);
  209. }
  210. BOOL _IsRowAtMinHeight(PRBB* pprbb)
  211. {
  212. return !_GetRowHeightExtra(pprbb, NULL);
  213. }
  214. int _GetBarHeight()
  215. {
  216. return (_cBands && _cy == 0) ? _Recalc(NULL, TRUE) : _cy;
  217. }
  218. BOOL _IsValidIndex(UINT i)
  219. {
  220. return (BOOL)(i < _cBands);
  221. }
  222. BOOL _IsValidBand(PRBB prbb)
  223. {
  224. return _IsValidIndex(_BandToIndex(prbb));
  225. }
  226. COLORREF _GetBkColor()
  227. {
  228. if (_clrBk == CLR_DEFAULT)
  229. return g_clrBtnFace;
  230. else
  231. return _clrBk;
  232. }
  233. COLORREF _GetTextColor()
  234. {
  235. if (_clrText == CLR_DEFAULT)
  236. return g_clrBtnText;
  237. else
  238. return _clrText;
  239. }
  240. COLORREF _BandGetBkColor(PRBB prbb)
  241. {
  242. switch(prbb->clrBack)
  243. {
  244. case CLR_NONE:
  245. // CLR_NONE means "use our dad's color"
  246. return _GetBkColor();
  247. case CLR_DEFAULT:
  248. return g_clrBtnFace;
  249. default:
  250. return prbb->clrBack;
  251. }
  252. }
  253. COLORREF _BandGetTextColor(PRBB prbb)
  254. {
  255. switch (prbb->clrFore)
  256. {
  257. case CLR_NONE:
  258. // CLR_NONE means "use our dad's color"
  259. return _GetTextColor();
  260. case CLR_DEFAULT:
  261. return g_clrBtnText;
  262. default:
  263. return prbb->clrFore;
  264. }
  265. }
  266. //
  267. // Our use of CLR_DEFAULT for the band background colors is new for
  268. // version 5.01. Since we don't want to confuse apps by returning
  269. // CLR_DEFAULT when they used to see a real colorref, we convert it
  270. // before returning it to them. If the background color is CLR_NONE,
  271. // though, we need to return it without conversion (like version 4 did).
  272. // The *External functions handle these cases.
  273. //
  274. COLORREF _BandGetTextColorExternal(PRBB prbb)
  275. {
  276. if (prbb->clrFore == CLR_NONE)
  277. return CLR_NONE;
  278. else
  279. return _BandGetTextColor(prbb);
  280. }
  281. COLORREF _BandGetBkColorExternal(PRBB prbb)
  282. {
  283. if (prbb->clrBack == CLR_NONE)
  284. return CLR_NONE;
  285. else
  286. return _BandGetBkColor(prbb);
  287. }
  288. BOOL _ValidateRangePtr(PRBB prbb)
  289. {
  290. #ifdef DEBUG
  291. if (prbb < _GetBand(0)) {
  292. ASSERT(0);
  293. return FALSE;
  294. }
  295. if (_GetLastBand() + 1 < prbb) {
  296. // +1 to allow for "p = first; p < last+1; p++" kinds of loops
  297. ASSERT(0);
  298. return FALSE;
  299. }
  300. #endif
  301. return TRUE;
  302. }
  303. BOOL _ValidateRangeInd(UINT i)
  304. {
  305. #ifdef DEBUG
  306. if ( !IsInRange(i, 0, _cBands) ) { // if !(0 <= i <= _cBands)
  307. // +1 to allow for "p = first; p < last+1; p++" kinds of loops
  308. ASSERT(0);
  309. return FALSE;
  310. }
  311. #endif
  312. return TRUE;
  313. }
  314. CCONTROLINFO _ci;
  315. HPALETTE _hpal;
  316. BOOL _fResizeRecursed;
  317. BOOL _fResizePending;
  318. BOOL _fResizeNotify;
  319. BOOL _fRedraw;
  320. BOOL _fRecalcPending;
  321. BOOL _fRecalc;
  322. BOOL _fParentDrag;
  323. BOOL _fRefreshPending;
  324. BOOL _fResizing;
  325. BOOL _fUserPalette;
  326. BOOL _fFontCreated;
  327. BOOL _fFullOnDrag;
  328. BOOL _fHasBorder;
  329. HDRAGPROXY _hDragProxy;
  330. HWND _hwndToolTips;
  331. int _xBmpOrg;
  332. int _yBmpOrg;
  333. int _cyFont;
  334. int _cy;
  335. int _cxImage;
  336. int _cyImage;
  337. int _xStart;
  338. MARGINS _mBand;
  339. HIMAGELIST _himl;
  340. HFONT _hFont;
  341. UINT _cBands;
  342. UINT _uCapture;
  343. UINT _uResizeNext; // this marks the next band to resize vertically if needed and allowed (VARIABLEHEIGHT set)
  344. POINT _ptCapture;
  345. PRBB _rbbList;
  346. COLORREF _clrBk;
  347. COLORREF _clrText;
  348. DWORD _dwStyleEx;
  349. COLORSCHEME _clrsc;
  350. POINT _ptLastDragPos;
  351. PRBB _prbbHot; // band w/ hot chevron
  352. HTHEME _hTheme;
  353. friend BOOL InitReBarClass(HINSTANCE hInstance);
  354. };
  355. void CReBar::_CacheThemeInfo(BOOL fOpenNew)
  356. {
  357. if (_hTheme)
  358. CloseThemeData(_hTheme);
  359. _hTheme = NULL;
  360. if (fOpenNew)
  361. _hTheme = OpenThemeData(_ci.hwnd, L"Rebar");
  362. if (_hTheme)
  363. {
  364. // Get the cached metrics. These are things that can be slow to get during a calculation
  365. GetThemeMargins(_hTheme, NULL, RP_BAND, 0, TMT_CONTENTMARGINS, NULL, &_mBand);
  366. SetWindowBits(_ci.hwnd, GWL_STYLE, WS_BORDER, 0);
  367. }
  368. else
  369. {
  370. if (_fHasBorder)
  371. SetWindowBits(_ci.hwnd, GWL_STYLE, WS_BORDER, WS_BORDER);
  372. ZeroMemory(&_mBand, sizeof(MARGINS));
  373. }
  374. _AfterSetFont();
  375. }
  376. int CReBar::_GetGripperWidth()
  377. {
  378. BOOL fVert;
  379. RECT rcClient;
  380. RECT rc;
  381. if (!_hTheme)
  382. return GRABWIDTH;
  383. GetClientRect(_ci.hwnd, &rcClient);
  384. fVert = _IsVerticalGripper();
  385. SetRect(&rc, 0, 0, fVert?RECTWIDTH(rcClient):3, fVert?3:RECTHEIGHT(rcClient));
  386. GetThemeBackgroundExtent(_hTheme, NULL, RP_GRIPPER, 0, &rc, &rc);
  387. return fVert?RECTHEIGHT(rc):RECTWIDTH(rc);
  388. }
  389. ///
  390. //
  391. // Map a rect to parent should be based on the visual right edge
  392. // for calculating the client coordinates for a RTL mirrored windows.
  393. // This routine should only be used when calculating client
  394. // coordinates in a RTL mirrored window. [samera]
  395. //
  396. BOOL MapRectInRTLMirroredWindow( LPRECT lprc, HWND hwnd)
  397. {
  398. int iWidth = lprc->right - lprc->left;
  399. int iHeight = lprc->bottom- lprc->top;
  400. RECT rc={0,0,0,0};
  401. if (hwnd) {
  402. GetClientRect(hwnd, &rc);
  403. MapWindowPoints(hwnd, NULL, (LPPOINT)&rc.left, 2);
  404. }
  405. lprc->left = rc.right - lprc->right;
  406. lprc->top = lprc->top-rc.top;
  407. lprc->bottom = lprc->top + iHeight;
  408. lprc->right = lprc->left + iWidth;
  409. return TRUE;
  410. }
  411. void CReBar::_Realize(HDC hdcParam, BOOL fBackground, BOOL fForceRepaint)
  412. {
  413. if (_hpal)
  414. {
  415. HDC hdc = hdcParam ? hdcParam : GetDC(_ci.hwnd);
  416. if (hdc)
  417. {
  418. BOOL fRepaint;
  419. SelectPalette(hdc, _hpal, fBackground);
  420. fRepaint = RealizePalette(hdc) || fForceRepaint;
  421. if (!hdcParam)
  422. ReleaseDC(_ci.hwnd, hdc);
  423. if (fRepaint)
  424. {
  425. InvalidateRect(_ci.hwnd, NULL, TRUE);
  426. }
  427. }
  428. }
  429. }
  430. //////////////////////////////////////////////////////////////////
  431. // _SendNotify
  432. //
  433. // sends a wm_notify of code iCode and packages up all the data for you
  434. // for band uBand
  435. //
  436. //////////////////////////////////////////////////////////////////
  437. LRESULT CReBar::_SendNotify(UINT uBand, int iCode)
  438. {
  439. NMREBAR nm = {0};
  440. nm.uBand = uBand;
  441. if (uBand != (UINT)-1) {
  442. nm.dwMask = RBNM_ID | RBNM_STYLE | RBNM_LPARAM;
  443. nm.wID = _GetBand(uBand)->wID;
  444. nm.fStyle = _GetBand(uBand)->fStyle;
  445. nm.lParam = _GetBand(uBand)->lParam;
  446. }
  447. return CCSendNotify(&_ci, iCode, &nm.hdr);
  448. }
  449. BOOL CReBar::_InvalidateRect(RECT* prc)
  450. {
  451. if (_fRedraw)
  452. {
  453. RECT rc;
  454. if (prc && _IsVertical())
  455. {
  456. CopyRect(&rc, prc);
  457. FlipRect(&rc);
  458. prc = &rc;
  459. }
  460. _fRefreshPending = FALSE;
  461. InvalidateRect(_ci.hwnd, prc, TRUE);
  462. return TRUE;
  463. }
  464. else
  465. {
  466. _fRefreshPending = TRUE;
  467. return FALSE;
  468. }
  469. }
  470. LRESULT CReBar::s_DragCallback(HWND hwnd, UINT code, WPARAM wp, LPARAM lp)
  471. {
  472. CReBar* prb = (CReBar*)GetWindowPtr(hwnd, 0);
  473. LRESULT lres;
  474. switch (code)
  475. {
  476. case DPX_DRAGHIT:
  477. if (lp)
  478. {
  479. int iBand;
  480. RBHITTESTINFO rbht;
  481. rbht.pt.x = ((POINTL *)lp)->x;
  482. rbht.pt.y = ((POINTL *)lp)->y;
  483. MapWindowPoints(NULL, prb->_ci.hwnd, &rbht.pt, 1);
  484. iBand = prb->_HitTest(&rbht);
  485. *(DWORD*)wp = rbht.flags;
  486. lres = (LRESULT)(iBand != -1 ? prb->_rbbList[iBand].wID : -1);
  487. }
  488. else
  489. lres = -1;
  490. break;
  491. case DPX_GETOBJECT:
  492. lres = (LRESULT)GetItemObject(&prb->_ci, RBN_GETOBJECT, &IID_IDropTarget, (LPNMOBJECTNOTIFY)lp);
  493. break;
  494. default:
  495. lres = -1;
  496. break;
  497. }
  498. return lres;
  499. }
  500. // ----------------------------------------------------------------------------
  501. //
  502. // _CanBandMove
  503. //
  504. // returns TRUE if the given band can be moved and FALSE if it cannot
  505. //
  506. // ----------------------------------------------------------------------------
  507. BOOL CReBar::_CanBandMove(PRBB prbb)
  508. {
  509. // If there is only one visible band it cannot move
  510. if (_EnumBand(1, RBBS_HIDDEN) > _GetLastBand())
  511. return FALSE;
  512. ASSERT(!(prbb->fStyle & RBBS_HIDDEN));
  513. if ((_ci.style & RBS_FIXEDORDER)
  514. && (prbb == _EnumBand(0, RBBS_HIDDEN)))
  515. // the first (visible) band in fixed order rebars can't be moved
  516. return(FALSE);
  517. // fixed size bands can't be moved
  518. return(!(prbb->fStyle & RBBS_FIXEDSIZE));
  519. }
  520. // ----------------------------------------------------------------------------
  521. //
  522. // _BandCalcMinWidth
  523. //
  524. // calculates minimum width for the given band
  525. //
  526. // ----------------------------------------------------------------------------
  527. void CReBar::_BandCalcMinWidth(PRBB prbb)
  528. {
  529. BOOL fDrawGripper = _ShouldDrawGripper(prbb);
  530. BOOL fVertical;
  531. int cEdge;
  532. BOOL fEmpty = (prbb->iImage == -1 && !_ShowText(prbb));
  533. if (prbb->fStyle & RBBS_HIDDEN)
  534. {
  535. ASSERT(0);
  536. return;
  537. }
  538. // did the user specify the size explicitly?
  539. if (prbb->fStyle & RBBS_FIXEDHEADERSIZE)
  540. return;
  541. prbb->cxMin = prbb->cxMinChild;
  542. if (_UseChevron(prbb))
  543. prbb->cxMin += CX_CHEVRON;
  544. if (!fDrawGripper && fEmpty)
  545. return;
  546. fVertical = (_ci.style & CCS_VERT);
  547. if (_IsVerticalGripper())
  548. {
  549. prbb->cxMin += 4 * g_cyEdge;
  550. prbb->cxMin += max(_cyImage, _cyFont);
  551. }
  552. else
  553. {
  554. cEdge = fVertical ? g_cyEdge : g_cxEdge;
  555. prbb->cxMin += 2 * cEdge;
  556. if (fDrawGripper)
  557. {
  558. prbb->cxMin += _GetGripperWidth() * (fVertical ? g_cyBorder : g_cxBorder);
  559. if (fEmpty)
  560. return;
  561. }
  562. prbb->cxMin += 2 * cEdge;
  563. if (prbb->iImage != -1)
  564. prbb->cxMin += (fVertical ? _cyImage : _cxImage);
  565. if (_ShowText(prbb))
  566. {
  567. if (fVertical)
  568. prbb->cxMin += _cyFont;
  569. else
  570. prbb->cxMin += prbb->cxText;
  571. if (prbb->iImage != -1)
  572. // has both image and text -- add in edge between 'em
  573. prbb->cxMin += cEdge;
  574. }
  575. }
  576. }
  577. BOOL CReBar::_ShouldDrawGripper(PRBB prbb)
  578. {
  579. if (prbb->fStyle & RBBS_NOGRIPPER)
  580. return FALSE;
  581. if ((prbb->fStyle & RBBS_GRIPPERALWAYS) || _CanBandMove(prbb))
  582. return TRUE;
  583. return FALSE;
  584. }
  585. // ----------------------------------------------------------------------------
  586. //
  587. // _BandCalcTextExtent
  588. //
  589. // computes the horizontal extent of the given band's title text in the current
  590. // title font for the rebar
  591. //
  592. // returns TRUE if text extent changed, FALSE otherwise
  593. //
  594. // ----------------------------------------------------------------------------
  595. BOOL CReBar::_BandCalcTextExtent(PRBB prbb, HDC hdcIn)
  596. {
  597. HDC hdc = hdcIn;
  598. HFONT hFontOld;
  599. int cx;
  600. if (prbb->fStyle & RBBS_HIDDEN)
  601. {
  602. ASSERT(0); // caller should have skipped
  603. return FALSE;
  604. }
  605. if (!_ShowText(prbb))
  606. {
  607. cx = 0;
  608. }
  609. else
  610. {
  611. RECT rc = {0,0,0,0};
  612. HRESULT hr = E_FAIL;
  613. if (!hdcIn && !(hdc = GetDC(_ci.hwnd)))
  614. return FALSE;
  615. hFontOld = SelectFont(hdc, _hFont);
  616. if (_hTheme)
  617. hr = GetThemeTextExtent(_hTheme, hdc, 0, 0, prbb->lpText, -1, DT_CALCRECT, &rc, &rc);
  618. if (FAILED(hr))
  619. {
  620. DrawText(hdc, prbb->lpText, lstrlen(prbb->lpText), &rc, DT_CALCRECT);
  621. }
  622. SelectObject(hdc, hFontOld);
  623. cx = RECTWIDTH(rc);
  624. if (!hdcIn)
  625. ReleaseDC(_ci.hwnd, hdc);
  626. }
  627. if (prbb->cxText != cx)
  628. {
  629. prbb->cxText = cx;
  630. _BandCalcMinWidth(prbb);
  631. return TRUE;
  632. }
  633. return FALSE;
  634. }
  635. // ----------------------------------------------------------------------------
  636. //
  637. // _BandGetHeight
  638. //
  639. // returns minimum height for the given band
  640. // TODO: make this a field in the band structure instead of always calling this
  641. //
  642. // ----------------------------------------------------------------------------
  643. int CReBar::_BandGetHeight(PRBB prbb)
  644. {
  645. UINT cy = 0;
  646. BOOL fVertical = (_ci.style & CCS_VERT);
  647. UINT cyCheck, cyBorder;
  648. cyBorder = (fVertical ? g_cxEdge : g_cyEdge) * 2;
  649. if (prbb->hwndChild)
  650. {
  651. cy = prbb->cyChild;
  652. if (!(prbb->fStyle & RBBS_CHILDEDGE))
  653. // add edge to top and bottom of child window
  654. cy -= cyBorder;
  655. }
  656. if (_ShowText(prbb) && !fVertical)
  657. {
  658. cyCheck = _cyFont;
  659. if (cyCheck > cy)
  660. cy = cyCheck;
  661. }
  662. if (prbb->iImage != -1)
  663. {
  664. cyCheck = (fVertical) ? _cxImage : _cyImage;
  665. if (cyCheck > cy)
  666. cy = cyCheck;
  667. }
  668. return(cy + cyBorder);
  669. }
  670. // ----------------------------------------------------------------------------
  671. //
  672. // _GetRowCount
  673. //
  674. // returns the number of rows in the rebar's current configuration
  675. //
  676. // ----------------------------------------------------------------------------
  677. UINT CReBar::_GetRowCount()
  678. {
  679. UINT i;
  680. UINT cRows = 0;
  681. for (i = 0; i < _cBands; i++)
  682. {
  683. PRBB prbb = _GetBand(i);
  684. if (!(prbb->fStyle & RBBS_HIDDEN) &&
  685. _IsBandStartOfRow(prbb))
  686. {
  687. cRows++;
  688. }
  689. }
  690. return cRows;
  691. }
  692. // ----------------------------------------------------------------------------
  693. //
  694. // _GetLineHeight
  695. //
  696. // returns the height of the line of bands from iStart to iEnd, inclusively
  697. //
  698. // ----------------------------------------------------------------------------
  699. int CReBar::_GetLineHeight(UINT iStart, UINT iEnd)
  700. {
  701. int cy = 0;
  702. PRBB prbb;
  703. int cyMinChild = 0;
  704. int iMinExtra = -1;
  705. if (!(_ci.style & RBS_VARHEIGHT))
  706. {
  707. // for fixed height bars, line height is maximum height of ALL bands
  708. iStart = 0;
  709. iEnd = _cBands - 1;
  710. }
  711. UINT i = iStart;
  712. for (prbb = _rbbList + i; i <= iEnd; prbb++, i++)
  713. {
  714. if (prbb->fStyle & RBBS_HIDDEN)
  715. continue;
  716. cy = max(cy, (int)_BandGetHeight(prbb));
  717. if (prbb->cyMinChild > cyMinChild)
  718. {
  719. cyMinChild = prbb->cyMinChild;
  720. }
  721. }
  722. i = iStart;
  723. for (prbb = _rbbList + i; i <= iEnd; prbb++, i++)
  724. {
  725. if (prbb->fStyle & RBBS_HIDDEN)
  726. continue;
  727. if ((prbb->fStyle & RBBS_VARIABLEHEIGHT) && prbb->cyIntegral)
  728. {
  729. int iExtra = (cy - prbb->cyMinChild) % prbb->cyIntegral;
  730. if ((iMinExtra == -1) || (iExtra < iMinExtra))
  731. {
  732. iMinExtra = iExtra;
  733. }
  734. }
  735. }
  736. if (iMinExtra != -1)
  737. {
  738. cy -= iMinExtra;
  739. }
  740. if (cy < cyMinChild)
  741. {
  742. cy = cyMinChild;
  743. }
  744. return cy;
  745. }
  746. // _BandRecalcChevron: update & refresh chevron
  747. void CReBar::_BandRecalcChevron(PRBB prbb, BOOL fChevron)
  748. {
  749. RECT rcChevron;
  750. if (fChevron)
  751. {
  752. rcChevron.right = prbb->x + prbb->cx;
  753. rcChevron.left = rcChevron.right - CX_CHEVRON;
  754. rcChevron.top = prbb->y;
  755. rcChevron.bottom = rcChevron.top + prbb->cy;
  756. }
  757. else
  758. SetRect(&rcChevron, -1, -1, -1, -1);
  759. if (!EqualRect(&rcChevron, &prbb->rcChevron))
  760. {
  761. if (prbb->fChevron)
  762. _InvalidateRect(&prbb->rcChevron);
  763. prbb->fChevron = fChevron;
  764. CopyRect(&prbb->rcChevron, &rcChevron);
  765. if (prbb->fChevron)
  766. _InvalidateRect(&prbb->rcChevron);
  767. }
  768. }
  769. void CReBar::_InvalidateBorders(PRBB prbb)
  770. {
  771. if (_mBand.cxLeftWidth ||
  772. _mBand.cyTopHeight ||
  773. _mBand.cxRightWidth ||
  774. _mBand.cyBottomHeight)
  775. {
  776. RECT rcOuter = {prbb->x - _mBand.cxLeftWidth,
  777. prbb->y - _mBand.cyTopHeight,
  778. prbb->x + prbb->cx + _mBand.cxRightWidth,
  779. prbb->y + prbb->cy + _mBand.cyBottomHeight};
  780. RECT rcInner = {prbb->x + _mBand.cxLeftWidth,
  781. prbb->y + _mBand.cyTopHeight,
  782. prbb->x + prbb->cx - _mBand.cxRightWidth,
  783. prbb->y + prbb->cy - _mBand.cyBottomHeight};
  784. if (_ci.style & CCS_VERT)
  785. {
  786. FlipRect(&rcOuter);
  787. FlipRect(&rcInner);
  788. }
  789. HRGN hrgnOuter = CreateRectRgnIndirect(&rcOuter);
  790. if (hrgnOuter)
  791. {
  792. HRGN hrgnInner = CreateRectRgnIndirect(&rcInner);
  793. if (hrgnInner)
  794. {
  795. CombineRgn(hrgnOuter, hrgnOuter, hrgnInner, RGN_DIFF);
  796. DeleteObject(hrgnInner);
  797. }
  798. InvalidateRgn(_ci.hwnd, hrgnOuter, FALSE);
  799. DeleteObject(hrgnOuter);
  800. }
  801. }
  802. }
  803. // ----------------------------------------------------------------------------
  804. //
  805. // _ResizeChildren
  806. //
  807. // resizes children to fit properly in their respective bands' bounding rects
  808. //
  809. // ----------------------------------------------------------------------------
  810. void CReBar::_ResizeChildren()
  811. {
  812. int cx, cy, x, y, cxHeading;
  813. HDWP hdwp;
  814. BOOL fVertical = (_ci.style & CCS_VERT);
  815. PRBB prbb, prbbEnd;
  816. if (!_cBands || !_fRedraw)
  817. return;
  818. hdwp = BeginDeferWindowPos(_cBands);
  819. prbb = _GetBand(0);
  820. prbbEnd = _GetLastBand();
  821. for ( ; prbb <= prbbEnd ; prbb++)
  822. {
  823. NMREBARCHILDSIZE nm;
  824. BOOL fChevron = FALSE;
  825. if (prbb->fStyle & RBBS_HIDDEN)
  826. continue;
  827. if (!prbb->hwndChild)
  828. continue;
  829. cxHeading = _GetHeaderWidth(prbb);
  830. x = prbb->x + cxHeading;
  831. cx = prbb->cx - cxHeading;
  832. // if we're not giving child ideal size, make space for chevron button
  833. if ((cx < prbb->cxIdeal) && _UseChevron(prbb))
  834. {
  835. fChevron = TRUE;
  836. cx -= CX_CHEVRON;
  837. }
  838. if (!(prbb->fStyle & RBBS_FIXEDSIZE))
  839. {
  840. if (fVertical)
  841. {
  842. PRBB prbbNext = _GetNextVisible(prbb);
  843. if (prbbNext && !_IsBandStartOfRow(prbbNext))
  844. cx -= g_cyEdge * 2;
  845. }
  846. else
  847. cx -= CX_OFFSET;
  848. }
  849. if (cx < 0)
  850. cx = 0;
  851. y = prbb->y;
  852. cy = prbb->cy;
  853. if (prbb->cyChild && (prbb->cyChild < cy))
  854. {
  855. if (!(prbb->fStyle & RBBS_TOPALIGN))
  856. {
  857. y += (cy - prbb->cyChild) / 2;
  858. }
  859. cy = prbb->cyChild;
  860. }
  861. nm.rcChild.left = x;
  862. nm.rcChild.top = y;
  863. nm.rcChild.right = x + cx;
  864. nm.rcChild.bottom = y + cy;
  865. nm.rcBand.left = prbb->x + _GetHeaderWidth(prbb);
  866. nm.rcBand.right = prbb->x + prbb->cx;
  867. nm.rcBand.top = prbb->y;
  868. nm.rcBand.bottom = prbb->y + prbb->cy;
  869. nm.uBand = _BandToIndex(prbb);
  870. nm.wID = prbb->wID;
  871. if (fVertical)
  872. {
  873. FlipRect(&nm.rcChild);
  874. FlipRect(&nm.rcBand);
  875. }
  876. CCSendNotify(&_ci, RBN_CHILDSIZE, &nm.hdr);
  877. if (!_IsValidBand(prbb))
  878. {
  879. // somebody responded to notify by nuking bands; bail
  880. break;
  881. }
  882. _BandRecalcChevron(prbb, fChevron);
  883. _InvalidateBorders(prbb);
  884. DeferWindowPos(hdwp, prbb->hwndChild, NULL, nm.rcChild.left, nm.rcChild.top,
  885. RECTWIDTH(nm.rcChild), RECTHEIGHT(nm.rcChild), SWP_NOZORDER);
  886. }
  887. EndDeferWindowPos(hdwp);
  888. //
  889. // The SQL 7.0 Enterprise Manager Data Transformation Services MMC Snap-In
  890. // (and the Visual Basic Coolbar Sample App, too) has problems.
  891. // It hosts a rebar but doesn't set the WS_CLIPCHILDREN flag,
  892. // so when it erases its background, it wipes out the rebar. So don't
  893. // call UpdateWindow() here, or we will paint *first*, then SQL will
  894. // erase us by mistake. We have to leave our paint pending, so that
  895. // when SQL erases us by mistake, we will eventually get a WM_PAINT
  896. // message afterwards.
  897. //
  898. #if 0
  899. UpdateWindow(_ci.hwnd);
  900. #endif
  901. }
  902. // ----------------------------------------------------------------------------
  903. //
  904. // _MoveBand
  905. //
  906. // moves the band from one position to another in the rebar's band array,
  907. // updating the rebar's iCapture field as needed
  908. //
  909. // returns TRUE or FALSE if something moved
  910. // ----------------------------------------------------------------------------
  911. BOOL CReBar::_MoveBand(UINT iFrom, UINT iTo)
  912. {
  913. RBB rbbMove;
  914. int iShift;
  915. BOOL fCaptureChanged = (_uCapture == -1);
  916. if (iFrom != iTo)
  917. {
  918. rbbMove = *_GetBand(iFrom);
  919. if (_uCapture == iFrom)
  920. {
  921. _uCapture = iTo;
  922. fCaptureChanged = TRUE;
  923. }
  924. iShift = (iFrom > iTo) ? -1 : 1;
  925. while (iFrom != iTo)
  926. {
  927. if (!fCaptureChanged && (_uCapture == (iFrom + iShift)))
  928. {
  929. _uCapture = iFrom;
  930. fCaptureChanged = TRUE;
  931. }
  932. *_GetBand(iFrom) = *_GetBand(iFrom + iShift);
  933. iFrom += iShift;
  934. }
  935. *_GetBand(iTo) = rbbMove;
  936. return TRUE;
  937. }
  938. return(FALSE);
  939. }
  940. // ----------------------------------------------------------------------------
  941. //
  942. // _Recalc
  943. //
  944. // recomputes bounding rects for all bands in given rebar
  945. //
  946. // ----------------------------------------------------------------------------
  947. int CReBar::_Recalc(LPRECT prc, BOOL fForce /* = FALSE */)
  948. {
  949. PRBB prbb = _GetBand(0);
  950. PRBB prbbWalk;
  951. UINT cHidden; // # of hidden guys we've seen in current row
  952. int cxRow;
  953. int cxMin;
  954. UINT i;
  955. UINT j;
  956. UINT k;
  957. UINT iFixed = 0xFFFF;
  958. int cy;
  959. int y;
  960. int x;
  961. int cxBar;
  962. RECT rc;
  963. HWND hwndSize;
  964. BOOL fNewLine = FALSE;
  965. BOOL fChanged;
  966. BOOL fVertical = (_ci.style & CCS_VERT);
  967. BOOL fBandBorders;
  968. int iBarWidth;
  969. if (!_cBands)
  970. return(0);
  971. if ((_ci.style & CCS_NORESIZE) || (_ci.style & CCS_NOPARENTALIGN))
  972. {
  973. // size based on rebar window itself
  974. hwndSize = _ci.hwnd;
  975. }
  976. else if (!(hwndSize = _ci.hwndParent))
  977. {
  978. // size based on parent window -- if no parent window, bail now
  979. return(0);
  980. }
  981. if (!_fRecalc && !fForce)
  982. {
  983. // defer this recalc
  984. _fRecalcPending = TRUE;
  985. return 0;
  986. }
  987. else
  988. {
  989. _fRecalcPending = FALSE;
  990. }
  991. if (prc)
  992. {
  993. rc = *prc;
  994. }
  995. else
  996. {
  997. GetClientRect(hwndSize, &rc);
  998. }
  999. iBarWidth = (fVertical ? (rc.bottom - rc.top) : (rc.right - rc.left));
  1000. // this can happen because we adjust the client rect, but wedon't change
  1001. // the getminmaxinfo.
  1002. if (iBarWidth <= 0)
  1003. iBarWidth = 1;
  1004. cxBar = iBarWidth;
  1005. fBandBorders = _UseBandBorders();
  1006. for (i = 0; i < _cBands; i++)
  1007. {
  1008. _rbbList[i].cx = _rbbList[i].cxRequest;
  1009. }
  1010. y = 0;
  1011. i = 0;
  1012. // Main Loop -- loop until all bands are calculated
  1013. while (i < _cBands)
  1014. {
  1015. TraceMsg(TF_REBAR, "_Recalc: outer loop i=%d", i);
  1016. if (fBandBorders && (y > 0))
  1017. y += g_cyEdge;
  1018. y += _mBand.cyTopHeight;
  1019. ReLoop:
  1020. cxRow = 0;
  1021. cxMin = _mBand.cxLeftWidth + _mBand.cxRightWidth;
  1022. x = _mBand.cxLeftWidth;
  1023. cHidden = 0;
  1024. // Row Loop -- loop until hard line break is found or soft line break
  1025. // is necessary
  1026. for (j = i, prbbWalk = prbb; j < _cBands; j++, prbbWalk++)
  1027. {
  1028. TraceMsg(TF_REBAR, "_Recalc: inner loop j=%d", j);
  1029. if (prbbWalk->fStyle & RBBS_HIDDEN)
  1030. {
  1031. ++cHidden;
  1032. continue;
  1033. }
  1034. if (j > i + cHidden)
  1035. {
  1036. // not the first band in the row -- check for break style
  1037. if ((prbbWalk->fStyle & RBBS_BREAK) && !(prbbWalk->fStyle & RBBS_FIXEDSIZE))
  1038. break;
  1039. if (fBandBorders)
  1040. // add in space for vertical etch on palettized display
  1041. cxMin += g_cxEdge;
  1042. }
  1043. if (prbbWalk->fStyle & RBBS_FIXEDSIZE)
  1044. {
  1045. // remember location of branding brick
  1046. iFixed = j;
  1047. // if this is the first band, the next band cannot have a forced break.
  1048. if (i + cHidden == j)
  1049. {
  1050. // if the first index in the row (i) plus the number of hidden items (cHidden) leaves us at this band,
  1051. // then it's the first visible in this row.
  1052. PRBB prbbNextVis = _GetNextVisible(prbbWalk);
  1053. if (prbbNextVis && (prbbNextVis->fStyle & RBBS_BREAK))
  1054. {
  1055. // can't do this unilaterally because on startup
  1056. // some folks (net meeting) initialize it in reverse order
  1057. // and we whack off this break bit incorrectly
  1058. if (_fRedraw && IsWindowVisible(_ci.hwnd))
  1059. prbbNextVis->fStyle &= ~RBBS_BREAK;
  1060. }
  1061. }
  1062. prbbWalk->cx = prbbWalk->cxMin;
  1063. }
  1064. if (prbbWalk->cx < prbbWalk->cxMin)
  1065. prbbWalk->cx = prbbWalk->cxMin;
  1066. cxMin += prbbWalk->cxMin; // update running total of min widths
  1067. // read the assert comment below
  1068. if (j > i + cHidden)
  1069. {
  1070. // not the first band in row -- check for need to autobreak
  1071. if ((cxMin > cxBar) && (_OkayToChangeBreak(prbbWalk, RBAB_AUTOSIZE)))
  1072. // autobreak here
  1073. break;
  1074. if (fBandBorders)
  1075. {
  1076. // add in space for vertical etch on palettized display
  1077. cxRow += g_cxEdge;
  1078. }
  1079. }
  1080. cxRow += prbbWalk->cx; // update running total of current widths
  1081. cxRow += _mBand.cxLeftWidth + _mBand.cxRightWidth;
  1082. }
  1083. if (!i)
  1084. {
  1085. // first row -- handle proper placement of branding band
  1086. if (iFixed == 0xFFFF)
  1087. {
  1088. // branding band not yet found; look in the remaining bands
  1089. k = j;
  1090. for ( ; j < _cBands; j++)
  1091. {
  1092. if (_GetBand(j)->fStyle & RBBS_HIDDEN)
  1093. continue;
  1094. if (_GetBand(j)->fStyle & RBBS_FIXEDSIZE)
  1095. {
  1096. // branding band found; move to 1st row and recompute
  1097. ASSERT(j != k);
  1098. _MoveBand(j, k);
  1099. goto ReLoop;
  1100. }
  1101. }
  1102. // no branding band found -- reset j and continue on
  1103. j = k;
  1104. }
  1105. else
  1106. {
  1107. // we have a branding band; move it to
  1108. // the rightmost position in the row
  1109. _MoveBand(iFixed, j - 1);
  1110. }
  1111. TraceMsg(TF_REBAR, "_Recalc: after brand i=%d", i);
  1112. }
  1113. // variant:
  1114. // now the current row of bands is from i to j - 1
  1115. // n.b. i (and some following bands) might be hidden
  1116. // assert that j != i because then the above variant won't be true
  1117. ASSERT(j != i);
  1118. if (cxRow > cxBar)
  1119. {
  1120. // bands are too long -- shrink bands from right to left
  1121. for (k = i; k < j; k++)
  1122. {
  1123. prbbWalk--;
  1124. if (prbbWalk->fStyle & RBBS_HIDDEN)
  1125. continue;
  1126. if (prbbWalk->cx > prbbWalk->cxMin)
  1127. {
  1128. cxRow -= prbbWalk->cx - prbbWalk->cxMin;
  1129. prbbWalk->cx = prbbWalk->cxMin;
  1130. if (cxRow <= cxBar)
  1131. {
  1132. prbbWalk->cx += cxBar - cxRow;
  1133. break;
  1134. }
  1135. }
  1136. }
  1137. TraceMsg(TF_REBAR, "_Recalc: after shrink i=%d", i);
  1138. }
  1139. else if (cxRow < cxBar)
  1140. {
  1141. // bands are too short -- grow rightmost non-minimized band
  1142. for (k = j - 1; k >= i; k--)
  1143. {
  1144. ASSERT(k != (UINT)-1); // catch infinite loop
  1145. prbbWalk--;
  1146. if ((k == i) ||
  1147. (!(prbbWalk->fStyle & (RBBS_HIDDEN | RBBS_FIXEDSIZE)) &&
  1148. (prbbWalk->cx > prbb->cxMin)))
  1149. {
  1150. // the k == i check means we've made it to the first
  1151. // band on this row and so he has to get the cx change
  1152. if (prbbWalk->fStyle & RBBS_HIDDEN)
  1153. {
  1154. ASSERT(k == i);
  1155. prbbWalk = _GetNextVisible(prbbWalk);
  1156. if (!prbbWalk)
  1157. break;
  1158. }
  1159. prbbWalk->cx += cxBar - cxRow;
  1160. break;
  1161. }
  1162. }
  1163. TraceMsg(TF_REBAR, "_Recalc: after grow i=%d", i);
  1164. }
  1165. // items from index i to index j-1 (inclusive) WILL fit on one line
  1166. cy = _GetLineHeight(i, j - 1);
  1167. fChanged = FALSE; // set if any bands on current row changed position
  1168. for ( ; i < j; i++, prbb++)
  1169. {
  1170. if (prbb->fStyle & RBBS_HIDDEN)
  1171. continue;
  1172. // go through row of bands, updating positions and heights,
  1173. // invalidating as needed
  1174. if ((prbb->y != y) || (prbb->x != x) || (prbb->cy != cy))
  1175. {
  1176. TraceMsg(TF_REBAR, "_Recalc: invalidate i=%d", _BandToIndex(prbb));
  1177. fChanged = TRUE;
  1178. rc.left = min(prbb->x, x);
  1179. rc.top = min(prbb->y, y);
  1180. rc.right = cxBar;
  1181. rc.bottom = max(prbb->y + prbb->cy, y + cy);
  1182. if (fBandBorders)
  1183. {
  1184. // acount for etch line that will need to move
  1185. rc.left -= g_cxEdge;
  1186. rc.bottom += g_cyEdge/2;
  1187. }
  1188. else
  1189. {
  1190. rc.left -= _mBand.cxLeftWidth;
  1191. rc.right += _mBand.cxRightWidth;
  1192. rc.top -= _mBand.cyTopHeight;
  1193. rc.bottom += _mBand.cyBottomHeight;
  1194. }
  1195. if (!prc)
  1196. {
  1197. _InvalidateRect(&rc);
  1198. }
  1199. }
  1200. prbb->x = x;
  1201. prbb->y = y;
  1202. prbb->cy = cy;
  1203. x += _BandWidth(prbb);
  1204. }
  1205. // i and prbb now refer to the first band in the next row of bands
  1206. y += cy + _mBand.cyBottomHeight;
  1207. }
  1208. _cy = y;
  1209. return(y);
  1210. }
  1211. // ----------------------------------------------------------------------------
  1212. //
  1213. // _ResizeNow
  1214. //
  1215. // recomputes bounding rects for all bands and then resizes rebar and children
  1216. // based on these rects
  1217. //
  1218. // ----------------------------------------------------------------------------
  1219. void CReBar::_ResizeNow()
  1220. {
  1221. RECT rc;
  1222. BOOL bMirroredWnd=(_ci.dwExStyle&RTL_MIRRORED_WINDOW);
  1223. if (!_ci.hwndParent)
  1224. return;
  1225. GetWindowRect(_ci.hwnd, &rc);
  1226. //
  1227. // If this is a mirrored window, we don't won't to refect the
  1228. // coordinates since they are coming from the screen coord
  1229. // which they are not mirrored. [samera]
  1230. //
  1231. if (bMirroredWnd)
  1232. MapRectInRTLMirroredWindow(&rc, _ci.hwndParent);
  1233. else
  1234. MapWindowPoints(HWND_DESKTOP, _ci.hwndParent, (LPPOINT)&rc, 2);
  1235. _ResizeChildren();
  1236. NewSize(_ci.hwnd, _cy, _ci.style, rc.left, rc.top, RECTWIDTH(rc), RECTHEIGHT(rc));
  1237. if (_fResizeNotify)
  1238. CCSendNotify(&_ci, RBN_HEIGHTCHANGE, NULL);
  1239. _fResizeNotify = FALSE;
  1240. _fResizePending = FALSE;
  1241. }
  1242. void CReBar::_Resize(BOOL fForceHeightChange)
  1243. {
  1244. int cy;
  1245. StartOver:
  1246. // lots of the code relies on having cy calculated synchronously with _Resize,
  1247. // but we're going to delay the actual changing of the window
  1248. cy = _cy;
  1249. _Recalc(NULL);
  1250. if (_fResizing)
  1251. {
  1252. _fResizeRecursed = TRUE;
  1253. return;
  1254. }
  1255. _fResizing = TRUE;
  1256. // true overrides always
  1257. if (fForceHeightChange || (cy != _cy))
  1258. _fResizeNotify = TRUE;
  1259. if (_fRedraw)
  1260. {
  1261. _ResizeNow();
  1262. }
  1263. else
  1264. {
  1265. _fResizePending = TRUE;
  1266. }
  1267. _fResizing = FALSE;
  1268. // we do this to avoid infinite loop... _Resize can cause NewSize which causes
  1269. // a notify in which the parent sizes us, which causes us to loop.
  1270. // if the parent does any message pumping during the NewSize, we're in a loop
  1271. if (_fResizeRecursed)
  1272. {
  1273. _fResizeRecursed = FALSE;
  1274. fForceHeightChange = FALSE;
  1275. goto StartOver;
  1276. }
  1277. }
  1278. void CReBar::_SetRecalc(BOOL fRecalc)
  1279. {
  1280. _fRecalc = fRecalc;
  1281. if (fRecalc) {
  1282. if (_fRecalcPending)
  1283. _Recalc(NULL);
  1284. }
  1285. }
  1286. BOOL CReBar::_SetRedraw(BOOL fRedraw)
  1287. {
  1288. BOOL fOld = _fRedraw;
  1289. _fRedraw = fRedraw;
  1290. if (fRedraw)
  1291. {
  1292. // save off _fRefreshPending since this can
  1293. // get changed by call to _ResizeNow
  1294. BOOL fRefreshPending = _fRefreshPending;
  1295. if (_fResizePending)
  1296. _ResizeNow();
  1297. if (fRefreshPending)
  1298. _InvalidateRect(NULL);
  1299. }
  1300. return fOld;
  1301. }
  1302. BOOL CReBar::_AfterSetFont()
  1303. {
  1304. BOOL fChange = FALSE;
  1305. UINT i;
  1306. HFONT hOldFont;
  1307. HDC hdc = GetDC(_ci.hwnd);
  1308. if (!hdc)
  1309. return FALSE;
  1310. hOldFont = SelectFont(hdc, _hFont);
  1311. TEXTMETRIC tm;
  1312. if (_hTheme)
  1313. {
  1314. GetThemeTextMetrics(_hTheme, hdc, 0, 0, &tm);
  1315. }
  1316. else
  1317. {
  1318. GetTextMetrics(hdc, &tm);
  1319. }
  1320. if (_cyFont != tm.tmHeight)
  1321. {
  1322. _cyFont = tm.tmHeight;
  1323. fChange = TRUE;
  1324. }
  1325. // adjust bands
  1326. for (i = 0; i < _cBands; i++)
  1327. {
  1328. if (_GetBand(i)->fStyle & RBBS_HIDDEN)
  1329. continue;
  1330. fChange |= _BandCalcTextExtent(_GetBand(i), hdc);
  1331. }
  1332. SelectObject(hdc, hOldFont);
  1333. ReleaseDC(_ci.hwnd, hdc);
  1334. if (fChange)
  1335. {
  1336. _Resize(FALSE);
  1337. // invalidate, o.w. title doesn't redraw 1st time after font growth
  1338. _InvalidateRect(NULL);
  1339. }
  1340. return TRUE;
  1341. }
  1342. BOOL CReBar::_OnSetFont(HFONT hFont)
  1343. {
  1344. if (_fFontCreated) {
  1345. DeleteObject(_hFont);
  1346. }
  1347. _hFont = hFont;
  1348. _fFontCreated = FALSE;
  1349. if (!_hFont)
  1350. _SetFont(0);
  1351. else
  1352. return _AfterSetFont();
  1353. return TRUE;
  1354. }
  1355. // ----------------------------------------------------------------------------
  1356. //
  1357. // _SetFont
  1358. //
  1359. // sets the rebar band title font to the current system-wide caption font
  1360. //
  1361. // ----------------------------------------------------------------------------
  1362. BOOL CReBar::_SetFont(WPARAM wParam)
  1363. {
  1364. NONCLIENTMETRICS ncm;
  1365. HFONT hOldFont;
  1366. if ((wParam != 0) && (wParam != SPI_SETNONCLIENTMETRICS))
  1367. return(FALSE);
  1368. ncm.cbSize = sizeof(NONCLIENTMETRICS);
  1369. if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
  1370. return(FALSE);
  1371. hOldFont = _hFont;
  1372. ncm.lfCaptionFont.lfWeight = FW_NORMAL;
  1373. if (!(_hFont = CreateFontIndirect(&ncm.lfCaptionFont)))
  1374. {
  1375. _hFont = hOldFont;
  1376. return(FALSE);
  1377. }
  1378. _fFontCreated = TRUE;
  1379. if (hOldFont)
  1380. DeleteObject(hOldFont);
  1381. return _AfterSetFont();
  1382. }
  1383. // ----------------------------------------------------------------------------
  1384. //
  1385. // Draws a horizontal or vertical dotted line from the given (x,y) location
  1386. // for the given length (c). (From TReeView's TV_DrawDottedLine)
  1387. //
  1388. // ----------------------------------------------------------------------------
  1389. void CReBar::_VertMungeGripperRect(LPRECT lprc)
  1390. {
  1391. if (_IsVerticalGripper()) {
  1392. OffsetRect(lprc, -lprc->left + lprc->top, -lprc->top + lprc->left);
  1393. lprc->bottom -= g_cyEdge;
  1394. } else {
  1395. FlipRect(lprc);
  1396. }
  1397. }
  1398. void CReBar::_DrawChevron(PRBB prbb, HDC hdc)
  1399. {
  1400. RECT rc;
  1401. DWORD dwFlags = prbb->wChevState | DCHF_HORIZONTAL | DCHF_TRANSPARENT;
  1402. CopyRect(&rc, &prbb->rcChevron);
  1403. int iPart;
  1404. if (_IsVertical())
  1405. {
  1406. FlipRect(&rc);
  1407. iPart = RP_CHEVRONVERT;
  1408. }
  1409. else
  1410. {
  1411. dwFlags |= DCHF_TOPALIGN;
  1412. iPart = RP_CHEVRON;
  1413. }
  1414. DrawChevron(_hTheme, iPart, hdc, &rc, dwFlags);
  1415. }
  1416. void CReBar::_UpdateChevronState(PRBB prbb, WORD wControlState)
  1417. {
  1418. if (prbb)
  1419. {
  1420. // if no change in state, bail
  1421. if (!(wControlState ^ prbb->wChevState))
  1422. return;
  1423. prbb->wChevState = wControlState;
  1424. // if active (pushed or hottracked)
  1425. if (!(wControlState & DCHF_INACTIVE)) {
  1426. // then we're now the hot band
  1427. _prbbHot = prbb;
  1428. }
  1429. // else if we were the hot band then clear
  1430. else if (prbb == _prbbHot) {
  1431. _prbbHot = NULL;
  1432. }
  1433. // clear background & repaint
  1434. _InvalidateRect(&prbb->rcChevron);
  1435. UpdateWindow(_ci.hwnd);
  1436. }
  1437. }
  1438. // ----------------------------------------------------------------------------
  1439. //
  1440. // _DrawBand
  1441. //
  1442. // draws the title icon and title text of the given band into the given DC;
  1443. // also the band's chevron
  1444. //
  1445. // ----------------------------------------------------------------------------
  1446. void CReBar::_DrawBand(PRBB prbb, HDC hdc)
  1447. {
  1448. COLORREF clrBackSave, clrForeSave;
  1449. int iModeSave;
  1450. BOOL fVertical = _IsVertical();
  1451. BOOL fDrawHorizontal = (!fVertical || _IsVerticalGripper());
  1452. NMCUSTOMDRAW nmcd;
  1453. LRESULT dwRet;
  1454. if (prbb->fStyle & RBBS_HIDDEN)
  1455. {
  1456. ASSERT(0);
  1457. return;
  1458. }
  1459. clrForeSave = SetTextColor(hdc, _BandGetTextColor(prbb));
  1460. clrBackSave = SetBkColor(hdc, _BandGetBkColor(prbb));
  1461. if (prbb->hbmBack || _hTheme)
  1462. iModeSave = SetBkMode(hdc, TRANSPARENT);
  1463. nmcd.hdc = hdc;
  1464. nmcd.dwItemSpec = prbb->wID;
  1465. nmcd.uItemState = 0;
  1466. nmcd.lItemlParam = prbb->lParam;
  1467. nmcd.rc.top = prbb->y;
  1468. nmcd.rc.left = prbb->x;
  1469. nmcd.rc.bottom = nmcd.rc.top + prbb->cy;
  1470. nmcd.rc.right = nmcd.rc.left + _GetHeaderWidth(prbb);
  1471. if (_ci.style & CCS_VERT)
  1472. {
  1473. FlipRect(&nmcd.rc);
  1474. }
  1475. RECT rcTemp = {0, 0, 0, 0};
  1476. HRGN hrgnOld = CreateRectRgnIndirect(&rcTemp);
  1477. if (GetClipRgn(hdc, hrgnOld) == 0)
  1478. {
  1479. DeleteObject(hrgnOld);
  1480. hrgnOld = NULL;
  1481. }
  1482. if (_ci.style & CCS_VERT)
  1483. {
  1484. IntersectClipRect(hdc, prbb->y, prbb->x, prbb->y + prbb->cy, prbb->x + prbb->cx);
  1485. }
  1486. else
  1487. {
  1488. IntersectClipRect(hdc, prbb->x, prbb->y, prbb->x + prbb->cx, prbb->y + prbb->cy);
  1489. }
  1490. if (_hTheme)
  1491. {
  1492. RECT rcBand = {prbb->x - _mBand.cxLeftWidth,
  1493. prbb->y - _mBand.cyTopHeight,
  1494. prbb->x + prbb->cx + _mBand.cxRightWidth,
  1495. prbb->y + prbb->cy + _mBand.cyBottomHeight};
  1496. if (_ci.style & CCS_VERT)
  1497. {
  1498. FlipRect(&rcBand);
  1499. }
  1500. DrawThemeBackground(_hTheme, hdc, RP_BAND, 0, &rcBand, 0);
  1501. }
  1502. dwRet = CICustomDrawNotify(&_ci, CDDS_ITEMPREPAINT, &nmcd);
  1503. if (!(dwRet & CDRF_SKIPDEFAULT))
  1504. {
  1505. int cy = prbb->cy;
  1506. int yCenter = prbb->y + (cy / 2);
  1507. if (_IsVerticalGripper())
  1508. {
  1509. cy = _GetHeaderWidth(prbb);
  1510. yCenter = prbb->x + (cy / 2);
  1511. }
  1512. int xStart = prbb->x;
  1513. if (_ShouldDrawGripper(prbb))
  1514. {
  1515. RECT rc;
  1516. if (_hTheme)
  1517. {
  1518. int cxGripper = _GetGripperWidth();
  1519. int iPart = RP_GRIPPER;
  1520. SetRect(&rc, xStart, prbb->y, xStart + cxGripper, prbb->y + cy);
  1521. if (fVertical)
  1522. {
  1523. iPart = RP_GRIPPERVERT;
  1524. _VertMungeGripperRect(&rc);
  1525. }
  1526. DrawThemeBackground(_hTheme, hdc, iPart, 0, &rc, 0);
  1527. xStart += cxGripper;
  1528. }
  1529. else
  1530. {
  1531. int c;
  1532. int dy;
  1533. c = 3 * g_cyBorder;
  1534. xStart += 2 * g_cxBorder;
  1535. dy = g_cxEdge;
  1536. SetRect(&rc, xStart, prbb->y + dy, xStart + c, prbb->y + cy - dy);
  1537. if (fVertical)
  1538. {
  1539. _VertMungeGripperRect(&rc);
  1540. if (_IsVerticalGripper())
  1541. xStart = rc.left;
  1542. }
  1543. CCDrawEdge(hdc, &rc, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE, &(_clrsc));
  1544. xStart += c;
  1545. }
  1546. }
  1547. xStart += 2 * (fVertical ? g_cyEdge : g_cxEdge);
  1548. if (prbb->iImage != -1)
  1549. {
  1550. int yStart;
  1551. IMAGELISTDRAWPARAMS imldp = {0};
  1552. yStart = yCenter - ((!fDrawHorizontal ? _cxImage : _cyImage) / 2);
  1553. imldp.cbSize = sizeof(imldp);
  1554. imldp.himl = _himl;
  1555. imldp.i = prbb->iImage;
  1556. imldp.hdcDst = hdc;
  1557. imldp.x = (!fDrawHorizontal ? yStart : xStart);
  1558. imldp.y = (!fDrawHorizontal ? xStart : yStart);
  1559. imldp.rgbBk = CLR_DEFAULT;
  1560. imldp.rgbFg = CLR_DEFAULT;
  1561. imldp.fStyle = ILD_TRANSPARENT;
  1562. imldp.fState = 0;
  1563. ImageList_DrawIndirect(&imldp);
  1564. xStart += (fDrawHorizontal ? (_cxImage + g_cxEdge) : (_cyImage + g_cyEdge));
  1565. }
  1566. if (_ShowText(prbb))
  1567. {
  1568. UINT uFormat=0;
  1569. RECT rcText;
  1570. HRESULT hr = E_FAIL;
  1571. rcText.left = fDrawHorizontal ? xStart : yCenter - (prbb->cxText / 2);
  1572. rcText.top = fDrawHorizontal ? yCenter - (_cyFont / 2) : xStart;
  1573. if (fDrawHorizontal)
  1574. rcText.top -= 1; // fudge
  1575. rcText.right = rcText.left + prbb->cxText;
  1576. rcText.bottom = rcText.top + _cyFont;
  1577. // for clients >= v5, we draw text with prefix processing (& underlines next char)
  1578. if (CCGetUIState(&(_ci)) & UISF_HIDEACCEL)
  1579. uFormat= DT_HIDEPREFIX;
  1580. HFONT hFontSave = SelectFont(hdc, _hFont);
  1581. if (_hTheme)
  1582. hr = DrawThemeText(_hTheme, hdc, 0, 0, prbb->lpText, lstrlen(prbb->lpText), uFormat, 0, &rcText);
  1583. if (FAILED(hr))
  1584. {
  1585. DrawText(hdc, prbb->lpText, lstrlen(prbb->lpText), &rcText, uFormat);
  1586. }
  1587. SelectObject(hdc, hFontSave);
  1588. }
  1589. // maybe draw chevron
  1590. if (_UseChevron(prbb) && prbb->fChevron)
  1591. _DrawChevron(prbb, hdc);
  1592. }
  1593. if (dwRet & CDRF_NOTIFYPOSTPAINT)
  1594. CICustomDrawNotify(&_ci, CDDS_ITEMPOSTPAINT, &nmcd);
  1595. if (prbb->hbmBack || _hTheme)
  1596. SetBkMode(hdc, iModeSave);
  1597. SetTextColor(hdc, clrForeSave);
  1598. SetBkColor(hdc, clrBackSave);
  1599. SelectClipRgn(hdc, hrgnOld);
  1600. if (hrgnOld)
  1601. {
  1602. DeleteObject(hrgnOld);
  1603. }
  1604. }
  1605. // ----------------------------------------------------------------------------
  1606. //
  1607. // _OnPaint
  1608. //
  1609. // processes WM_PAINT message
  1610. //
  1611. // ----------------------------------------------------------------------------
  1612. void CReBar::_OnPaint(HDC hdcIn)
  1613. {
  1614. HDC hdc = hdcIn;
  1615. PAINTSTRUCT ps;
  1616. UINT i;
  1617. NMCUSTOMDRAW nmcd;
  1618. if (!hdcIn)
  1619. {
  1620. hdc = BeginPaint(_ci.hwnd, &ps);
  1621. }
  1622. nmcd.hdc = hdc;
  1623. nmcd.uItemState = 0;
  1624. nmcd.lItemlParam = 0;
  1625. nmcd.rc = ps.rcPaint;
  1626. _ci.dwCustom = CICustomDrawNotify(&_ci, CDDS_PREPAINT, &nmcd);
  1627. if (!(_ci.dwCustom & CDRF_SKIPDEFAULT))
  1628. {
  1629. for (i = 0; i < _cBands; i++) {
  1630. if (_GetBand(i)->fStyle & RBBS_HIDDEN)
  1631. continue;
  1632. _DrawBand(_GetBand(i), hdc);
  1633. }
  1634. }
  1635. if (_ci.dwCustom & CDRF_NOTIFYPOSTPAINT)
  1636. CICustomDrawNotify(&_ci, CDDS_POSTPAINT, &nmcd);
  1637. if (!hdcIn)
  1638. EndPaint(_ci.hwnd, &ps);
  1639. }
  1640. // ----------------------------------------------------------------------------
  1641. //
  1642. // _BandTileBlt
  1643. //
  1644. // Fills the given rectangle with the rebar's background bitmap, tiling if
  1645. // necessary
  1646. //
  1647. // ----------------------------------------------------------------------------
  1648. void CReBar::_BandTileBlt(PRBB prbb, int x, int y, int cx, int cy, HDC hdcDst, HDC hdcSrc)
  1649. {
  1650. int xOff = 0;
  1651. int yOff = 0;
  1652. BOOL fxTile, fyTile;
  1653. int cxPart, cyPart;
  1654. int iPixelOffset = 0;
  1655. if (!(prbb->fStyle & RBBS_FIXEDBMP))
  1656. {
  1657. if (_ci.style & CCS_VERT)
  1658. {
  1659. xOff = -prbb->y;
  1660. yOff = -prbb->x;
  1661. }
  1662. else
  1663. {
  1664. xOff = -prbb->x;
  1665. yOff = -prbb->y;
  1666. }
  1667. }
  1668. xOff += x;
  1669. if (xOff >= prbb->cxBmp)
  1670. xOff %= prbb->cxBmp;
  1671. yOff += y;
  1672. if (yOff >= prbb->cyBmp)
  1673. yOff %= prbb->cyBmp;
  1674. ReCheck:
  1675. fxTile = ((xOff + cx) > prbb->cxBmp);
  1676. fyTile = ((yOff + cy) > prbb->cyBmp);
  1677. if (!fxTile && !fyTile)
  1678. {
  1679. // no tiling needed -- blt and leave
  1680. BitBlt(hdcDst, x , y, cx, cy, hdcSrc, xOff + iPixelOffset, yOff, SRCCOPY);
  1681. return;
  1682. }
  1683. if (!fxTile)
  1684. {
  1685. // vertically tile
  1686. cyPart = prbb->cyBmp - yOff;
  1687. BitBlt(hdcDst, x, y, cx, cyPart, hdcSrc, xOff + iPixelOffset, yOff, SRCCOPY);
  1688. y += cyPart;
  1689. cy -= cyPart;
  1690. yOff = 0;
  1691. goto ReCheck;
  1692. }
  1693. if (!fyTile)
  1694. {
  1695. // horizontally tile
  1696. cxPart = prbb->cxBmp - xOff;
  1697. BitBlt(hdcDst, x, y, cxPart, cy, hdcSrc, xOff + iPixelOffset, yOff, SRCCOPY);
  1698. x += cxPart;
  1699. cx -= cxPart;
  1700. xOff = 0;
  1701. goto ReCheck;
  1702. }
  1703. // tile both ways
  1704. cyPart = prbb->cyBmp - yOff;
  1705. _BandTileBlt(prbb, x, y, cx, cyPart, hdcDst, hdcSrc);
  1706. y += cyPart;
  1707. cy -= cyPart;
  1708. yOff = 0;
  1709. goto ReCheck;
  1710. }
  1711. // this is using virtual coordinate space (internal always horizontal)
  1712. int CReBar::_InternalHitTest(LPRBHITTESTINFO prbht, int x, int y)
  1713. {
  1714. BOOL fVert = (_ci.style & CCS_VERT);
  1715. UINT i;
  1716. PRBB prbb = _GetBand(0);
  1717. int cx;
  1718. RBHITTESTINFO rbht;
  1719. if (!prbht)
  1720. prbht = &rbht;
  1721. for (i = 0; i < _cBands; i++, prbb++)
  1722. {
  1723. if (prbb->fStyle & RBBS_HIDDEN)
  1724. continue;
  1725. if (x >= prbb->x - _mBand.cxLeftWidth &&
  1726. y >= prbb->y - _mBand.cyTopHeight &&
  1727. x <= prbb->x + prbb->cx + _mBand.cxRightWidth &&
  1728. y <= prbb->y + prbb->cy + _mBand.cyTopHeight)
  1729. {
  1730. cx = _GetHeaderWidth(prbb);
  1731. if (x <= prbb->x + cx + _mBand.cxRightWidth)
  1732. {
  1733. prbht->flags = RBHT_CAPTION;
  1734. if (_IsVerticalGripper())
  1735. {
  1736. if (y - prbb->y < _GetGripperWidth())
  1737. prbht->flags = RBHT_GRABBER;
  1738. }
  1739. else
  1740. {
  1741. cx = _GetGripperWidth() * (fVert ? g_cyBorder : g_cxBorder);
  1742. if (_ShouldDrawGripper(_GetBand(i)) &&
  1743. (x <= prbb->x + cx + _mBand.cxRightWidth))
  1744. {
  1745. prbht->flags = RBHT_GRABBER;
  1746. }
  1747. }
  1748. }
  1749. else
  1750. {
  1751. POINT pt;
  1752. pt.x = x;
  1753. pt.y = y;
  1754. if (_UseChevron(prbb) &&
  1755. prbb->fChevron &&
  1756. PtInRect(&prbb->rcChevron, pt))
  1757. {
  1758. prbht->flags = RBHT_CHEVRON;
  1759. }
  1760. else
  1761. {
  1762. prbht->flags = RBHT_CLIENT;
  1763. }
  1764. }
  1765. prbht->iBand = i;
  1766. return i;
  1767. }
  1768. }
  1769. prbht->flags = RBHT_NOWHERE;
  1770. prbht->iBand = -1;
  1771. return -1;
  1772. }
  1773. // ----------------------------------------------------------------------------
  1774. //
  1775. // _HitTest
  1776. //
  1777. // returns the index to the band that the given point lies in, or -1 if outside
  1778. // of all bands. Also, sets flags to indicate which part of the band the
  1779. // point lies in.
  1780. //
  1781. // ----------------------------------------------------------------------------
  1782. int CReBar::_HitTest(LPRBHITTESTINFO prbht)
  1783. {
  1784. BOOL fVert = (_ci.style & CCS_VERT);
  1785. POINT pt;
  1786. if (fVert)
  1787. {
  1788. pt.x = prbht->pt.y;
  1789. pt.y = prbht->pt.x;
  1790. }
  1791. else
  1792. pt = prbht->pt;
  1793. return _InternalHitTest(prbht, pt.x, pt.y);
  1794. }
  1795. // ----------------------------------------------------------------------------
  1796. //
  1797. // _EraseBkgnd
  1798. //
  1799. // processes WM_ERASEBKGND message by drawing band borders, if necessary, and
  1800. // filling in the rebar bands with their background color
  1801. //
  1802. // ----------------------------------------------------------------------------
  1803. BOOL CReBar::_EraseBkgnd(HDC hdc, int iBand)
  1804. {
  1805. BOOL fVertical = (_ci.style & CCS_VERT);
  1806. NMCUSTOMDRAW nmcd;
  1807. LRESULT dwItemRet;
  1808. BOOL fBandBorders = _UseBandBorders();
  1809. RECT rcClient;
  1810. HDC hdcMem = NULL;
  1811. UINT i;
  1812. PRBB prbb = _GetBand(0);
  1813. nmcd.hdc = hdc;
  1814. nmcd.uItemState = 0;
  1815. nmcd.lItemlParam = 0;
  1816. _ci.dwCustom = CICustomDrawNotify(&_ci, CDDS_PREERASE, &nmcd);
  1817. if (!(_ci.dwCustom & CDRF_SKIPDEFAULT))
  1818. {
  1819. COLORREF clrBk;
  1820. GetClientRect(_ci.hwnd, &rcClient);
  1821. if (_hTheme)
  1822. {
  1823. RECT rcClip;
  1824. if (GetClipBox(hdc, &rcClip) == NULLREGION)
  1825. rcClip = rcClient;
  1826. if (CCShouldAskForBits(&_ci, _hTheme, 0, 0))
  1827. CCForwardPrint(&_ci, hdc);
  1828. DrawThemeBackground(_hTheme, hdc, 0, 0, &rcClient, &rcClip);
  1829. }
  1830. else
  1831. {
  1832. clrBk = _GetBkColor();
  1833. if (clrBk != CLR_NONE)
  1834. {
  1835. FillRectClr(hdc, &rcClient, clrBk);
  1836. }
  1837. }
  1838. for (i = 0; i < _cBands; i++, prbb++)
  1839. {
  1840. if (prbb->fStyle & RBBS_HIDDEN)
  1841. continue;
  1842. if (fVertical)
  1843. SetRect(&nmcd.rc, prbb->y, prbb->x, prbb->y + prbb->cy, prbb->x + prbb->cx);
  1844. else
  1845. SetRect(&nmcd.rc, prbb->x, prbb->y, prbb->x + prbb->cx, prbb->y + prbb->cy);
  1846. if (fBandBorders)
  1847. {
  1848. if (prbb->x != _mBand.cxLeftWidth)
  1849. {
  1850. // draw etch between bands on same row
  1851. if (fVertical)
  1852. {
  1853. nmcd.rc.right += g_cxEdge / 2;
  1854. nmcd.rc.top -= g_cyEdge;
  1855. CCThemeDrawEdge(_hTheme, hdc, &nmcd.rc, RP_BAND, 0, EDGE_ETCHED, BF_TOP, &(_clrsc));
  1856. nmcd.rc.right -= g_cxEdge / 2;
  1857. nmcd.rc.top += g_cyEdge;
  1858. }
  1859. else
  1860. {
  1861. nmcd.rc.bottom += g_cyEdge / 2;
  1862. nmcd.rc.left -= g_cxEdge;
  1863. CCThemeDrawEdge(_hTheme, hdc, &nmcd.rc, RP_BAND, 0, EDGE_ETCHED, BF_LEFT, &(_clrsc));
  1864. nmcd.rc.bottom -= g_cyEdge / 2;
  1865. nmcd.rc.left += g_cxEdge;
  1866. }
  1867. }
  1868. else
  1869. {
  1870. // draw etch between rows
  1871. if (fVertical)
  1872. {
  1873. rcClient.right = prbb->y + prbb->cy + g_cxEdge;
  1874. CCThemeDrawEdge(_hTheme, hdc, &rcClient, RP_BAND, 0, EDGE_ETCHED, BF_RIGHT, &(_clrsc));
  1875. }
  1876. else
  1877. {
  1878. rcClient.bottom = prbb->y + prbb->cy + g_cyEdge;
  1879. CCThemeDrawEdge(_hTheme, hdc, &rcClient, RP_BAND, 0, EDGE_ETCHED, BF_BOTTOM, &(_clrsc));
  1880. }
  1881. }
  1882. }
  1883. nmcd.dwItemSpec = prbb->wID;
  1884. nmcd.uItemState = 0;
  1885. dwItemRet = CICustomDrawNotify(&_ci, CDDS_ITEMPREERASE, &nmcd);
  1886. if (!(dwItemRet & CDRF_SKIPDEFAULT))
  1887. {
  1888. if (prbb->hbmBack)
  1889. {
  1890. if (!hdcMem)
  1891. {
  1892. hdcMem = CreateCompatibleDC(hdc);
  1893. if (!hdcMem)
  1894. continue;
  1895. _Realize(hdc, TRUE, FALSE);
  1896. }
  1897. SelectObject(hdcMem, prbb->hbmBack);
  1898. _BandTileBlt(prbb, nmcd.rc.left, nmcd.rc.top, nmcd.rc.right - nmcd.rc.left,
  1899. nmcd.rc.bottom - nmcd.rc.top, hdc, hdcMem);
  1900. }
  1901. else if (_hTheme)
  1902. {
  1903. DrawThemeBackground(_hTheme, hdc, RP_BAND, 0, &nmcd.rc, 0);
  1904. }
  1905. else
  1906. {
  1907. // if the color for this band is the same as the
  1908. // rebar's default background color, then we
  1909. // don't need to paint this specially
  1910. COLORREF clr = _BandGetBkColor(prbb);
  1911. if (clr != _GetBkColor())
  1912. {
  1913. FillRectClr(hdc, &nmcd.rc, clr);
  1914. }
  1915. }
  1916. }
  1917. if (dwItemRet & CDRF_NOTIFYPOSTERASE)
  1918. CICustomDrawNotify(&_ci, CDDS_ITEMPOSTERASE, &nmcd);
  1919. }
  1920. if (hdcMem)
  1921. {
  1922. DeleteDC(hdcMem);
  1923. }
  1924. }
  1925. if (_ci.dwCustom & CDRF_NOTIFYPOSTERASE)
  1926. {
  1927. nmcd.uItemState = 0;
  1928. nmcd.dwItemSpec = 0;
  1929. nmcd.lItemlParam = 0;
  1930. CICustomDrawNotify(&_ci, CDDS_POSTERASE, &nmcd);
  1931. }
  1932. return(TRUE);
  1933. }
  1934. // ----------------------------------------------------------------------------
  1935. //
  1936. // _GetBarInfo
  1937. //
  1938. // retrieves the indicated values from the rebar's internal structure
  1939. //
  1940. // ----------------------------------------------------------------------------
  1941. BOOL CReBar::_GetBarInfo(LPREBARINFO lprbi)
  1942. {
  1943. if (lprbi->cbSize != sizeof(REBARINFO))
  1944. return(FALSE);
  1945. if (lprbi->fMask & RBIM_IMAGELIST)
  1946. lprbi->himl = _himl;
  1947. return(TRUE);
  1948. }
  1949. // ----------------------------------------------------------------------------
  1950. //
  1951. // _SetBarInfo
  1952. //
  1953. // sets the indicated values in the rebar's internal structure, recalculating
  1954. // and refreshing as needed
  1955. //
  1956. // ----------------------------------------------------------------------------
  1957. BOOL CReBar::_SetBarInfo(LPREBARINFO lprbi)
  1958. {
  1959. if (lprbi->cbSize != sizeof(REBARINFO))
  1960. return(FALSE);
  1961. if (lprbi->fMask & RBIM_IMAGELIST)
  1962. {
  1963. HIMAGELIST himl = _himl;
  1964. int cxOld, cyOld;
  1965. //todo:validate lprbi->himl
  1966. _himl = lprbi->himl;
  1967. cxOld = _cxImage;
  1968. cyOld = _cyImage;
  1969. ImageList_GetIconSize(_himl, (LPINT)&_cxImage, (LPINT)&_cyImage);
  1970. if ((_cxImage != cxOld) || (_cyImage != cyOld))
  1971. {
  1972. UINT i;
  1973. for (i = 0; i < _cBands; i++) {
  1974. if (_GetBand(i)->fStyle & RBBS_HIDDEN)
  1975. continue;
  1976. _BandCalcMinWidth(_GetBand(i));
  1977. }
  1978. _Resize(FALSE);
  1979. }
  1980. else
  1981. _InvalidateRect(NULL);
  1982. lprbi->himl = himl;
  1983. }
  1984. return(TRUE);
  1985. }
  1986. // ----------------------------------------------------------------------------
  1987. //
  1988. // _GetBandInfo
  1989. //
  1990. // retrieves the indicated values from the specified band's internal structure
  1991. //
  1992. // ----------------------------------------------------------------------------
  1993. BOOL CReBar::_GetBandInfo(UINT uBand, LPREBARBANDINFO lprbbi)
  1994. {
  1995. PRBB prbb;
  1996. if (!_IsValidIndex(uBand) || lprbbi->cbSize > SIZEOF(REBARBANDINFO))
  1997. return(FALSE);
  1998. prbb = _GetBand(uBand);
  1999. if (lprbbi->fMask & RBBIM_SIZE) {
  2000. if (prbb->fStyle & RBBS_FIXEDSIZE)
  2001. lprbbi->cx = prbb->cx;
  2002. else
  2003. lprbbi->cx = prbb->cxRequest;
  2004. }
  2005. if (lprbbi->fMask & RBBIM_STYLE)
  2006. lprbbi->fStyle = prbb->fStyle;
  2007. if (lprbbi->fMask & RBBIM_COLORS)
  2008. {
  2009. lprbbi->clrFore = _BandGetTextColorExternal(prbb);
  2010. lprbbi->clrBack = _BandGetBkColorExternal(prbb);
  2011. }
  2012. if (lprbbi->fMask & RBBIM_TEXT)
  2013. {
  2014. UINT cch = prbb->lpText ? lstrlen(prbb->lpText) : 0;
  2015. if (!lprbbi->cch || !lprbbi->lpText || (lprbbi->cch <= cch))
  2016. lprbbi->cch = cch + 1;
  2017. else if (prbb->lpText)
  2018. lstrcpy(lprbbi->lpText, prbb->lpText);
  2019. else
  2020. // no text -- so just make it an empty string
  2021. lprbbi->lpText[0] = 0;
  2022. }
  2023. if (lprbbi->fMask & RBBIM_IMAGE)
  2024. lprbbi->iImage = prbb->iImage;
  2025. if (lprbbi->fMask & RBBIM_CHILD)
  2026. lprbbi->hwndChild = prbb->hwndChild;
  2027. if (lprbbi->fMask & RBBIM_CHILDSIZE)
  2028. {
  2029. // HACKHACK: (tjgreen) Subtract the offset we added in SetBandInfo (see
  2030. // comments there).
  2031. lprbbi->cxMinChild = prbb->cxMinChild ? prbb->cxMinChild - CX_OFFSET : 0;
  2032. lprbbi->cyMinChild = prbb->cyMinChild;
  2033. }
  2034. if (lprbbi->fMask & RBBIM_BACKGROUND)
  2035. lprbbi->hbmBack = prbb->hbmBack;
  2036. if (lprbbi->fMask & RBBIM_ID)
  2037. lprbbi->wID = prbb->wID;
  2038. if (lprbbi->cbSize > REBARBANDINFO_V3_SIZE)
  2039. {
  2040. if ((lprbbi->fMask & RBBIM_CHILDSIZE) && (prbb->fStyle & RBBS_VARIABLEHEIGHT))
  2041. {
  2042. lprbbi->cyIntegral = prbb->cyIntegral;
  2043. lprbbi->cyMaxChild = prbb->cyMaxChild;
  2044. lprbbi->cyChild = prbb->cyChild;
  2045. }
  2046. if (lprbbi->fMask & RBBIM_HEADERSIZE)
  2047. lprbbi->cxHeader = _GetHeaderWidth(prbb);
  2048. if (lprbbi->fMask & RBBIM_IDEALSIZE)
  2049. // HACKHACK: (tjgreen) Subtract the offset we added in SetBandInfo (see
  2050. // comments there).
  2051. lprbbi->cxIdeal = prbb->cxIdeal ? prbb->cxIdeal - CX_OFFSET : 0;
  2052. if (lprbbi->fMask & RBBIM_LPARAM)
  2053. lprbbi->lParam = prbb->lParam;
  2054. }
  2055. return(TRUE);
  2056. }
  2057. BOOL CReBar::_ValidateBandInfo(LPREBARBANDINFO *pprbbi, LPREBARBANDINFO prbbi)
  2058. {
  2059. BOOL fRet = ((*pprbbi)->cbSize == sizeof(REBARBANDINFO));
  2060. if (!fRet) {
  2061. if ((*pprbbi)->cbSize < SIZEOF(REBARBANDINFO)) {
  2062. hmemcpy(prbbi, (*pprbbi), (*pprbbi)->cbSize);
  2063. (*pprbbi) = prbbi;
  2064. prbbi->cbSize = SIZEOF(REBARBANDINFO);
  2065. fRet = TRUE;
  2066. }
  2067. }
  2068. return fRet;
  2069. }
  2070. // ----------------------------------------------------------------------------
  2071. //
  2072. // _SetBandInfo
  2073. //
  2074. // sets the indicated values in the specified band's internal structure,
  2075. // recalculating and refreshing as needed
  2076. //
  2077. // ----------------------------------------------------------------------------
  2078. BOOL CReBar::_SetBandInfo(UINT uBand, LPREBARBANDINFO lprbbi, BOOL fAllowRecalc)
  2079. {
  2080. PRBB prbb;
  2081. BOOL fRefresh = FALSE;
  2082. BOOL fRecalc = FALSE;
  2083. BOOL fRecalcMin = FALSE;
  2084. BOOL fTextChanged = FALSE;
  2085. REBARBANDINFO rbbi = {0};
  2086. RECT rc;
  2087. if (!_IsValidIndex(uBand) || !_ValidateBandInfo(&lprbbi, &rbbi))
  2088. return(FALSE);
  2089. prbb = _GetBand(uBand);
  2090. if (lprbbi->fMask & RBBIM_TEXT)
  2091. {
  2092. if (!lprbbi->lpText || !prbb->lpText || lstrcmp(lprbbi->lpText, prbb->lpText))
  2093. {
  2094. if (lprbbi->lpText != prbb->lpText) {
  2095. Str_Set(&prbb->lpText, lprbbi->lpText);
  2096. fTextChanged = TRUE;
  2097. }
  2098. }
  2099. }
  2100. if (lprbbi->fMask & RBBIM_STYLE)
  2101. {
  2102. UINT fStylePrev = prbb->fStyle;
  2103. UINT fChanged = lprbbi->fStyle ^ fStylePrev;
  2104. prbb->fStyle = lprbbi->fStyle;
  2105. if (fChanged)
  2106. fRecalc = TRUE;
  2107. if ((prbb->fStyle & RBBS_FIXEDSIZE) && !(fStylePrev & RBBS_FIXEDSIZE))
  2108. prbb->cxMin = prbb->cx;
  2109. else if (fChanged & RBBS_FIXEDSIZE)
  2110. fRecalcMin = TRUE;
  2111. if (fChanged & RBBS_GRIPPERALWAYS)
  2112. fRecalcMin = TRUE;
  2113. if (fChanged & RBBS_HIDDEN)
  2114. _ShowBand(uBand, !(prbb->fStyle & RBBS_HIDDEN));
  2115. if (fChanged & RBBS_HIDETITLE)
  2116. fTextChanged = TRUE;
  2117. // can't have both of these
  2118. if (prbb->fStyle & RBBS_FIXEDSIZE)
  2119. prbb->fStyle &= ~RBBS_BREAK;
  2120. }
  2121. // RBBIM_TEXT does calculations that want to take some RBBIM_STYLE bits
  2122. // into account, so delay those calculations until we grab the style bits.
  2123. //
  2124. if (fTextChanged && !(prbb->fStyle & RBBS_HIDDEN))
  2125. {
  2126. if (_BandCalcTextExtent(prbb, NULL))
  2127. fRecalc = TRUE;
  2128. else
  2129. fRefresh = TRUE;
  2130. }
  2131. if (lprbbi->fMask & RBBIM_IDEALSIZE)
  2132. {
  2133. // HACKHACK: (tjgreen) Add an offset to the width the caller specifies.
  2134. // This offset gets clipped off in _ResizeChildren, so the child window is
  2135. // rendered with the width specified by caller, and we get a little space on
  2136. // the toolbar after the buttons. If caller specifies zero-width, though,
  2137. // we don't want this extra space, so don't add offset.
  2138. int cxIdeal = lprbbi->cxIdeal ? lprbbi->cxIdeal + CX_OFFSET : 0;
  2139. if (cxIdeal != prbb->cxIdeal)
  2140. {
  2141. prbb->cxIdeal = cxIdeal;
  2142. fRecalcMin = TRUE;
  2143. fRecalc = TRUE;
  2144. }
  2145. }
  2146. if (lprbbi->fMask & RBBIM_SIZE)
  2147. {
  2148. if (prbb->cxRequest != (int)lprbbi->cx)
  2149. {
  2150. fRecalc = TRUE;
  2151. prbb->cxRequest = lprbbi->cx;
  2152. }
  2153. if (prbb->fStyle & RBBS_FIXEDSIZE)
  2154. prbb->cxMin = prbb->cxRequest;
  2155. }
  2156. if (lprbbi->fMask & RBBIM_HEADERSIZE)
  2157. {
  2158. if ((lprbbi->cxHeader == -1) ||
  2159. !(prbb->fStyle & RBBS_FIXEDHEADERSIZE) ||
  2160. (prbb->cxMin != (int)lprbbi->cxHeader + prbb->cxMinChild))
  2161. {
  2162. if (lprbbi->cxHeader == -1)
  2163. {
  2164. prbb->fStyle &= ~RBBS_FIXEDHEADERSIZE;
  2165. fRecalcMin = TRUE;
  2166. }
  2167. else
  2168. {
  2169. prbb->fStyle |= RBBS_FIXEDHEADERSIZE;
  2170. prbb->cxMin = lprbbi->cxHeader + prbb->cxMinChild;
  2171. }
  2172. fRecalc = TRUE;
  2173. fRefresh = TRUE;
  2174. }
  2175. }
  2176. if (lprbbi->fMask & RBBIM_COLORS)
  2177. {
  2178. prbb->clrFore = lprbbi->clrFore;
  2179. prbb->clrBack = lprbbi->clrBack;
  2180. fRefresh = TRUE;
  2181. }
  2182. if ((lprbbi->fMask & RBBIM_IMAGE) && (prbb->iImage != lprbbi->iImage))
  2183. {
  2184. BOOL fToggleBmp = ((prbb->iImage == -1) || (lprbbi->iImage == -1));
  2185. prbb->iImage = lprbbi->iImage;
  2186. if (fToggleBmp)
  2187. {
  2188. fRecalc = TRUE;
  2189. fRecalcMin = TRUE;
  2190. }
  2191. else
  2192. fRefresh = TRUE;
  2193. }
  2194. if (lprbbi->fMask & RBBIM_CHILD &&
  2195. lprbbi->hwndChild != prbb->hwndChild &&
  2196. (NULL == lprbbi->hwndChild ||
  2197. !IsChild(lprbbi->hwndChild, _ci.hwnd)))
  2198. {
  2199. if (IsWindow(prbb->hwndChild))
  2200. ShowWindow(prbb->hwndChild, SW_HIDE);
  2201. prbb->hwndChild = lprbbi->hwndChild;
  2202. if (prbb->hwndChild)
  2203. {
  2204. SetParent(prbb->hwndChild, _ci.hwnd);
  2205. ShowWindow(prbb->hwndChild, SW_SHOW);
  2206. }
  2207. fRecalc = TRUE;
  2208. }
  2209. if (lprbbi->fMask & RBBIM_CHILDSIZE)
  2210. {
  2211. int cyChildOld = prbb->cyChild;
  2212. if (lprbbi->cyMinChild != -1)
  2213. prbb->cyMinChild = lprbbi->cyMinChild;
  2214. if (prbb->fStyle & RBBS_VARIABLEHEIGHT)
  2215. {
  2216. BOOL fIntegralLarger = FALSE;
  2217. if (lprbbi->cyIntegral != -1)
  2218. {
  2219. fIntegralLarger = ((int)lprbbi->cyIntegral > prbb->cyIntegral);
  2220. prbb->cyIntegral = lprbbi->cyIntegral;
  2221. }
  2222. if (lprbbi->cyMaxChild != -1)
  2223. prbb->cyMaxChild = lprbbi->cyMaxChild;
  2224. if (lprbbi->cyChild != -1)
  2225. prbb->cyChild = lprbbi->cyChild;
  2226. if (prbb->cyChild < prbb->cyMinChild)
  2227. prbb->cyChild = prbb->cyMinChild;
  2228. if (prbb->cyChild > prbb->cyMaxChild)
  2229. prbb->cyChild = prbb->cyMaxChild;
  2230. // validate the child size. cyChild must be cyMinChild plux n*cyIntegral
  2231. if (prbb->cyIntegral)
  2232. {
  2233. int iExtra;
  2234. iExtra = (prbb->cyChild - prbb->cyMinChild) % prbb->cyIntegral;
  2235. // Don't change cyChild if it is already an valid integral height
  2236. if (iExtra)
  2237. {
  2238. if (fIntegralLarger)
  2239. {
  2240. // Round up
  2241. prbb->cyChild += (prbb->cyIntegral - iExtra);
  2242. }
  2243. else
  2244. {
  2245. // Round down
  2246. prbb->cyChild -= iExtra;
  2247. }
  2248. }
  2249. }
  2250. }
  2251. else
  2252. {
  2253. // if we're not in variable height mode, then
  2254. // the cyChild is the same as cyMinChild.
  2255. // this is a little peculiar, but done this way for backcompat.
  2256. // cyMinChild came before cyChild
  2257. prbb->cyChild = lprbbi->cyMinChild;
  2258. }
  2259. if (lprbbi->cxMinChild != -1)
  2260. {
  2261. // HACKHACK: (tjgreen) Add an offset to the width the caller specifies.
  2262. // This offset gets clipped off in _ResizeChildren, so the child window is
  2263. // rendered with the width specified by caller, and we get a little space on
  2264. // the toolbar after the buttons. However, if caller specifies zero-width or
  2265. // if the band is fixed size, we don't want this extra space, so don't add offset.
  2266. int cxMinChild = lprbbi->cxMinChild;
  2267. if ((lprbbi->cxMinChild != 0) && !(prbb->fStyle & RBBS_FIXEDSIZE))
  2268. cxMinChild += CX_OFFSET;
  2269. if (prbb->cxMinChild != cxMinChild)
  2270. {
  2271. int cxOldHeaderMin = _GetHeaderWidth(prbb);
  2272. if (prbb->fStyle & RBBS_FIXEDSIZE)
  2273. fRecalc = TRUE;
  2274. prbb->cxMinChild = cxMinChild;
  2275. if (prbb->fStyle & RBBS_FIXEDHEADERSIZE)
  2276. prbb->cxMin = cxOldHeaderMin + prbb->cxMinChild;
  2277. fRecalcMin = TRUE;
  2278. }
  2279. if (cyChildOld != prbb->cyChild)
  2280. {
  2281. // TODO: revisit optimization:
  2282. // if (_BandGetHeight(prbb) != prbb->cy)
  2283. fRecalc = TRUE;
  2284. }
  2285. }
  2286. }
  2287. if (lprbbi->fMask & RBBIM_BACKGROUND)
  2288. {
  2289. DIBSECTION dib;
  2290. if (lprbbi->hbmBack && !GetObject(lprbbi->hbmBack, sizeof(DIBSECTION), &dib))
  2291. return(FALSE);
  2292. prbb->hbmBack = lprbbi->hbmBack;
  2293. prbb->cxBmp = dib.dsBm.bmWidth;
  2294. prbb->cyBmp = dib.dsBm.bmHeight;
  2295. fRefresh = TRUE;
  2296. }
  2297. if (lprbbi->fMask & RBBIM_ID)
  2298. prbb->wID = lprbbi->wID;
  2299. if (lprbbi->fMask & RBBIM_LPARAM)
  2300. prbb->lParam = lprbbi->lParam;
  2301. if (fRecalcMin && !(prbb->fStyle & RBBS_HIDDEN))
  2302. _BandCalcMinWidth(prbb);
  2303. if (fAllowRecalc)
  2304. {
  2305. if (fRecalc)
  2306. _Resize(FALSE);
  2307. if (fRefresh || fRecalc)
  2308. {
  2309. // '|| fRecalc' so we catch add/grow of text.
  2310. // testcase: remove title from band; add back; make sure the text
  2311. // shows up (used to just leave old band contents there)
  2312. SetRect(&rc, prbb->x, prbb->y, prbb->x + prbb->cx, prbb->y + prbb->cy);
  2313. _InvalidateRect(&rc);
  2314. }
  2315. }
  2316. return(TRUE);
  2317. }
  2318. // ----------------------------------------------------------------------------
  2319. //
  2320. // _ReallocBands
  2321. //
  2322. // reallocates the array of bands pointed to by _rbbList to the given
  2323. // number of bands
  2324. //
  2325. // ----------------------------------------------------------------------------
  2326. BOOL CReBar::_ReallocBands(UINT cBands)
  2327. {
  2328. PRBB rbbList;
  2329. if (!(rbbList = (PRBB) CCLocalReAlloc(_rbbList, sizeof(RBB) * cBands)) && cBands)
  2330. return(FALSE);
  2331. _rbbList = rbbList;
  2332. return(TRUE);
  2333. }
  2334. //
  2335. // NOTES
  2336. // for now caller does this in two calls (query, set). eventually we
  2337. // should be able to have it do everything up front.
  2338. BOOL CReBar::_RecalcFirst(int nCmd, PRBB prbbDelHide)
  2339. {
  2340. switch (nCmd) {
  2341. case RBC_QUERY:
  2342. {
  2343. BOOL fRecalcFirst;
  2344. // if we're nuking the 1st visible guy,
  2345. // and there are visible guys after us,
  2346. // then we need to recompute stuff
  2347. //
  2348. // for a testcase, start w/:
  2349. // row1: 'standard buttons' + 'brand'
  2350. // row2: 'address' + 'links'
  2351. // now hide 'standard buttons', you should end up w/:
  2352. // row1: 'address' + 'links' + 'brand'
  2353. // if there's a bug, you'll end up w/ (since the break isn't recomputed):
  2354. // row1: 'brand'
  2355. // row2: 'address' + 'links'
  2356. // fRecalcFirst = (!uBand && _cBands);
  2357. // if brbbDelHide is the first non-hidden band, and there are other non-hidden bands after it, fRecalcFirst = TRUE;
  2358. fRecalcFirst = (_EnumBand(0, RBBS_HIDDEN) == prbbDelHide) &&
  2359. _GetNextVisible(prbbDelHide);
  2360. return fRecalcFirst;
  2361. }
  2362. case RBC_SET: // set
  2363. {
  2364. PRBB prbb1 = _EnumBand(0, RBBS_HIDDEN);
  2365. if (_IsValidBand(prbb1) && (prbb1->fStyle & RBBS_FIXEDSIZE))
  2366. {
  2367. PRBB prbb2 = _EnumBand(1, RBBS_HIDDEN);
  2368. if (_IsValidBand(prbb2))
  2369. {
  2370. // get rid of line break on NEW first item
  2371. prbb2->fStyle &= ~RBBS_BREAK;
  2372. }
  2373. if (_ci.style & RBS_FIXEDORDER)
  2374. {
  2375. // this is because the min width is now based on it's movability --
  2376. // and since we are deleting (or hiding) the first item,
  2377. // the new first item becomes immovable
  2378. _BandCalcMinWidth(prbb1);
  2379. }
  2380. }
  2381. return TRUE;
  2382. }
  2383. default:
  2384. ASSERT(0);
  2385. }
  2386. return FALSE;
  2387. }
  2388. // ----------------------------------------------------------------------------
  2389. //
  2390. // _ShowBand
  2391. //
  2392. // updates show/hide state for the indicated band in the rebar's band array
  2393. // (rbbList).
  2394. //
  2395. // ----------------------------------------------------------------------------
  2396. BOOL CReBar::_ShowBand(UINT uBand, BOOL fShow)
  2397. {
  2398. PRBB prbb;
  2399. BOOL fRecalcFirst;
  2400. if (!_IsValidIndex(uBand))
  2401. return(FALSE);
  2402. prbb = _GetBand(uBand);
  2403. // if we're nuking the 1st visible guy,
  2404. // then we need to recompute stuff
  2405. fRecalcFirst = _RecalcFirst(RBC_QUERY, prbb);
  2406. if (fShow)
  2407. {
  2408. prbb->fStyle &= ~RBBS_HIDDEN;
  2409. if (!_BandCalcTextExtent(prbb, NULL))
  2410. _BandCalcMinWidth(prbb);
  2411. if (prbb->hwndChild)
  2412. ShowWindow(prbb->hwndChild, SW_SHOW);
  2413. }
  2414. else
  2415. {
  2416. prbb->fStyle |= RBBS_HIDDEN;
  2417. if (prbb->hwndChild)
  2418. ShowWindow(prbb->hwndChild, SW_HIDE);
  2419. }
  2420. if (fRecalcFirst)
  2421. _RecalcFirst(RBC_SET, NULL);
  2422. _InvalidateRect(NULL);
  2423. // Since _Resize is followed by _AutoSize,
  2424. // redraw must be TRUE for _Resize to do anything.
  2425. BOOL fRedrawOld = _SetRedraw(TRUE);
  2426. _Resize(FALSE);
  2427. _AutoSize();
  2428. _SetRedraw(fRedrawOld);
  2429. return(TRUE);
  2430. }
  2431. // ----------------------------------------------------------------------------
  2432. //
  2433. // _DeleteBand
  2434. //
  2435. // deletes the indicated band from the rebar's band array (rbbList) and
  2436. // decrements the rebar's band count (cBands)
  2437. //
  2438. // ----------------------------------------------------------------------------
  2439. BOOL CReBar::_DeleteBand(UINT uBand)
  2440. {
  2441. PRBB prbb;
  2442. PRBB prbbStop;
  2443. BOOL fRecalcFirst;
  2444. NMREBAR nm = {0};
  2445. // we need to clean up
  2446. //
  2447. // a) captured band and
  2448. // b) hottracked band
  2449. //
  2450. // before we delete this band
  2451. if (_uCapture != -1)
  2452. {
  2453. _SendNotify(_uCapture, RBN_ENDDRAG);
  2454. _OnBeginDrag((UINT)-1);
  2455. }
  2456. if (!_IsValidIndex(uBand))
  2457. return FALSE;
  2458. prbb = _GetBand(uBand);
  2459. // Notify the client of the delete
  2460. _SendNotify(uBand, RBN_DELETINGBAND);
  2461. nm.dwMask = RBNM_ID;
  2462. nm.wID = _GetBand(uBand)->wID; // Save this
  2463. Str_Set(&prbb->lpText, NULL);
  2464. // don't destroy the hbmBack 'cause it's given to us by app
  2465. // if we're nuking the 1st visible guy,
  2466. // then we need to recompute stuff
  2467. // if this is the first visible guy and there are other visible bands after it, fRecalcFirst = TRUE
  2468. fRecalcFirst = _RecalcFirst(RBC_QUERY, prbb);
  2469. if (IsWindow(prbb->hwndChild))
  2470. ShowWindow(prbb->hwndChild, SW_HIDE);
  2471. // prbbStop gets the address of the last band
  2472. prbbStop = _GetLastBand();
  2473. for ( ; prbb < prbbStop; prbb++)
  2474. *prbb = *(prbb + 1);
  2475. _cBands--;
  2476. if (_uResizeNext >= uBand && _uResizeNext > 0)
  2477. {
  2478. // (defer RBBS_HIDDEN stuff to use of uResizeNext)
  2479. _uResizeNext--;
  2480. }
  2481. // Notify the client of the delete
  2482. CCSendNotify(&_ci, RBN_DELETEDBAND, &nm.hdr);
  2483. if (fRecalcFirst)
  2484. _RecalcFirst(RBC_SET, NULL);
  2485. _ReallocBands(_cBands);
  2486. _InvalidateRect(NULL);
  2487. _Resize(FALSE);
  2488. _AutoSize();
  2489. return(TRUE);
  2490. }
  2491. // ----------------------------------------------------------------------------
  2492. //
  2493. // _InsertBand
  2494. //
  2495. // inserts a new band at the given position in the rebar's band array (rbbList),
  2496. // increments the rebar's band count (cBands), and sets the band's structure
  2497. // based on the given REBARBANDINFO structure.
  2498. //
  2499. // ----------------------------------------------------------------------------
  2500. BOOL CReBar::_InsertBand(UINT uBand, LPREBARBANDINFO lprbbi)
  2501. {
  2502. PRBB prbb;
  2503. REBARBANDINFO rbbi = {0};
  2504. if (!_ValidateBandInfo(&lprbbi, &rbbi))
  2505. return(FALSE);
  2506. if (uBand == -1)
  2507. uBand = _cBands;
  2508. else if (uBand > _cBands)
  2509. return(FALSE);
  2510. if (!_ReallocBands(_cBands + 1))
  2511. return(FALSE);
  2512. ++_cBands;
  2513. MoveMemory(_GetBand(uBand + 1), _GetBand(uBand), (_cBands-1-uBand) * sizeof(_rbbList[0]));
  2514. prbb = _GetBand(uBand);
  2515. // movememory does not zero init for us...
  2516. ZeroMemory(prbb, SIZEOF(RBB));
  2517. // Init text color
  2518. if (_clrText == CLR_NONE)
  2519. {
  2520. // Default to system text color
  2521. prbb->clrFore = CLR_DEFAULT;
  2522. }
  2523. else
  2524. {
  2525. // Default to rebar's custom text color
  2526. prbb->clrFore = CLR_NONE;
  2527. }
  2528. // Init background color
  2529. if (_clrBk == CLR_NONE)
  2530. {
  2531. // Default to system background color
  2532. prbb->clrBack = CLR_DEFAULT;
  2533. }
  2534. else
  2535. {
  2536. // Default to rebar's custom background color
  2537. prbb->clrBack = CLR_NONE;
  2538. }
  2539. prbb->iImage = -1;
  2540. prbb->cyMaxChild = MAXINT;
  2541. prbb->wChevState = DCHF_INACTIVE;
  2542. ASSERT(prbb->fStyle == 0);
  2543. ASSERT(prbb->lpText == NULL);
  2544. ASSERT(prbb->cxText == 0);
  2545. ASSERT(prbb->hwndChild == NULL);
  2546. ASSERT(prbb->cxMinChild == 0);
  2547. ASSERT(prbb->cyMinChild == 0);
  2548. ASSERT(prbb->hbmBack == 0);
  2549. ASSERT(prbb->x == 0);
  2550. ASSERT(prbb->y == 0);
  2551. ASSERT(prbb->cx == 0);
  2552. ASSERT(prbb->cy == 0);
  2553. if (!_SetBandInfo(uBand, lprbbi, FALSE))
  2554. {
  2555. _DeleteBand(uBand);
  2556. return(FALSE);
  2557. }
  2558. if (!(prbb->fStyle & RBBS_HIDDEN))
  2559. {
  2560. PRBB prbbFirst = _EnumBand(0, RBBS_HIDDEN);
  2561. if (!prbb->cxMin)
  2562. _BandCalcMinWidth(prbb);
  2563. if (prbbFirst != prbb)
  2564. {
  2565. int cxMin = prbbFirst->cxMin;
  2566. _BandCalcMinWidth(prbbFirst);
  2567. }
  2568. _Resize(FALSE);
  2569. }
  2570. _SizeBandToRowHeight(uBand, -1);
  2571. if (_CountBands(RBBS_HIDDEN) == 1)
  2572. {
  2573. // typcially, when you insert a band, we put it in a row with another band.
  2574. // thus the total bounding rect doesn't change. however, on the addition of the first band,
  2575. // the bound rect does change, so we need to autosize as necessary.
  2576. _AutoSize();
  2577. }
  2578. return(TRUE);
  2579. }
  2580. BOOL InitReBarClass(HINSTANCE hInstance)
  2581. {
  2582. WNDCLASS wc;
  2583. wc.lpfnWndProc = CReBar::s_WndProc;
  2584. wc.lpszClassName= c_szReBarClass;
  2585. wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
  2586. wc.cbClsExtra = 0;
  2587. wc.cbWndExtra = sizeof(CReBar*);
  2588. wc.hInstance = hInstance; // use DLL instance if in DLL
  2589. wc.hIcon = NULL;
  2590. wc.hCursor = NULL;
  2591. wc.hbrBackground= (HBRUSH)(COLOR_BTNFACE + 1);
  2592. wc.lpszMenuName = NULL;
  2593. if (!RegisterClass(&wc) && !GetClassInfo(hInstance, c_szReBarClass, &wc))
  2594. return FALSE;
  2595. return(TRUE);
  2596. }
  2597. // get the first band in the same row as rbbRow
  2598. // n.b. we may return an RBBS_HIDDEN band!
  2599. PRBB CReBar::_GetFirstInRow(PRBB prbbRow)
  2600. {
  2601. // n.b. we don't pay attention to hidden here, that's up to caller.
  2602. // in fact we *can't*, since there might be no non-hidden guys left
  2603. // (e.g. when _OnDestroy is deleting all the bands), in which case
  2604. // we'd loop forever.
  2605. while (prbbRow > _GetBand(0) && !_IsBandStartOfRow(prbbRow))
  2606. {
  2607. _ValidateRangePtr(prbbRow);
  2608. prbbRow--;
  2609. }
  2610. return prbbRow;
  2611. }
  2612. // get the last band in the same row as rbbRow.
  2613. // fStopAtFixed says whether to continue over fixed bands or
  2614. // stop at them
  2615. // n.b. we may return an RBBS_HIDDEN band!
  2616. PRBB CReBar::_GetLastInRow(PRBB prbbRow, BOOL fStopAtFixed)
  2617. {
  2618. do
  2619. {
  2620. prbbRow++;
  2621. }
  2622. while (prbbRow <= _GetLastBand() && !_IsBandStartOfRow(prbbRow) &&
  2623. (!fStopAtFixed || (prbbRow->fStyle & (RBBS_FIXEDSIZE|RBBS_HIDDEN)) == RBBS_FIXEDSIZE));
  2624. // loop steps to the start of the NEXT line
  2625. prbbRow--;
  2626. return prbbRow;
  2627. }
  2628. //*** _GetPrev, _GetNext -- get prev (next) band, skipping guys
  2629. // of style uStyleSkip (e.g. RBBS_HIDDEN)
  2630. PRBB CReBar::_GetPrev(PRBB prbb, UINT uStyleSkip)
  2631. {
  2632. while (--prbb >= _GetBand(0))
  2633. {
  2634. if (prbb->fStyle & uStyleSkip)
  2635. continue;
  2636. return prbb;
  2637. }
  2638. return NULL;
  2639. }
  2640. PRBB CReBar::_GetNext(PRBB prbb, UINT uStyleSkip)
  2641. {
  2642. while (++prbb <= _GetLastBand())
  2643. {
  2644. if (prbb->fStyle & uStyleSkip)
  2645. continue;
  2646. return prbb;
  2647. }
  2648. return NULL;
  2649. }
  2650. //*** _CountBands -- get count of bands, skipping guys
  2651. // of style uStyleSkip (e.g. RBBS_HIDDEN)
  2652. int CReBar::_CountBands(UINT uStyleSkip)
  2653. {
  2654. int i;
  2655. PRBB prbb;
  2656. if (_cBands == 0)
  2657. return 0;
  2658. i = 0;
  2659. for (prbb = _GetBand(0); prbb <= _GetLastBand(); prbb++)
  2660. {
  2661. if (prbb->fStyle & uStyleSkip)
  2662. continue;
  2663. i++;
  2664. }
  2665. return i;
  2666. }
  2667. //*** _EnumBand -- get Nth band, skipping guys
  2668. // of style uStyleSkip (e.g. RBBS_HIDDEN)
  2669. // 'skipping' means don't include in count
  2670. PRBB CReBar::_EnumBand(int i, UINT uStyleSkip)
  2671. {
  2672. PRBB prbb;
  2673. for (prbb = _GetBand(0); prbb <= _GetLastBand(); prbb++)
  2674. {
  2675. if (prbb->fStyle & uStyleSkip)
  2676. continue;
  2677. if (i-- == 0)
  2678. break;
  2679. }
  2680. // if we found it, this is the band;
  2681. // if we ran out of bands, this is 1 past the end
  2682. return prbb;
  2683. }
  2684. // returns the minimum x position prbb can be
  2685. int CReBar::_MinX(PRBB prbb)
  2686. {
  2687. int xLimit = 0;
  2688. ASSERT(!(prbb->fStyle & RBBS_HIDDEN)); // o.w. might loop forever
  2689. while (!_IsBandStartOfRow(prbb))
  2690. {
  2691. prbb--;
  2692. if (!(prbb->fStyle & RBBS_HIDDEN))
  2693. xLimit += _FudgeWidth(prbb->cxMin);
  2694. }
  2695. return xLimit + _mBand.cxLeftWidth;
  2696. }
  2697. int CReBar::_MaxX(PRBB prbb)
  2698. {
  2699. int xLimit = 0;
  2700. if (prbb)
  2701. {
  2702. PRBB prbbLast = _rbbList + _cBands;
  2703. PRBB prbbWalk;
  2704. for (prbbWalk = prbb; prbbWalk < prbbLast; prbbWalk++)
  2705. {
  2706. if (prbbWalk->fStyle & RBBS_HIDDEN)
  2707. continue;
  2708. if (_IsBandStartOfRow(prbbWalk))
  2709. break;
  2710. if (prbbWalk != prbb)
  2711. xLimit += _FudgeWidth(prbbWalk->cxMin);
  2712. else
  2713. xLimit += prbbWalk->cxMin;
  2714. }
  2715. prbbWalk = _GetPrevVisible(prbbWalk); // prbbWalk--;
  2716. if (prbbWalk)
  2717. xLimit = prbbWalk->x + prbbWalk->cx - xLimit;
  2718. }
  2719. return xLimit;
  2720. }
  2721. BOOL CReBar::_MinimizeBand(UINT uBand, BOOL fAnim)
  2722. {
  2723. PRBB prbb;
  2724. if (!_IsValidIndex(uBand))
  2725. return FALSE;
  2726. prbb = _GetBand(uBand);
  2727. if (prbb->fStyle & RBBS_FIXEDSIZE)
  2728. return FALSE;
  2729. ASSERT(!(prbb->fStyle & RBBS_HIDDEN));
  2730. if (_IsBandStartOfRow(prbb))
  2731. {
  2732. // if it's the start of a row, the way to minimize it is to maximize the next guy
  2733. // if it's on the same row
  2734. prbb = _GetNextVisible(prbb);
  2735. if (!prbb || _IsBandStartOfRow(prbb))
  2736. return FALSE;
  2737. return _MaximizeBand(_BandToIndex(prbb), FALSE, fAnim);
  2738. }
  2739. if (fAnim)
  2740. return _SetBandPosAnim(prbb, prbb->x + (prbb->cx - prbb->cxMin));
  2741. else
  2742. return _SetBandPos(prbb, prbb->x + (prbb->cx - prbb->cxMin));
  2743. }
  2744. // fIdeal - FALSE == full maximization...
  2745. // TRUE == go to cxIdeal
  2746. // fAnim - TRUE means we were called due to UI action (via _ToggleBand), so animate
  2747. BOOL CReBar::_MaximizeBand(UINT uBand, BOOL fIdeal, BOOL fAnim)
  2748. {
  2749. int x, dx;
  2750. BOOL fChanged = FALSE;
  2751. PRBB prbbMaximize;
  2752. if (!_IsValidIndex(uBand))
  2753. return FALSE;
  2754. prbbMaximize = _GetBand(uBand);
  2755. if (prbbMaximize->fStyle & RBBS_FIXEDSIZE)
  2756. return FALSE;
  2757. dx = prbbMaximize->cxIdeal + _GetHeaderWidth(prbbMaximize) - prbbMaximize->cx;
  2758. if (fIdeal && dx > 0)
  2759. {
  2760. PRBB prbb;
  2761. // first move the next guy over if possible.
  2762. prbb = _GetNextVisible(prbbMaximize);
  2763. if (prbb && (!_IsBandStartOfRow(prbb)))
  2764. {
  2765. int dxRbb;
  2766. x = _MaxX(prbb);
  2767. // dxRbb is the maximum that prbb can move
  2768. dxRbb = x - prbb->x;
  2769. if (dxRbb > dx)
  2770. {
  2771. // if that's more than enough space, then limit dx
  2772. dxRbb = dx;
  2773. }
  2774. x = prbb->x + dxRbb;
  2775. fChanged |= (fAnim)?_SetBandPosAnim(prbb, x):_SetBandPos(prbb,x);
  2776. dx -= dxRbb;
  2777. }
  2778. if (dx)
  2779. {
  2780. int dxRbb;
  2781. // the one on the right didn't move enough.
  2782. // now move us back
  2783. x = _MinX(prbbMaximize);
  2784. dxRbb = prbbMaximize->x - x;
  2785. if (dxRbb > dx)
  2786. {
  2787. x = prbbMaximize->x - dx;
  2788. }
  2789. fChanged |= (fAnim)?_SetBandPosAnim(prbbMaximize, x):_SetBandPos(prbbMaximize, x);
  2790. }
  2791. }
  2792. else
  2793. {
  2794. x = _MinX(prbbMaximize);
  2795. fChanged |= (fAnim)?_SetBandPosAnim(prbbMaximize, x):_SetBandPos(prbbMaximize, x);
  2796. prbbMaximize = _GetNextVisible(prbbMaximize);
  2797. if (prbbMaximize && !_IsBandStartOfRow(prbbMaximize))
  2798. {
  2799. x = _MaxX(prbbMaximize);
  2800. fChanged |= (fAnim)?_SetBandPosAnim(prbbMaximize, x):_SetBandPos(prbbMaximize, x);
  2801. }
  2802. }
  2803. return fChanged;
  2804. }
  2805. // ----------------------------------------------------------------------------
  2806. //
  2807. // _ToggleBand
  2808. //
  2809. // switches a band between it's maximized and minimized state, based on where
  2810. // the user clicked
  2811. //
  2812. // ----------------------------------------------------------------------------
  2813. void CReBar::_ToggleBand(BOOL fAnim)
  2814. {
  2815. BOOL fDidSomething = FALSE;
  2816. // try to maximize this band. if failed (meaning already maximize)
  2817. // then minimize
  2818. if (CCSendNotify(&_ci, RBN_MINMAX, NULL))
  2819. return;
  2820. fDidSomething = _MaximizeBand(_uCapture, TRUE,fAnim);
  2821. if (!fDidSomething)
  2822. fDidSomething = _MinimizeBand(_uCapture,fAnim);
  2823. if (fDidSomething)
  2824. CCPlaySound(TEXT("ShowBand"));
  2825. }
  2826. // ----------------------------------------------------------------------------
  2827. //
  2828. // _SetCursor
  2829. //
  2830. // sets the cursor to either the move cursor or the arrow cursor, depending
  2831. // on whether or not the cursor is on a band's caption
  2832. //
  2833. // ----------------------------------------------------------------------------
  2834. void CReBar::_SetCursor(int x, int y, BOOL fMouseDown)
  2835. {
  2836. int iBand;
  2837. RBHITTESTINFO rbht;
  2838. rbht.pt.x = x;
  2839. rbht.pt.y = y;
  2840. iBand = _HitTest(&rbht);
  2841. if (rbht.flags == RBHT_GRABBER)
  2842. {
  2843. if (fMouseDown)
  2844. SetCursor(LoadCursor(HINST_THISDLL, (_ci.style & CCS_VERT) ? MAKEINTRESOURCE(IDC_DIVOPENV) : MAKEINTRESOURCE(IDC_DIVOPEN) ));
  2845. else
  2846. SetCursor(LoadCursor(NULL, (_ci.style & CCS_VERT) ? IDC_SIZENS : IDC_SIZEWE));
  2847. return;
  2848. }
  2849. if ((fMouseDown) && ((rbht.flags == RBHT_GRABBER) || (rbht.flags == RBHT_CAPTION) && _ShouldDrawGripper(_GetBand(iBand))))
  2850. {
  2851. // No longer IE3 compatible, per RichSt
  2852. SetCursor(LoadCursor(NULL, IDC_SIZEALL));
  2853. return;
  2854. }
  2855. SetCursor(LoadCursor(NULL, IDC_ARROW));
  2856. }
  2857. // adjust's a band's (prbb) starting location to the given location
  2858. BOOL CReBar::_SetBandPos(PRBB prbb, int xLeft)
  2859. {
  2860. RECT rc;
  2861. PRBB prbbPrev;
  2862. int xRight;
  2863. BOOL fBandBorders = _UseBandBorders();
  2864. BOOL fRight;
  2865. if (!prbb)
  2866. return (FALSE);
  2867. ASSERT(!(prbb->fStyle & RBBS_HIDDEN));
  2868. ASSERT((xLeft >= 0)); // We've got problems if someone is trying to set us negative
  2869. if (prbb->x == xLeft)
  2870. return(FALSE);
  2871. prbbPrev = _GetPrevVisible(prbb);
  2872. // band has moved within valid range -- adjust band sizes and redraw
  2873. // window
  2874. fRight = (prbb->x < xLeft);
  2875. SetRect(&rc, prbb->x - _mBand.cxLeftWidth, prbb->y- _mBand.cyTopHeight, prbb->x + prbb->cxMin + _mBand.cxRightWidth, prbb->y + prbb->cy + _mBand.cyBottomHeight);
  2876. xRight = prbb->x + prbb->cx;
  2877. prbb->x = xLeft;
  2878. prbb->cx = xRight - xLeft;
  2879. prbb->cxRequest = prbb->cx;
  2880. if (fRight)
  2881. {
  2882. if (prbbPrev)
  2883. {
  2884. //moving right
  2885. prbbPrev->cx = prbb->x - _mBand.cxRightWidth - prbbPrev->x - _mBand.cxLeftWidth;
  2886. if (fBandBorders)
  2887. {
  2888. prbbPrev->cx -= g_cxEdge;
  2889. rc.left -= g_cxEdge;
  2890. }
  2891. rc.left = rc.left - _mBand.cxRightWidth;
  2892. prbbPrev->cxRequest = prbbPrev->cx;
  2893. //check for compacting of following bands
  2894. while (prbb && prbb->cx < prbb->cxMin)
  2895. {
  2896. prbb->cx = prbb->cxMin;
  2897. prbb->cxRequest = prbb->cx;
  2898. xLeft += _BandWidth(prbb);
  2899. prbb = _GetNextVisible(prbb); // prbb++;
  2900. if (prbb)
  2901. {
  2902. xRight = prbb->x + prbb->cx;
  2903. prbb->x = xLeft;
  2904. prbb->cx = xRight - xLeft;
  2905. prbb->cxRequest = prbb->cx;
  2906. }
  2907. }
  2908. if (prbb)
  2909. rc.right = xLeft + prbb->cxMin + _mBand.cxRightWidth;
  2910. }
  2911. }
  2912. else
  2913. {
  2914. //moving left
  2915. //check for compacting of preceding bands
  2916. while (prbbPrev)
  2917. {
  2918. if (fBandBorders)
  2919. xLeft -= g_cxEdge;
  2920. prbbPrev->cx = xLeft - prbbPrev->x - _mBand.cxLeftWidth - _mBand.cxRightWidth;
  2921. prbbPrev->cxRequest = prbbPrev->cx;
  2922. if (prbbPrev->cx < prbbPrev->cxMin)
  2923. {
  2924. prbbPrev->x = xLeft - _mBand.cxLeftWidth - _mBand.cxRightWidth - prbbPrev->cxMin;
  2925. prbbPrev->cx = prbbPrev->cxMin;
  2926. prbbPrev->cxRequest = prbbPrev->cx;
  2927. xLeft = prbbPrev->x;
  2928. prbbPrev = _GetPrevVisible(prbbPrev); // prbbPrev--
  2929. }
  2930. else
  2931. {
  2932. break;
  2933. }
  2934. }
  2935. rc.left = xLeft - _mBand.cxLeftWidth - _mBand.cxRightWidth;
  2936. }
  2937. if (fBandBorders)
  2938. rc.bottom += g_cyEdge / 2;
  2939. _ResizeChildren();
  2940. if (_InvalidateRect(&rc))
  2941. {
  2942. UpdateWindow(_ci.hwnd);
  2943. }
  2944. return(TRUE);
  2945. }
  2946. BOOL CReBar::_SetBandPosAnim(PRBB prbb, int xLeft)
  2947. {
  2948. int ctr=0,dx, xCur = prbb->x;
  2949. DWORD dwStartTime;
  2950. if (xCur == xLeft)
  2951. return FALSE;
  2952. dwStartTime=GetTickCount();
  2953. dx = (xLeft - xCur)/ANIMSTEPS;
  2954. if (dx != 0)
  2955. {
  2956. if (xCur < xLeft)
  2957. {
  2958. // move right
  2959. for (; xCur < (xLeft-dx); ctr++,xCur += dx)
  2960. {
  2961. _SetBandPos(prbb, xCur);
  2962. // If something caused us to take more than 10 times the time we
  2963. // should be, break out, and let the final _SetBandPos finish
  2964. if (GetTickCount() - dwStartTime > 10*ANIMSTEPS*ANIMSTEPTIME)
  2965. break;
  2966. Sleep(ANIMSTEPTIME);
  2967. // Start slowing us down 80% of the way through
  2968. // Cut speed by 2/3 each time, but never move less than 4 pixels
  2969. if ((ctr >= 4*ANIMSTEPS/5) && (dx >= 4))
  2970. dx = 2*dx/3;
  2971. }
  2972. }
  2973. else
  2974. {
  2975. // move left
  2976. for (; xCur > (xLeft-dx); ctr++, xCur += dx)
  2977. {
  2978. _SetBandPos(prbb, xCur);
  2979. if (GetTickCount() > (dwStartTime + 10*ANIMSTEPS*ANIMSTEPTIME))
  2980. break;
  2981. Sleep(ANIMSTEPTIME);
  2982. if ((ctr >= 4*ANIMSTEPS/5) && (dx <= -4))
  2983. dx = 2*dx/3;
  2984. }
  2985. }
  2986. }
  2987. _SetBandPos(prbb, xLeft);
  2988. return TRUE;
  2989. }
  2990. void CReBar::_OnBeginDrag(UINT uBand)
  2991. {
  2992. _uCapture = uBand;
  2993. _ptLastDragPos.x = -1;
  2994. _ptLastDragPos.y = -1;
  2995. if (_uCapture == -1)
  2996. {
  2997. // aborting drag
  2998. _fParentDrag = FALSE;
  2999. _fFullOnDrag = FALSE;
  3000. // we could have unwrapped rows, in which case, we need to grow bands (but not wrap)
  3001. // to fill the empty space.
  3002. if (_ci.style & RBS_AUTOSIZE)
  3003. {
  3004. _SizeBandsToRect(NULL);
  3005. _SizeBandsToRowHeight();
  3006. }
  3007. }
  3008. else
  3009. {
  3010. _fParentDrag = TRUE;
  3011. _fFullOnDrag = TRUE;
  3012. }
  3013. }
  3014. int minmax(int x, int min, int max)
  3015. {
  3016. x = max(x, min);
  3017. x = min(x, max);
  3018. return x;
  3019. }
  3020. // pass the break bit along
  3021. void CReBar::_PassBreak(PRBB prbbSrc, PRBB prbbDest)
  3022. {
  3023. if (prbbSrc->fStyle & RBBS_BREAK)
  3024. {
  3025. prbbSrc->fStyle &= ~RBBS_BREAK;
  3026. if (prbbDest)
  3027. prbbDest->fStyle |= RBBS_BREAK;
  3028. }
  3029. }
  3030. void CReBar::_GetClientRect(LPRECT prc)
  3031. {
  3032. GetClientRect(_ci.hwnd, prc);
  3033. if (_ci.style & CCS_VERT)
  3034. FlipRect(prc);
  3035. }
  3036. //tells if prbb is the first band and the next band is fixed.
  3037. // if this is true then we need to do a recalc if we move prbb
  3038. BOOL CReBar::_RecalcIfMove(PRBB prbb)
  3039. {
  3040. if (_EnumBand(0, RBBS_HIDDEN) == prbb)
  3041. {
  3042. PRBB prbbNext = _GetNextVisible(prbb);
  3043. if (prbbNext && prbbNext->fStyle & RBBS_FIXEDSIZE)
  3044. return TRUE;
  3045. }
  3046. return FALSE;
  3047. }
  3048. // find out if the prbb at it's min height could fit within the current window
  3049. // if all the others shrunk as much as they could
  3050. BOOL CReBar::_RoomForBandVert(PRBB prbbSkip)
  3051. {
  3052. int yExtra = 0;
  3053. UINT cBands = _cBands;
  3054. int iNewRowHeight = prbbSkip->cyMinChild;
  3055. PRBB prbb = _GetBand(0);
  3056. if (_UseBandBorders())
  3057. iNewRowHeight += g_cyEdge;
  3058. iNewRowHeight += _mBand.cyBottomHeight + _mBand.cyTopHeight;
  3059. while (prbb)
  3060. {
  3061. if (_IsBandVisible(prbb))
  3062. {
  3063. if (_IsBandStartOfRow(prbb))
  3064. {
  3065. yExtra += _GetRowHeightExtra(&prbb, prbbSkip);
  3066. if (yExtra >= iNewRowHeight)
  3067. return TRUE;
  3068. continue;
  3069. }
  3070. }
  3071. prbb = _GetNextVisible(prbb);
  3072. }
  3073. return FALSE;
  3074. }
  3075. // we should make a new row if prbb isn't the start of the row already
  3076. // and we're off the end of the control
  3077. //
  3078. // poweruser hack of holding the control down will make a new row if you hit the border between lines
  3079. BOOL CReBar::_MakeNewRow(PRBB prbb, int y)
  3080. {
  3081. BOOL fRet = FALSE;
  3082. RECT rc;
  3083. // if we're off the top of the control, move this band to the end (or beginning)
  3084. _GetClientRect(&rc);
  3085. InflateRect(&rc, 0, -g_cyEdge);
  3086. if (!(_ci.style & RBS_FIXEDORDER))
  3087. {
  3088. int iOutsideLimit = g_cyEdge * 4; // how far do you have to move outside the bounds of the window to force a new row
  3089. if (_RoomForBandVert(prbb))
  3090. {
  3091. iOutsideLimit = -g_cyEdge;
  3092. }
  3093. if (y < rc.top - iOutsideLimit)
  3094. { // top of control
  3095. PRBB prbbNext = _EnumBand(0, RBBS_HIDDEN);
  3096. if (prbbNext == prbb)
  3097. prbbNext = _GetNextVisible(prbb);
  3098. fRet |= _MoveBand(_BandToIndex(prbb), 0);
  3099. ASSERT(prbbNext <= _GetLastBand());
  3100. if (prbbNext && !(prbbNext->fStyle & RBBS_BREAK))
  3101. {
  3102. prbbNext->fStyle |= RBBS_BREAK;
  3103. fRet = TRUE;
  3104. }
  3105. }
  3106. else if (y >= rc.bottom)
  3107. {
  3108. // move to the end
  3109. if (!(prbb->fStyle & RBBS_BREAK))
  3110. {
  3111. prbb->fStyle |= RBBS_BREAK;
  3112. fRet = TRUE;
  3113. }
  3114. prbb->cyChild = prbb->cyMinChild;
  3115. fRet |= _MoveBand(_BandToIndex(prbb), _cBands-1);
  3116. }
  3117. else
  3118. {
  3119. // create a new row in the middle
  3120. if (!_IsBandStartOfRow(prbb) && GetAsyncKeyState(VK_CONTROL) < 0)
  3121. {
  3122. // make sure they're on different rows and on the border
  3123. if (y > prbb->y + prbb->cy + _mBand.cyBottomHeight &&
  3124. y < prbb->y + prbb->cy + _mBand.cyBottomHeight + g_cyEdge)
  3125. {
  3126. PRBB prbbLast = _GetLastInRow(prbb, FALSE); // move it right before the first in this row
  3127. prbb->fStyle |= RBBS_BREAK;
  3128. _MoveBand(_BandToIndex(prbb), _BandToIndex(prbbLast));
  3129. fRet = TRUE;
  3130. }
  3131. }
  3132. }
  3133. }
  3134. else
  3135. {
  3136. // fixed guys can't move, they can only make a new row
  3137. if (!_IsBandStartOfRow(prbb))
  3138. {
  3139. if (y > prbb->y + prbb->cy + _mBand.cyBottomHeight)
  3140. {
  3141. prbb->fStyle |= RBBS_BREAK;
  3142. fRet = TRUE;
  3143. }
  3144. }
  3145. }
  3146. return fRet;
  3147. }
  3148. // ----------------------------------------------------------------------------
  3149. //
  3150. // _DragBand
  3151. //
  3152. // resizes the currently tracked band based on the user's mouse movement as
  3153. // indicated in the given point (x, y)
  3154. //
  3155. // ----------------------------------------------------------------------------
  3156. void CReBar::_DragBand(int x, int y)
  3157. {
  3158. PRBB prbb = _GetBand(_uCapture);
  3159. UINT iHit = -1;
  3160. // Do nothing if the mouse didn't actually move
  3161. // otherwise, multiple WM_MOUSEMOVE messages will be generated by resizing windows
  3162. if (x==_ptLastDragPos.x && y==_ptLastDragPos.y)
  3163. return;
  3164. else
  3165. {
  3166. _ptLastDragPos.x = x;
  3167. _ptLastDragPos.y = y;
  3168. }
  3169. if (_ci.style & CCS_VERT)
  3170. SWAP(x,y, int);
  3171. if (!_fFullOnDrag)
  3172. {
  3173. // don't begin dragging until mouse is moved outside of an edge-thick
  3174. // tolerance border
  3175. if ((y < (_ptCapture.y - g_cyEdge)) || (y > (_ptCapture.y + g_cyEdge)) ||
  3176. (x < (_ptCapture.x - g_cxEdge)) || (x > (_ptCapture.x + g_cxEdge)))
  3177. {
  3178. // did parent abort?
  3179. if (_SendNotify(_uCapture, RBN_BEGINDRAG))
  3180. return;
  3181. if (!_IsValidBand(prbb))
  3182. {
  3183. // somebody responded to RBN_BEGINDRAG by nuking bands; bail
  3184. return;
  3185. }
  3186. _fFullOnDrag = TRUE;
  3187. }
  3188. else
  3189. return;
  3190. }
  3191. // bail for right now on fRecalcIfMoved (ie3 did the same thing). nice feature for later
  3192. if (!_CanBandMove(prbb))
  3193. return;
  3194. /* what type of drag operation depends on what we drag hit on.
  3195. if we hit on the band before us, or ourself
  3196. and it's the same row
  3197. and we're not the first band of the row
  3198. then we just to a size move
  3199. otherwise if we hit on a band then we do a move
  3200. if we hit outside of any band, we grow to meet the cursor
  3201. in all of the above, a band that's hit must be NOT fixed and not hidden
  3202. */
  3203. BOOL fResize = FALSE;
  3204. RECT rc;
  3205. _GetClientRect(&rc);
  3206. if (y < rc.bottom - 1)
  3207. {
  3208. iHit = _InternalHitTest(NULL, x, y);
  3209. }
  3210. if (iHit != -1)
  3211. {
  3212. PRBB prbbPrev = _GetPrevVisible(prbb);
  3213. PRBB prbbHit = _GetBand(iHit);
  3214. prbbHit = _GetPrev(++prbbHit, RBBS_FIXEDSIZE); // skip over fixed guys
  3215. if (prbbHit)
  3216. {
  3217. ASSERT(prbbHit >= _rbbList);
  3218. // this should never happen.
  3219. if (prbbHit < _rbbList)
  3220. return;
  3221. iHit = _BandToIndex(prbbHit);
  3222. // if we're on the same row ... and it's us or the previous one
  3223. if (prbbHit->y == prbb->y && (prbbHit == prbb || prbbHit == prbbPrev))
  3224. {
  3225. if (x < _GetGripperWidth() + _mBand.cxLeftWidth &&
  3226. !(_ci.style & RBS_FIXEDORDER))
  3227. {
  3228. // special case dragging to the far left. there's no other way to move to first in row
  3229. _PassBreak(prbbHit, prbb);
  3230. if (_MoveBand(_uCapture, iHit))
  3231. fResize = TRUE;
  3232. }
  3233. else if (!_IsBandStartOfRow(prbb))
  3234. {
  3235. // and we're not the first band of the row
  3236. // then just size it
  3237. int xLeft = _xStart + (x - _ptCapture.x);
  3238. xLeft = minmax(xLeft, _MinX(prbb), _MaxX(prbb));
  3239. _DragSize(xLeft);
  3240. }
  3241. }
  3242. else if (_MakeNewRow(prbb, y))
  3243. {
  3244. fResize = TRUE;
  3245. }
  3246. else
  3247. { // otherwise do a move if we're not in a fixed order
  3248. if (!(_ci.style & RBS_FIXEDORDER))
  3249. {
  3250. if (iHit < _BandToIndex(prbb))
  3251. iHit++; // +1 because if you hit a band, you're moving to the right of him
  3252. // if one with a break is moving, the next one inherits the break
  3253. _PassBreak(prbb, _GetNextVisible(prbb));
  3254. _MoveBand(_uCapture, iHit);
  3255. }
  3256. else
  3257. {
  3258. if (iHit < _BandToIndex(prbb))
  3259. _PassBreak(prbb, _GetNextVisible(prbb));
  3260. }
  3261. fResize = TRUE;
  3262. }
  3263. }
  3264. }
  3265. else if (_MakeNewRow(prbb, y))
  3266. {
  3267. fResize = TRUE;
  3268. }
  3269. if (fResize)
  3270. {
  3271. _Resize(FALSE);
  3272. _AutoSize();
  3273. }
  3274. }
  3275. HPALETTE CReBar::_SetPalette(HPALETTE hpal)
  3276. {
  3277. HPALETTE hpalOld = _hpal;
  3278. if (hpal != hpalOld)
  3279. {
  3280. if (!_fUserPalette)
  3281. {
  3282. if (_hpal)
  3283. {
  3284. DeleteObject(_hpal);
  3285. _hpal = NULL;
  3286. }
  3287. }
  3288. if (hpal)
  3289. {
  3290. _fUserPalette = TRUE;
  3291. _hpal = hpal;
  3292. }
  3293. _InvalidateRect(NULL);
  3294. }
  3295. return hpalOld;
  3296. }
  3297. // ----------------------------------------------------------------------------
  3298. //
  3299. // _OnDestroy
  3300. //
  3301. // frees all memory allocated by rebar
  3302. //
  3303. // ----------------------------------------------------------------------------
  3304. BOOL CReBar::_OnDestroy()
  3305. {
  3306. UINT c = _cBands;
  3307. _SetRedraw(FALSE);
  3308. _SetRecalc(FALSE);
  3309. while (c--)
  3310. _DeleteBand(c);
  3311. // so that we don't keep trying to autosize
  3312. _ci.style &= ~RBS_AUTOSIZE;
  3313. ASSERT(!_rbbList);
  3314. _SetPalette(NULL);
  3315. if (_hFont && _fFontCreated)
  3316. {
  3317. DeleteObject(_hFont);
  3318. }
  3319. if ((_ci.style & RBS_TOOLTIPS) && IsWindow(_hwndToolTips))
  3320. {
  3321. DestroyWindow (_hwndToolTips);
  3322. _hwndToolTips = NULL;
  3323. }
  3324. // don't destroy the himl 'cause it's given to us by app
  3325. if (_hDragProxy)
  3326. DestroyDragProxy(_hDragProxy);
  3327. if (_hTheme)
  3328. CloseThemeData(_hTheme);
  3329. return TRUE;
  3330. }
  3331. // ----------------------------------------------------------------------------
  3332. //
  3333. // _InitPaletteHack
  3334. //
  3335. // this is a hack to use the halftone palette until we have a way of asking
  3336. // the client what palette they are using
  3337. //
  3338. // ----------------------------------------------------------------------------
  3339. void CReBar::_InitPaletteHack()
  3340. {
  3341. if (!_fUserPalette)
  3342. {
  3343. HDC hdc = CreateCompatibleDC(NULL);
  3344. if (hdc)
  3345. {
  3346. if (GetDeviceCaps(hdc, BITSPIXEL) <= 8)
  3347. {
  3348. if (_hpal)
  3349. DeleteObject(_hpal);
  3350. _hpal = CreateHalftonePalette(hdc); // this is a hack
  3351. }
  3352. DeleteDC(hdc);
  3353. }
  3354. }
  3355. }
  3356. UINT CReBar::_IDToIndex(UINT id)
  3357. {
  3358. UINT i;
  3359. REBARBANDINFO rbbi;
  3360. rbbi.cbSize = sizeof(REBARBANDINFO);
  3361. rbbi.fMask = RBBIM_ID;
  3362. for (i = 0; i < _cBands; i++)
  3363. {
  3364. if (_GetBandInfo(i, &rbbi))
  3365. {
  3366. if (rbbi.wID == (WORD)id)
  3367. return i;
  3368. }
  3369. }
  3370. return -1;
  3371. }
  3372. int CReBar::_GetRowHeight(UINT uRow)
  3373. {
  3374. if (uRow < _cBands)
  3375. {
  3376. // move back to start of line
  3377. PRBB prbbFirst = _GetFirstInRow(_GetBand(uRow));
  3378. PRBB prbbLast = _GetLastInRow(_GetBand(uRow), FALSE);
  3379. return _GetLineHeight(_BandToIndex(prbbFirst), _BandToIndex(prbbLast));
  3380. }
  3381. return -1;
  3382. }
  3383. // fOneStep == whether to allow only one cyIntegral or as many as will fit to
  3384. // fill dy
  3385. int CReBar::_GrowBand(PRBB prbb, int dy, BOOL fResize, int iLineHeight)
  3386. {
  3387. int dyBand = 0; // how much the band changes
  3388. if (prbb->cyIntegral)
  3389. {
  3390. if (iLineHeight == -1)
  3391. {
  3392. iLineHeight = _GetRowHeight(_BandToIndex(prbb));
  3393. }
  3394. // get the proposed new size
  3395. int cyDesiredHeight = min(iLineHeight + dy, prbb->cyMaxChild) - prbb->cyMinChild;
  3396. // Limit new height to band's min and max
  3397. int iNumOfIntegrals = max(cyDesiredHeight / prbb->cyIntegral, 0);
  3398. int cyNewHeight = prbb->cyMinChild + (iNumOfIntegrals * prbb->cyIntegral);
  3399. DebugMsg(TF_REBAR, TEXT("REBAR._gb Band {%d}, Line Height {%d} Desired Height {%d} New Height {%d} Old Height {%d} dy {%d}"), _BandToIndex(prbb), iLineHeight, cyDesiredHeight + prbb->cyMinChild, cyNewHeight, prbb->cyChild, dy);
  3400. dyBand = cyNewHeight - prbb->cyChild;
  3401. prbb->cyChild = cyNewHeight;
  3402. if (fResize)
  3403. {
  3404. _Resize(TRUE);
  3405. }
  3406. }
  3407. return dyBand;
  3408. }
  3409. // returns the delta in size that the rebar is from prc.
  3410. // taking into account vertical mode
  3411. int CReBar::_SizeDifference(LPRECT prc)
  3412. {
  3413. int d;
  3414. d = (_IsVertical() ? RECTWIDTH(*prc) : RECTHEIGHT(*prc))
  3415. - _cy;
  3416. return d;
  3417. }
  3418. // returns how much this row could shrink
  3419. int CReBar::_GetRowHeightExtra(PRBB *pprbb, PRBB prbbSkip)
  3420. {
  3421. // this is the largest minimum child size for the row.
  3422. // even if something is not at it's min size, if it's smaller than this
  3423. // then it doesn't matter because someone else on that row can't be sized
  3424. int yLimit = 0;
  3425. int yExtra = 0;
  3426. PRBB prbb = *pprbb;
  3427. while (prbb)
  3428. {
  3429. if (prbb != prbbSkip)
  3430. {
  3431. int yMin;
  3432. int yExtraBand = 0;
  3433. // the min height is the cyChild if it's not variable height
  3434. yMin = prbb->cyChild;
  3435. if (prbb->fStyle & RBBS_VARIABLEHEIGHT)
  3436. {
  3437. // if it is variable height, and there's still room to shrink, then cyMinChild is
  3438. // the minimum.
  3439. if (prbb->cyChild >= prbb->cyMinChild + prbb->cyIntegral)
  3440. {
  3441. yMin = prbb->cyMinChild;
  3442. yExtraBand = prbb->cyChild - prbb->cyMinChild;
  3443. }
  3444. }
  3445. if (yMin == yLimit)
  3446. {
  3447. if (yExtraBand > yExtra)
  3448. yExtra = yExtraBand;
  3449. }
  3450. else if (yMin > yLimit)
  3451. {
  3452. yExtra = yExtraBand;
  3453. }
  3454. }
  3455. prbb = _GetNextVisible(prbb);
  3456. }
  3457. *pprbb = prbb;
  3458. return yExtra;
  3459. }
  3460. // are allt he bands at the minimum size?
  3461. BOOL CReBar::_BandsAtMinHeight()
  3462. {
  3463. BOOL fRet = TRUE;
  3464. PRBB prbb = _GetBand(0);
  3465. while (prbb)
  3466. {
  3467. if (_IsBandVisible(prbb))
  3468. {
  3469. if (_IsBandStartOfRow(prbb))
  3470. {
  3471. fRet = _IsRowAtMinHeight(&prbb);
  3472. if (!fRet)
  3473. break;
  3474. continue;
  3475. }
  3476. }
  3477. prbb = _GetNextVisible(prbb);
  3478. }
  3479. return fRet;
  3480. }
  3481. // this is like _SizeBarToRect except that it resizes the actual bands if they
  3482. // are VARIABLEHEIGHT
  3483. BOOL CReBar::_SizeBandsToRect(LPRECT prc)
  3484. {
  3485. int dy;
  3486. RECT rc;
  3487. BOOL fRedrawOld;
  3488. BOOL fChanged = FALSE;
  3489. // Turn recalc on to ensure calculations actually do something
  3490. // (else we can loop forever since _cy never actually changes).
  3491. _SetRecalc(TRUE);
  3492. if (prc)
  3493. {
  3494. rc = *prc;
  3495. }
  3496. else
  3497. {
  3498. GetClientRect(_ci.hwnd, &rc);
  3499. }
  3500. DebugMsg(TF_REBAR, TEXT("REBAR._sbandstr starting rect is {%d, %d, %d, %d}"), rc.left, rc.top, rc.right, rc.bottom);
  3501. fRedrawOld = _SetRedraw(FALSE);
  3502. dy = _SizeDifference(&rc);
  3503. for (int iAttempt = 0; (iAttempt < 2) && dy; iAttempt++)
  3504. {
  3505. PRBB prbb = _rbbList;
  3506. BOOL fValidBand = FALSE;
  3507. while ((prbb - _rbbList < (int)_cBands) && !fValidBand)
  3508. {
  3509. if (!(prbb->fStyle & RBBS_HIDDEN) && (prbb->fStyle & RBBS_VARIABLEHEIGHT) && !(prbb->fStyle & RBBS_FIXEDSIZE))
  3510. {
  3511. fValidBand = TRUE;
  3512. }
  3513. else
  3514. {
  3515. prbb++;
  3516. }
  3517. }
  3518. if ((prbb - _rbbList < (int)_cBands) && !(prbb->fStyle & RBBS_HIDDEN) && (prbb->fStyle & RBBS_VARIABLEHEIGHT) && !(prbb->fStyle & RBBS_FIXEDSIZE))
  3519. {
  3520. PRBB prbbMaxIntegral = prbb;
  3521. do {
  3522. if (!(prbb->fStyle & RBBS_HIDDEN) && (prbb->fStyle & RBBS_VARIABLEHEIGHT) && !(prbb->fStyle & RBBS_FIXEDSIZE))
  3523. {
  3524. if (prbbMaxIntegral->cyIntegral < prbb->cyIntegral)
  3525. {
  3526. prbbMaxIntegral = prbb;
  3527. }
  3528. }
  3529. prbb++;
  3530. }
  3531. while ((prbb - _rbbList < (int)_cBands) && !_IsBandStartOfRow(prbb));
  3532. int old_cyChild = prbbMaxIntegral->cyChild;
  3533. if (prbbMaxIntegral->cyIntegral)
  3534. {
  3535. _GrowBand(prbbMaxIntegral, dy, FALSE, -1);
  3536. }
  3537. else
  3538. {
  3539. prbbMaxIntegral->cyChild += dy;
  3540. }
  3541. if (prbbMaxIntegral->cyChild != old_cyChild)
  3542. {
  3543. fChanged = TRUE;
  3544. }
  3545. UINT uFirst = _BandToIndex(_GetFirstInRow(prbbMaxIntegral));
  3546. UINT uLast = _BandToIndex(_GetLastInRow(prbbMaxIntegral, FALSE));
  3547. for (UINT uBand = uFirst; uBand <= uLast; uBand++)
  3548. {
  3549. prbb = _GetBand(uBand);
  3550. // if it's a variable height kind of guy, grow/shrink it
  3551. if ((prbb != prbbMaxIntegral) && !(prbb->fStyle & RBBS_HIDDEN) && (prbb->fStyle & RBBS_VARIABLEHEIGHT) && !(prbb->fStyle & RBBS_FIXEDSIZE))
  3552. {
  3553. old_cyChild = prbb->cyChild;
  3554. if (prbb->cyIntegral && prbbMaxIntegral->cyIntegral)
  3555. {
  3556. prbb->cyChild = prbbMaxIntegral->cyChild - ((prbbMaxIntegral->cyChild - prbb->cyMinChild) % prbb->cyIntegral);
  3557. }
  3558. else
  3559. {
  3560. prbb->cyChild = prbbMaxIntegral->cyChild;
  3561. }
  3562. if (prbb->cyChild != old_cyChild)
  3563. {
  3564. fChanged = TRUE;
  3565. }
  3566. }
  3567. }
  3568. for (UINT uBand = uLast + 1; uBand < _cBands; uBand++)
  3569. {
  3570. prbb = _GetBand(uBand);
  3571. if (!(prbb->fStyle & RBBS_HIDDEN) && (prbb->fStyle & RBBS_VARIABLEHEIGHT) && !(prbb->fStyle & RBBS_FIXEDSIZE))
  3572. {
  3573. if (prbb->cyChild != prbb->cyMinChild)
  3574. {
  3575. prbb->cyChild = prbb->cyMinChild;
  3576. fChanged = TRUE;
  3577. }
  3578. }
  3579. }
  3580. }
  3581. if (fChanged)
  3582. {
  3583. _Resize(TRUE);
  3584. dy = _SizeDifference(&rc);
  3585. }
  3586. }
  3587. _SetRedraw(fRedrawOld);
  3588. return fChanged;
  3589. }
  3590. void CReBar::_SizeBandToRowHeight(int i, int uRowHeight)
  3591. {
  3592. PRBB prbb = _GetBand(i);
  3593. if (prbb && prbb->fStyle & RBBS_VARIABLEHEIGHT)
  3594. {
  3595. if (uRowHeight == -1)
  3596. uRowHeight = _GetRowHeight(i);
  3597. if (uRowHeight > prbb->cyChild)
  3598. {
  3599. _GrowBand(prbb, 0, TRUE, uRowHeight);
  3600. }
  3601. }
  3602. }
  3603. // in the process of sizing, one band in a row of several bands might have
  3604. // grow pretty large. we need to let the other bands have a chance to fill
  3605. // the extra space as well
  3606. void CReBar::_SizeBandsToRowHeight()
  3607. {
  3608. UINT i;
  3609. int iRowHeight = -1;
  3610. for (i = 0; i < _cBands; i++)
  3611. {
  3612. PRBB prbb = _GetBand(i);
  3613. if (prbb->fStyle & RBBS_HIDDEN)
  3614. continue;
  3615. if (_IsBandStartOfRow(prbb))
  3616. iRowHeight = _GetRowHeight(i);
  3617. _SizeBandToRowHeight(i, iRowHeight);
  3618. }
  3619. }
  3620. BOOL CReBar::_OkayToChangeBreak(PRBB prbb, UINT uMsg)
  3621. {
  3622. NMREBARAUTOBREAK nm;
  3623. nm.uBand = _BandToIndex(prbb);
  3624. nm.wID = prbb->wID;
  3625. nm.lParam = prbb->lParam;
  3626. nm.uMsg = uMsg;
  3627. nm.fStyleCurrent = prbb->fStyle;
  3628. nm.fAutoBreak = TRUE;
  3629. CCSendNotify(&_ci, RBN_AUTOBREAK, &nm.hdr);
  3630. return nm.fAutoBreak;
  3631. }
  3632. // this will add/remove rebar band breaks to get to the requested size.
  3633. // it returns TRUE/FALSE whether something was done or not.
  3634. LRESULT CReBar::_SizeBarToRect(DWORD dwFlags, LPRECT prc)
  3635. {
  3636. BOOL fChanged = FALSE;
  3637. RECT rc;
  3638. BOOL fRedrawOld = _SetRedraw(FALSE);
  3639. if (!prc)
  3640. {
  3641. GetClientRect(_ci.hwnd, &rc);
  3642. prc = &rc;
  3643. }
  3644. if (_cBands)
  3645. {
  3646. int c;
  3647. UINT cBands = _cBands;
  3648. BOOL fRearrangeBands = (_cBands > 0);
  3649. BOOL fGrowing = TRUE;
  3650. // if we're shrinking the rebar, we first want to shrink the bands before we start
  3651. // removing breaks
  3652. c = _SizeDifference(prc);
  3653. if (c < 0)
  3654. fGrowing = FALSE;
  3655. fChanged = _SizeBandsToRect(prc);
  3656. if (!fGrowing && !_BandsAtMinHeight())
  3657. {
  3658. // if we're shrinking and all the bands are not down to
  3659. // the minimum height, don't try doing any of the breaking stuff
  3660. goto Bail;
  3661. }
  3662. while (fRearrangeBands)
  3663. {
  3664. int cyRowHalf = _GetRowHeight(_cBands-1) / 2 ;
  3665. REBARBANDINFO rbbi;
  3666. PRBB prbb;
  3667. fRearrangeBands = FALSE;
  3668. rbbi.cbSize = sizeof(REBARBANDINFO);
  3669. rbbi.fMask = RBBIM_STYLE;
  3670. c = _SizeDifference(prc);
  3671. if (c < -cyRowHalf)
  3672. {
  3673. // we've shrunk the rebar, try to remove breaks
  3674. while (--cBands)
  3675. {
  3676. prbb = _GetBand(cBands);
  3677. if (prbb->fStyle & RBBS_HIDDEN)
  3678. continue;
  3679. if ((prbb->fStyle & RBBS_BREAK) && (_OkayToChangeBreak(prbb, RBAB_AUTOSIZE)))
  3680. {
  3681. fChanged = TRUE;
  3682. fRearrangeBands = TRUE;
  3683. rbbi.fStyle = prbb->fStyle & ~RBBS_BREAK;
  3684. _SetBandInfo(cBands, &rbbi, TRUE);
  3685. break;
  3686. }
  3687. }
  3688. }
  3689. else if (c > cyRowHalf)
  3690. {
  3691. // we're enlarging the rebar
  3692. while (--cBands)
  3693. {
  3694. prbb = _GetBand(cBands);
  3695. if (prbb->fStyle & RBBS_HIDDEN)
  3696. continue;
  3697. if ((!(prbb->fStyle & (RBBS_BREAK | RBBS_FIXEDSIZE))) && (_OkayToChangeBreak(prbb, RBAB_AUTOSIZE)))
  3698. {
  3699. // no break here, add it
  3700. fChanged = TRUE;
  3701. fRearrangeBands = TRUE;
  3702. rbbi.fStyle = (prbb->fStyle | RBBS_BREAK);
  3703. _SetBandInfo(cBands, &rbbi, TRUE);
  3704. break;
  3705. }
  3706. }
  3707. }
  3708. }
  3709. // if we did as much breaking as we could
  3710. // and we walked all the way down to the 0th band (we start at the Nth band)
  3711. // then we try to grow the bands that are VARIABLEHEIGHT
  3712. // for fGrowing, see comment at top of function
  3713. //
  3714. // wedo the % because cBands == _cBands if we didn't go through
  3715. // any of the breaking loops at all
  3716. if (!(cBands % _cBands) && fGrowing)
  3717. fChanged |= _SizeBandsToRect(prc);
  3718. }
  3719. Bail:
  3720. _SizeBandsToRowHeight();
  3721. _SetRedraw(fRedrawOld);
  3722. if (prc && (dwFlags & RBSTR_CHANGERECT))
  3723. {
  3724. if (_IsVertical())
  3725. {
  3726. prc->right = prc->left + _cy;
  3727. }
  3728. else
  3729. {
  3730. prc->bottom = prc->top + _cy;
  3731. }
  3732. }
  3733. return (LRESULT)fChanged;
  3734. }
  3735. void CReBar::_AutoSize()
  3736. {
  3737. NMRBAUTOSIZE nm;
  3738. // if this is an internal autosize call, but we're not in autosize mode
  3739. // do nothing
  3740. if (!(_ci.style & RBS_AUTOSIZE))
  3741. return;
  3742. GetClientRect(_ci.hwnd, &nm.rcTarget);
  3743. nm.fChanged = (BOOL) _SizeBarToRect(0, &nm.rcTarget);
  3744. GetClientRect(_ci.hwnd, &nm.rcActual);
  3745. CCSendNotify(&_ci, RBN_AUTOSIZE, &nm.hdr);
  3746. }
  3747. LRESULT CReBar::_GetBandBorders(int wParam, LPRECT prc)
  3748. {
  3749. BOOL fBandBorders = _UseBandBorders();
  3750. PRBB prbb = &_rbbList[wParam];
  3751. prc->left = _GetHeaderWidth(prbb);
  3752. if (fBandBorders)
  3753. {
  3754. prc->left += 2*g_cxEdge;
  3755. prc->right = 0;
  3756. prc->top = g_cyEdge/2;
  3757. prc->bottom = g_cyEdge /2;
  3758. }
  3759. else
  3760. {
  3761. prc->right = 0;
  3762. prc->top = 0;
  3763. prc->bottom = 0;
  3764. }
  3765. if (_ci.style & CCS_VERT)
  3766. FlipRect(prc);
  3767. return 0;
  3768. }
  3769. void CReBar::_OnStyleChanged(WPARAM wParam, LPSTYLESTRUCT lpss)
  3770. {
  3771. if (wParam == GWL_STYLE)
  3772. {
  3773. DWORD dwChanged;
  3774. _ci.style = lpss->styleNew;
  3775. dwChanged = (lpss->styleOld ^ lpss->styleNew);
  3776. // update to reflect style change
  3777. if (dwChanged & CCS_VERT)
  3778. {
  3779. DebugMsg(TF_REBAR, TEXT("REBAR._osc ReBar is now {%s}"), (lpss->styleNew & CCS_VERT) ? TEXT("Horizontal") : TEXT("Vertical"));
  3780. UINT i;
  3781. for (i = 0; i < _cBands; i++)
  3782. {
  3783. PRBB prbb = _GetBand(i);
  3784. if (prbb->fStyle & RBBS_HIDDEN)
  3785. continue;
  3786. if (!(lpss->styleNew & CCS_VERT))
  3787. {
  3788. prbb->cyChild = 0;
  3789. _cy = 0;
  3790. }
  3791. _BandCalcMinWidth(prbb);
  3792. }
  3793. }
  3794. if (dwChanged & RBS_REGISTERDROP)
  3795. {
  3796. if (_ci.style & RBS_REGISTERDROP)
  3797. {
  3798. ASSERT(!_hDragProxy);
  3799. _hDragProxy = CreateDragProxy(_ci.hwnd, s_DragCallback, TRUE);
  3800. }
  3801. else
  3802. {
  3803. ASSERT(_hDragProxy);
  3804. DestroyDragProxy(_hDragProxy);
  3805. }
  3806. }
  3807. }
  3808. else if (wParam == GWL_EXSTYLE)
  3809. {
  3810. //
  3811. // If the RTL_MIRROR extended style bit had changed, let's
  3812. // repaint the control window
  3813. //
  3814. if ((_ci.dwExStyle&RTL_MIRRORED_WINDOW) != (lpss->styleNew&RTL_MIRRORED_WINDOW))
  3815. {
  3816. _InvalidateRect(NULL);
  3817. }
  3818. //
  3819. // Save the new ex-style bits
  3820. //
  3821. _ci.dwExStyle = lpss->styleNew;
  3822. }
  3823. }
  3824. void CReBar::_OnMouseMove(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3825. {
  3826. RelayToToolTips(_hwndToolTips, hwnd, uMsg, wParam, lParam);
  3827. if (_uCapture != -1)
  3828. {
  3829. // captured band -- mouse is down
  3830. if (hwnd != GetCapture() && !_fParentDrag)
  3831. {
  3832. _SendNotify(_uCapture, RBN_ENDDRAG);
  3833. _OnBeginDrag((UINT)-1);
  3834. }
  3835. else
  3836. _DragBand(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  3837. }
  3838. else
  3839. {
  3840. // hottracking
  3841. int iBand;
  3842. PRBB prbb = NULL;
  3843. PRBB prbbHotOld = _prbbHot;
  3844. RBHITTESTINFO rbht;
  3845. rbht.pt.x = GET_X_LPARAM(lParam);
  3846. rbht.pt.y = GET_Y_LPARAM(lParam);
  3847. iBand = _HitTest(&rbht);
  3848. if (iBand != -1)
  3849. prbb = _GetBand(iBand);
  3850. if (prbbHotOld && (prbbHotOld->wChevState & DCHF_PUSHED))
  3851. return;
  3852. if (prbb && (rbht.flags & RBHT_CHEVRON))
  3853. {
  3854. SetCapture(hwnd);
  3855. _UpdateChevronState(prbb, DCHF_HOT);
  3856. if (prbb == prbbHotOld)
  3857. prbbHotOld = NULL;
  3858. }
  3859. if (prbbHotOld)
  3860. {
  3861. CCReleaseCapture(&_ci);
  3862. _UpdateChevronState(prbbHotOld, DCHF_INACTIVE);
  3863. }
  3864. }
  3865. }
  3866. void CReBar::_OnPushChevron(HWND hwnd, PRBB prbb, LPARAM lParamNM)
  3867. {
  3868. NMREBARCHEVRON nm;
  3869. nm.uBand = _BandToIndex(prbb);
  3870. nm.wID = prbb->wID;
  3871. nm.lParam = prbb->lParam;
  3872. nm.lParamNM = lParamNM;
  3873. CopyRect(&nm.rc, &prbb->rcChevron);
  3874. if (_IsVertical())
  3875. FlipRect(&nm.rc);
  3876. _UpdateChevronState(prbb, DCHF_PUSHED);
  3877. CCReleaseCapture(&_ci);
  3878. CCSendNotify(&_ci, RBN_CHEVRONPUSHED, &nm.hdr);
  3879. _UpdateChevronState(_prbbHot, DCHF_INACTIVE);
  3880. }
  3881. void CReBar::_OnCreate(HWND hwnd, LPCREATESTRUCT pcs)
  3882. {
  3883. InitGlobalColors();
  3884. _uCapture = -1;
  3885. _clrBk = CLR_NONE;
  3886. _clrText = CLR_NONE;
  3887. // Init the dwSize because we block-copy it back to the app
  3888. _clrsc.dwSize = sizeof(COLORSCHEME);
  3889. _clrsc.clrBtnHighlight = _clrsc.clrBtnShadow = CLR_DEFAULT;
  3890. _fRedraw = TRUE;
  3891. _fRecalc = TRUE;
  3892. CIInitialize(&_ci, hwnd, pcs);
  3893. _CacheThemeInfo(TRUE);
  3894. if (!(_ci.style & (CCS_TOP | CCS_NOMOVEY | CCS_BOTTOM)))
  3895. {
  3896. _ci.style |= CCS_TOP;
  3897. SetWindowLong(hwnd, GWL_STYLE, _ci.style);
  3898. }
  3899. if (_ci.style & WS_BORDER)
  3900. _fHasBorder = TRUE;
  3901. _SetFont(0);
  3902. if (pcs->lpCreateParams)
  3903. _SetBarInfo((LPREBARINFO) (pcs->lpCreateParams));
  3904. }
  3905. LRESULT CALLBACK CReBar::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3906. {
  3907. CReBar* prb = (CReBar*) GetWindowPtr(hwnd, 0);
  3908. if (prb)
  3909. {
  3910. LRESULT lres = prb->_WndProc(hwnd, uMsg, wParam, lParam);
  3911. if (uMsg == WM_NCDESTROY)
  3912. {
  3913. SetWindowPtr(hwnd, 0, 0);
  3914. delete prb;
  3915. }
  3916. return lres;
  3917. }
  3918. else if (uMsg == WM_NCCREATE)
  3919. {
  3920. prb = new CReBar();
  3921. if (prb)
  3922. {
  3923. SetWindowPtr(hwnd, 0, prb);
  3924. return prb->_WndProc(hwnd, uMsg, wParam, lParam);
  3925. }
  3926. return FALSE;
  3927. }
  3928. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  3929. }
  3930. LRESULT CReBar::_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3931. {
  3932. switch (uMsg)
  3933. {
  3934. case WM_SETREDRAW:
  3935. _SetRecalc(BOOLFROMPTR(wParam));
  3936. return _SetRedraw(BOOLFROMPTR(wParam));
  3937. case WM_NCCREATE:
  3938. _OnCreate(hwnd, (LPCREATESTRUCT)lParam);
  3939. return TRUE;
  3940. case WM_NCDESTROY:
  3941. _OnDestroy();
  3942. break;
  3943. case WM_CREATE:
  3944. // Do delayed stuff for speed.
  3945. PostMessage(hwnd, RB_PRIV_DODELAYEDSTUFF, 0, 0);
  3946. goto CallDWP;
  3947. case RB_PRIV_DODELAYEDSTUFF:
  3948. // Delay done stuff for speed:
  3949. if (_ci.style & RBS_REGISTERDROP)
  3950. _hDragProxy = CreateDragProxy(_ci.hwnd, s_DragCallback, TRUE);
  3951. if (_ci.style & RBS_TOOLTIPS)
  3952. {
  3953. TOOLINFO ti;
  3954. // don't bother setting the rect because we'll do it below
  3955. // in FlushToolTipsMgr;
  3956. ti.cbSize = sizeof(ti);
  3957. ti.uFlags = TTF_IDISHWND;
  3958. ti.hwnd = hwnd;
  3959. ti.uId = (UINT_PTR)hwnd;
  3960. ti.lpszText = 0;
  3961. _hwndToolTips = CreateWindowEx(WS_EX_TRANSPARENT, c_szSToolTipsClass, NULL,
  3962. WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  3963. hwnd, NULL, (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
  3964. SendMessage(_hwndToolTips, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO) &ti);
  3965. }
  3966. _InitPaletteHack();
  3967. break;
  3968. case WM_NCHITTEST:
  3969. {
  3970. RBHITTESTINFO rbht;
  3971. int iBand;
  3972. rbht.pt.x = GET_X_LPARAM(lParam);
  3973. rbht.pt.y = GET_Y_LPARAM(lParam);
  3974. ScreenToClient(_ci.hwnd, &rbht.pt);
  3975. iBand = _HitTest(&rbht);
  3976. {
  3977. NMMOUSE nm;
  3978. LRESULT lres;
  3979. nm.dwItemSpec = iBand;
  3980. nm.pt = rbht.pt;
  3981. nm.dwHitInfo = rbht.flags;
  3982. // send to the parent to give them a chance to override
  3983. lres = CCSendNotify(&_ci, NM_NCHITTEST, &nm.hdr);
  3984. if (lres)
  3985. return lres;
  3986. }
  3987. }
  3988. return HTCLIENT;
  3989. case WM_NCCALCSIZE:
  3990. if (_ci.style & WS_BORDER)
  3991. {
  3992. InflateRect((LPRECT) lParam, -g_cxEdge, -g_cyEdge);
  3993. break;
  3994. }
  3995. goto CallDWP;
  3996. case WM_NCPAINT:
  3997. if (_ci.style & WS_BORDER)
  3998. {
  3999. RECT rc;
  4000. HDC hdc;
  4001. GetWindowRect(hwnd, &rc);
  4002. OffsetRect(&rc, -rc.left, -rc.top);
  4003. hdc = GetWindowDC(hwnd);
  4004. if (hdc)
  4005. {
  4006. CCDrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT, &(_clrsc));
  4007. ReleaseDC(hwnd, hdc);
  4008. }
  4009. break;
  4010. }
  4011. goto CallDWP;
  4012. case WM_PALETTECHANGED:
  4013. if ((HWND)wParam == hwnd)
  4014. break;
  4015. case WM_QUERYNEWPALETTE:
  4016. // Want to pass FALSE if WM_QUERYNEWPALETTE...
  4017. _Realize(NULL, uMsg == WM_PALETTECHANGED, uMsg == WM_PALETTECHANGED);
  4018. return TRUE;
  4019. case WM_PAINT:
  4020. case WM_PRINTCLIENT:
  4021. _OnPaint((HDC)wParam);
  4022. break;
  4023. case WM_ERASEBKGND:
  4024. if (_EraseBkgnd((HDC) wParam, -1))
  4025. return(TRUE);
  4026. goto CallDWP;
  4027. case WM_SYSCOLORCHANGE:
  4028. _InitPaletteHack();
  4029. if (_hwndToolTips)
  4030. SendMessage(_hwndToolTips, uMsg, wParam, lParam);
  4031. InitGlobalColors();
  4032. InvalidateRect(_ci.hwnd, NULL, TRUE);
  4033. break;
  4034. case RB_SETPALETTE:
  4035. return (LRESULT)_SetPalette((HPALETTE)lParam);
  4036. case RB_GETPALETTE:
  4037. return (LRESULT)_hpal;
  4038. case RB_GETBANDMARGINS:
  4039. {
  4040. MARGINS* pMargin = (MARGINS*)lParam;
  4041. if (pMargin)
  4042. *pMargin = _mBand;
  4043. return 1;
  4044. }
  4045. case WM_SIZE:
  4046. _AutoSize();
  4047. _Resize(FALSE);
  4048. break;
  4049. case WM_GETFONT:
  4050. return (LRESULT)_hFont;
  4051. case WM_COMMAND:
  4052. case WM_DRAWITEM:
  4053. case WM_MEASUREITEM:
  4054. case WM_VKEYTOITEM:
  4055. case WM_CHARTOITEM:
  4056. SendMessage(_ci.hwndParent, uMsg, wParam, lParam);
  4057. break;
  4058. case WM_LBUTTONDBLCLK: // DBLCLK sent in place of LBUTTONDOWN
  4059. case WM_RBUTTONDOWN: // right button drags too
  4060. case WM_LBUTTONDOWN:
  4061. {
  4062. RBHITTESTINFO rbht;
  4063. PRBB prbb = NULL;
  4064. rbht.pt.x = GET_X_LPARAM(lParam);
  4065. rbht.pt.y = GET_Y_LPARAM(lParam);
  4066. RelayToToolTips(_hwndToolTips, hwnd, uMsg, wParam, lParam);
  4067. int iBand = _HitTest(&rbht);
  4068. if (iBand != -1)
  4069. prbb = _GetBand(iBand);
  4070. if (!prbb)
  4071. {
  4072. /* nothing */ ;
  4073. }
  4074. else if (rbht.flags & RBHT_CHEVRON)
  4075. {
  4076. _OnPushChevron(hwnd, prbb, 0);
  4077. }
  4078. else if (rbht.flags != RBHT_CLIENT && _ShouldDrawGripper(prbb))
  4079. {
  4080. _uCapture = iBand;
  4081. _ptCapture = rbht.pt;
  4082. if (_ci.style & CCS_VERT)
  4083. SWAP(_ptCapture.x, _ptCapture.y, int);
  4084. _xStart = prbb->x;
  4085. SetCapture(hwnd);
  4086. _fFullOnDrag = FALSE;
  4087. if (uMsg == WM_LBUTTONDBLCLK && (_ci.style & RBS_DBLCLKTOGGLE))
  4088. _ToggleBand(TRUE);
  4089. }
  4090. }
  4091. break;
  4092. case WM_SETCURSOR:
  4093. // Give the parent first crack, if it sets the cursor then
  4094. // leave it at that. Otherwise if the cursor is over our
  4095. // window then set it to what we want it to be.
  4096. if (!DefWindowProc(hwnd, uMsg, wParam, lParam) && (hwnd == (HWND)wParam))
  4097. {
  4098. POINT pt;
  4099. GetMessagePosClient(_ci.hwnd, &pt);
  4100. _SetCursor(pt.x, pt.y, (HIWORD(lParam) == WM_LBUTTONDOWN || HIWORD(lParam) == WM_RBUTTONDOWN));
  4101. }
  4102. return TRUE;
  4103. case WM_MOUSEMOVE:
  4104. _OnMouseMove(hwnd, uMsg, wParam, lParam);
  4105. break;
  4106. case WM_RBUTTONUP:
  4107. if (!_fFullOnDrag && !_fParentDrag) {
  4108. CCReleaseCapture(&_ci);
  4109. // if we're not doing drag drop, go to def window proc so that
  4110. // wm_contextmenu gets propagated
  4111. _OnBeginDrag((UINT)-1);
  4112. goto CallDWP;
  4113. }
  4114. // fall through
  4115. case WM_LBUTTONUP:
  4116. RelayToToolTips(_hwndToolTips, hwnd, uMsg, wParam, lParam);
  4117. if (_uCapture != -1)
  4118. {
  4119. UINT uiIndex;
  4120. if (!_fParentDrag)
  4121. CCReleaseCapture(&_ci);
  4122. // if there was no significant mouse motion, treat as a click
  4123. if (!(_ci.style & RBS_DBLCLKTOGGLE) && !_fFullOnDrag)
  4124. _ToggleBand(TRUE);
  4125. _GetBand(_uCapture)->fStyle &= ~RBBS_DRAGBREAK;
  4126. CCSendNotify(&_ci, RBN_LAYOUTCHANGED, NULL);
  4127. _SendNotify(_uCapture, RBN_ENDDRAG);
  4128. _OnBeginDrag((UINT)-1);
  4129. for (uiIndex = 0; uiIndex < _cBands; uiIndex++) {
  4130. if (_GetBand(uiIndex)->fStyle & RBBS_HIDDEN)
  4131. continue;
  4132. _BandCalcMinWidth(_GetBand(uiIndex));
  4133. }
  4134. _SizeBandsToRect(NULL);
  4135. _InvalidateRect(NULL);
  4136. }
  4137. break;
  4138. case WM_WININICHANGE:
  4139. InitGlobalMetrics(wParam);
  4140. if (_fFontCreated)
  4141. _SetFont(wParam);
  4142. if (_hwndToolTips)
  4143. SendMessage(_hwndToolTips, uMsg, wParam, lParam);
  4144. for (DWORD dwIndex = 0; dwIndex < _cBands; dwIndex++)
  4145. {
  4146. PRBB prbb = _rbbList + dwIndex;
  4147. SendMessage(prbb->hwndChild, WM_WININICHANGE, wParam, lParam);
  4148. }
  4149. break;
  4150. case WM_SETFONT:
  4151. _OnSetFont((HFONT)wParam);
  4152. break;
  4153. case WM_NOTIFYFORMAT:
  4154. return(CIHandleNotifyFormat(&_ci, lParam));
  4155. case WM_NOTIFY:
  4156. // We are just going to pass this on to the real parent
  4157. // Note that -1 is used as the hwndFrom. This prevents SendNotifyEx
  4158. // from updating the NMHDR structure.
  4159. return(SendNotifyEx(_ci.hwndParent, (HWND) -1,
  4160. ((LPNMHDR) lParam)->code, (LPNMHDR) lParam, _ci.bUnicode));
  4161. case WM_STYLECHANGED:
  4162. _OnStyleChanged(wParam, (LPSTYLESTRUCT)lParam);
  4163. break;
  4164. case WM_UPDATEUISTATE:
  4165. if (CCOnUIState(&(_ci), WM_UPDATEUISTATE, wParam, lParam))
  4166. {
  4167. InvalidateRect(hwnd, NULL, TRUE);
  4168. }
  4169. goto CallDWP;
  4170. case RB_SETBANDINFOA:
  4171. case RB_INSERTBANDA:
  4172. if (EVAL(lParam))
  4173. {
  4174. LPWSTR lpStrings = NULL;
  4175. LPSTR lpAnsiString;
  4176. int iResult;
  4177. // lParam starts out pointing to a REBARBANDINFOA, and
  4178. // we secretly change it into a REBARBANDINFOW, and then
  4179. // change it back.
  4180. LPREBARBANDINFOW prbiW = (LPREBARBANDINFOW)lParam;
  4181. LPREBARBANDINFOA prbiA = (LPREBARBANDINFOA)lParam;
  4182. COMPILETIME_ASSERT(sizeof(REBARBANDINFOW) == sizeof(REBARBANDINFOA));
  4183. // Bug#94345 - raymondc - Is it safe to modify the incoming
  4184. // REBARBANDINFOA structure?
  4185. lpAnsiString = prbiA->lpText;
  4186. if ((prbiA->fMask & RBBIM_TEXT) && prbiA->lpText) {
  4187. lpStrings = ProduceWFromA(_ci.uiCodePage, lpAnsiString);
  4188. if (!lpStrings)
  4189. return -1;
  4190. // Presto! Now it's a REBARBANDINFOW!
  4191. prbiW->lpText = lpStrings;
  4192. }
  4193. if (uMsg == RB_INSERTBANDA)
  4194. iResult = _InsertBand((UINT) wParam, prbiW);
  4195. else
  4196. iResult = _SetBandInfo((UINT) wParam, prbiW, TRUE);
  4197. // Change-o! Now it's a REBARBANDINFOA!
  4198. prbiA->lpText = lpAnsiString;
  4199. if (lpStrings)
  4200. FreeProducedString(lpStrings);
  4201. return iResult;
  4202. }
  4203. case RB_INSERTBAND:
  4204. return(_InsertBand((UINT) wParam, (LPREBARBANDINFO) lParam));
  4205. case RB_DELETEBAND:
  4206. return(_DeleteBand((UINT) wParam));
  4207. case RB_SHOWBAND:
  4208. return(_ShowBand((UINT) wParam, BOOLFROMPTR(lParam)));
  4209. case RB_GETBANDINFOA:
  4210. {
  4211. LPREBARBANDINFOA prbbi = (LPREBARBANDINFOA)lParam;
  4212. LPWSTR pszW = NULL;
  4213. LPSTR lpAnsiString = prbbi->lpText;
  4214. int iResult;
  4215. if (prbbi->fMask & RBBIM_TEXT) {
  4216. pszW = (LPWSTR)LocalAlloc(LPTR, prbbi->cch * sizeof(WCHAR));
  4217. if (!pszW)
  4218. return 0;
  4219. prbbi->lpText = (LPSTR)pszW;
  4220. }
  4221. iResult = _GetBandInfo((UINT)wParam, (LPREBARBANDINFO)lParam);
  4222. if (pszW) {
  4223. ConvertWToAN(_ci.uiCodePage, lpAnsiString, prbbi->cch, (LPWSTR)prbbi->lpText, -1);
  4224. prbbi->lpText = lpAnsiString;
  4225. LocalFree(pszW);
  4226. }
  4227. return iResult;
  4228. }
  4229. // we have getbandinfoold because in ie3, we did not thunk
  4230. // and getbandinfo always return OS native string (dumb)
  4231. case RB_GETBANDINFOOLD:
  4232. case RB_GETBANDINFO:
  4233. return(_GetBandInfo((UINT) wParam, (LPREBARBANDINFO) lParam));
  4234. case RB_GETTOOLTIPS:
  4235. return (LPARAM)_hwndToolTips;
  4236. case RB_SETTOOLTIPS:
  4237. _hwndToolTips = (HWND)wParam;
  4238. break;
  4239. case RB_SETBKCOLOR:
  4240. {
  4241. COLORREF clr = _clrBk;
  4242. _clrBk = (COLORREF)lParam;
  4243. if (clr != _clrBk)
  4244. InvalidateRect(_ci.hwnd, NULL, TRUE);
  4245. return clr;
  4246. }
  4247. case RB_GETBKCOLOR:
  4248. return _clrBk;
  4249. case RB_SETTEXTCOLOR:
  4250. {
  4251. COLORREF clr = _clrText;
  4252. _clrText = (COLORREF)lParam;
  4253. return clr;
  4254. }
  4255. case RB_GETTEXTCOLOR:
  4256. return _clrText;
  4257. case RB_IDTOINDEX:
  4258. return _IDToIndex((UINT) wParam);
  4259. case RB_GETROWCOUNT:
  4260. return(_GetRowCount());
  4261. case RB_GETROWHEIGHT:
  4262. return _GetRowHeight((UINT)wParam);
  4263. case RB_GETBANDBORDERS:
  4264. return _GetBandBorders((UINT)wParam, (LPRECT)lParam);
  4265. case RB_GETBANDCOUNT:
  4266. return(_cBands);
  4267. case RB_SETBANDINFO:
  4268. return(_SetBandInfo((UINT) wParam, (LPREBARBANDINFO) lParam, TRUE));
  4269. case RB_GETBARINFO:
  4270. return(_GetBarInfo((LPREBARINFO) lParam));
  4271. case RB_SETBARINFO:
  4272. return(_SetBarInfo((LPREBARINFO) lParam));
  4273. case RB_SETPARENT:
  4274. {
  4275. HWND hwndOld = _ci.hwndParent;
  4276. _ci.hwndParent = (HWND) wParam;
  4277. return (LRESULT)hwndOld;
  4278. }
  4279. break;
  4280. case RB_GETRECT:
  4281. if (_IsValidIndex((UINT)wParam))
  4282. {
  4283. PRBB prbb = _GetBand((UINT)wParam);
  4284. LPRECT lprc = (LPRECT) lParam;
  4285. lprc->left = prbb->x;
  4286. lprc->top = prbb->y;
  4287. lprc->right = prbb->x + prbb->cx;
  4288. lprc->bottom = prbb->y + prbb->cy;
  4289. return(TRUE);
  4290. }
  4291. break;
  4292. case RB_HITTEST:
  4293. return(_HitTest((LPRBHITTESTINFO) lParam));
  4294. case RB_SIZETORECT:
  4295. return _SizeBarToRect((DWORD)wParam, (LPRECT)lParam);
  4296. case RB_BEGINDRAG:
  4297. if (_IsValidIndex((UINT)wParam)) {
  4298. // -1 means do it yourself.
  4299. // -2 means use what you had saved before
  4300. if (lParam != (LPARAM)-2) {
  4301. if (lParam == (LPARAM)-1) {
  4302. GetMessagePosClient(_ci.hwnd, &_ptCapture);
  4303. } else {
  4304. _ptCapture.x = GET_X_LPARAM(lParam);
  4305. _ptCapture.y = GET_Y_LPARAM(lParam);
  4306. }
  4307. if (_ci.style & CCS_VERT)
  4308. SWAP(_ptCapture.x, _ptCapture.y, int);
  4309. }
  4310. _xStart = _GetBand((UINT)wParam)->x;
  4311. _OnBeginDrag((UINT)wParam);
  4312. }
  4313. break;
  4314. case RB_GETBARHEIGHT:
  4315. return _GetBarHeight();
  4316. case RB_ENDDRAG:
  4317. _OnBeginDrag((UINT)-1);
  4318. break;
  4319. case RB_DRAGMOVE:
  4320. if (_uCapture != -1) {
  4321. if (lParam == (LPARAM)-1) {
  4322. lParam = GetMessagePosClient(_ci.hwnd, NULL);
  4323. }
  4324. _DragBand(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  4325. }
  4326. break;
  4327. case RB_MINIMIZEBAND:
  4328. _MinimizeBand((UINT) wParam,FALSE);
  4329. break;
  4330. case RB_MAXIMIZEBAND:
  4331. _MaximizeBand((UINT)wParam, BOOLFROMPTR(lParam),FALSE);
  4332. break;
  4333. case RB_MOVEBAND:
  4334. if (!_IsValidIndex((UINT)wParam) || !_IsValidIndex((UINT)lParam))
  4335. break;
  4336. return _MoveBand((UINT) wParam, (UINT) lParam);
  4337. case RB_GETDROPTARGET:
  4338. if (!_hDragProxy)
  4339. _hDragProxy = CreateDragProxy(_ci.hwnd, s_DragCallback, FALSE);
  4340. GetDragProxyTarget(_hDragProxy, (IDropTarget**)lParam);
  4341. break;
  4342. case RB_GETCOLORSCHEME:
  4343. {
  4344. LPCOLORSCHEME lpclrsc = (LPCOLORSCHEME) lParam;
  4345. if (lpclrsc) {
  4346. if (lpclrsc->dwSize == sizeof(COLORSCHEME))
  4347. *lpclrsc = _clrsc;
  4348. }
  4349. return (LRESULT) lpclrsc;
  4350. }
  4351. case RB_SETCOLORSCHEME:
  4352. if (lParam) {
  4353. if (((LPCOLORSCHEME) lParam)->dwSize == sizeof(COLORSCHEME)) {
  4354. _clrsc.clrBtnHighlight = ((LPCOLORSCHEME) lParam)->clrBtnHighlight;
  4355. _clrsc.clrBtnShadow = ((LPCOLORSCHEME) lParam)->clrBtnShadow;
  4356. InvalidateRect(hwnd, NULL, FALSE);
  4357. if (_ci.style & WS_BORDER)
  4358. CCInvalidateFrame(hwnd);
  4359. }
  4360. }
  4361. break;
  4362. case RB_PUSHCHEVRON:
  4363. if (_IsValidIndex((UINT)wParam)) {
  4364. PRBB prbb = _GetBand((UINT)wParam);
  4365. _OnPushChevron(hwnd, prbb, lParam);
  4366. }
  4367. break;
  4368. case RB_SETWINDOWTHEME:
  4369. if (lParam)
  4370. {
  4371. SetWindowTheme(hwnd, (LPWSTR)lParam, NULL);
  4372. }
  4373. break;
  4374. case WM_THEMECHANGED:
  4375. _CacheThemeInfo((BOOL)wParam);
  4376. InvalidateRect(_ci.hwnd, NULL, TRUE);
  4377. return 0;
  4378. default:
  4379. LRESULT lres;
  4380. if (CCWndProc(&_ci, uMsg, wParam, lParam, &lres))
  4381. return lres;
  4382. CallDWP:
  4383. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  4384. }
  4385. return 0;
  4386. }