XTPTabPaintManager.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:40k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPTabPaintManager.cpp: implementation of the CXTPTabPaintManager class.
  2. //
  3. // This file is a part of the XTREME TOOLKIT PRO MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPVC80Helpers.h"
  22. #include "Common/XTPSystemHelpers.h"
  23. #include "Common/XTPMarkupRender.h"
  24. #include "XTPTabPaintManager.h"
  25. #include "XTPTabManager.h"
  26. #include "Common/XTPColorManager.h"
  27. #include "Common/XTPDrawHelpers.h"
  28. #include "XTPTabPaintManager.inl"
  29. #ifdef _DEBUG
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #define new DEBUG_NEW
  33. #endif
  34. //////////////////////////////////////////////////////////////////////
  35. // CXTPTabPaintManager
  36. CXTPTabPaintManager::CXTPTabPaintManager()
  37. {
  38. m_bUseStandardFont = TRUE;
  39. m_pColorSet = NULL;
  40. m_pAppearanceSet = NULL;
  41. SetAppearance(xtpTabAppearancePropertyPage);
  42. m_bHotTracking = FALSE;
  43. m_bBoldNormal = m_bBoldSelected = FALSE;
  44. m_bShowIcons = TRUE;
  45. m_bSelectOnButtonDown = TRUE;
  46. m_bDisableLunaColors = FALSE;
  47. m_bOneNoteColors = FALSE;
  48. m_tabPosition = xtpTabPositionTop;
  49. m_tabLayout = xtpTabLayoutAutoSize;
  50. m_clientFrame = xtpTabFrameBorder;
  51. m_bStaticFrame = FALSE;
  52. m_bInvertGradient = FALSE;
  53. m_bFillBackground = TRUE;
  54. m_bDrawFocusRect = TRUE;
  55. m_rcClientMargin.SetRect(0, 0, 0, 0);
  56. m_rcControlMargin.SetRect(0, 0, 0, 0);
  57. m_rcButtonMargin.SetRect(0, 0, 0, 0);
  58. m_nButtonExtraLength = 0;
  59. m_szIcon = CSize(16, 16);
  60. m_nFixedTabWidth = 70;
  61. m_nMinTabWidth = m_nMaxTabWidth = 0;
  62. m_bDrawTextEndEllipsis = TRUE;
  63. m_bDrawTextPathEllipsis = FALSE;
  64. m_bDrawTextNoPrefix = TRUE;
  65. m_bDrawTextHidePrefix = FALSE;
  66. m_bMultiRowFixedSelection = FALSE;
  67. m_bMultiRowJustified = TRUE;
  68. m_toolBehaviour = xtpTabToolTipShrinkedOnly;
  69. m_bSelectOnDragOver = TRUE;
  70. m_nItemColor = 0;
  71. m_bClearTypeTextQuality = FALSE;
  72. m_bRotateImageOnVerticalDraw = FALSE;
  73. m_rcButtonTextPadding.SetRect(6, 0, 6, 0);
  74. m_bClipHeader = TRUE;
  75. m_nDrawTextFormat = DT_LEFT | DT_VCENTER;
  76. m_szNavigateButton = CSize(14, 15);
  77. m_bShowTabs = TRUE;
  78. EnableAutomation();
  79. RefreshMetrics();
  80. }
  81. CXTPTabPaintManager::~CXTPTabPaintManager()
  82. {
  83. delete m_pColorSet;
  84. delete m_pAppearanceSet;
  85. }
  86. CXTPTabPaintManager::CColorSet* CXTPTabPaintManager::SetColor(XTPTabColorStyle tabColor)
  87. {
  88. CColorSet* pColorSet = NULL;
  89. m_tabColor = tabColor;
  90. if (tabColor == xtpTabColorVisualStudio) pColorSet = new CColorSetVisualStudio();
  91. else if (tabColor == xtpTabColorOffice2003) pColorSet = new CColorSetOffice2003();
  92. else if (tabColor == xtpTabColorWinXP) pColorSet = new CColorSetWinXP();
  93. else if (tabColor == xtpTabColorWhidbey) pColorSet = new CColorSetWhidbey();
  94. else if (tabColor == xtpTabColorVisualStudio2008) pColorSet = new CColorSetVisualStudio2008();
  95. else if (tabColor == xtpTabColorOffice2007) pColorSet = new CColorSetOffice2007();
  96. else if (tabColor == xtpTabColorAccess2007) pColorSet = new CColorSetAccess2007();
  97. else pColorSet = new CColorSetDefault();
  98. return SetColorSet(pColorSet);
  99. }
  100. CXTPTabPaintManager::CColorSet* CXTPTabPaintManager::SetColorSet(CColorSet* pColorSet)
  101. {
  102. if (pColorSet)
  103. {
  104. if (m_pColorSet) delete m_pColorSet;
  105. m_pColorSet = pColorSet;
  106. pColorSet->m_pPaintManager = this;
  107. pColorSet->RefreshMetrics();
  108. }
  109. OnPropertyChanged();
  110. return pColorSet;
  111. }
  112. CXTPTabPaintManager::CAppearanceSet* CXTPTabPaintManager::SetAppearance(XTPTabAppearanceStyle tabAppearance)
  113. {
  114. CAppearanceSet* pAppearanceSet = NULL;
  115. m_tabAppearance = tabAppearance;
  116. if (tabAppearance == xtpTabAppearanceVisualStudio) pAppearanceSet = new CAppearanceSetVisualStudio();
  117. else if (tabAppearance == xtpTabAppearanceExcel) pAppearanceSet = new CAppearanceSetExcel();
  118. else if (tabAppearance == xtpTabAppearancePropertyPageFlat) pAppearanceSet = new CAppearanceSetPropertyPageFlat();
  119. else if (tabAppearance == xtpTabAppearanceFlat) pAppearanceSet = new CAppearanceSetFlat();
  120. else if (tabAppearance == xtpTabAppearanceStateButtons) pAppearanceSet = new CAppearanceSetStateButtons();
  121. else if (tabAppearance == xtpTabAppearancePropertyPageSelected) pAppearanceSet = new CAppearanceSetPropertyPageSelected();
  122. else if (tabAppearance == xtpTabAppearancePropertyPage2003) pAppearanceSet = new CAppearanceSetPropertyPage2003();
  123. else if (tabAppearance == xtpTabAppearanceVisio) pAppearanceSet = new CAppearanceSetVisio();
  124. else if (tabAppearance == xtpTabAppearanceVisualStudio2005) pAppearanceSet = new CAppearanceSetVisualStudio2005();
  125. else if (tabAppearance == xtpTabAppearancePropertyPage2007) pAppearanceSet = new CAppearanceSetPropertyPage2007();
  126. else if (tabAppearance == xtpTabAppearancePropertyPageAccess2007) pAppearanceSet = new CAppearanceSetPropertyPageAccess2007();
  127. else pAppearanceSet = new CAppearanceSetPropertyPage();
  128. return SetAppearanceSet(pAppearanceSet);
  129. }
  130. CXTPTabPaintManager::CAppearanceSet* CXTPTabPaintManager::SetAppearanceSet(CAppearanceSet* pAppearanceSet)
  131. {
  132. if (pAppearanceSet)
  133. {
  134. if (m_pAppearanceSet) delete m_pAppearanceSet;
  135. m_pAppearanceSet = pAppearanceSet;
  136. pAppearanceSet->m_pPaintManager = this;
  137. pAppearanceSet->RefreshMetrics();
  138. SetColor(pAppearanceSet->GetDefaultColorSet());
  139. }
  140. OnPropertyChanged();
  141. return pAppearanceSet;
  142. }
  143. void CXTPTabPaintManager::SetFontIndirect(LOGFONT* pLogFont, BOOL bUseStandardFont /*= FALSE*/)
  144. {
  145. m_bUseStandardFont = bUseStandardFont;
  146. if (!pLogFont)
  147. return;
  148. if (m_bClearTypeTextQuality && XTPSystemVersion()->IsClearTypeTextQualitySupported())
  149. {
  150. pLogFont->lfQuality = 5;
  151. }
  152. m_fntNormal.DeleteObject();
  153. m_fntBold.DeleteObject();
  154. m_fntVerticalNormal.DeleteObject();
  155. m_fntVerticalBold.DeleteObject();
  156. pLogFont->lfWeight = m_bBoldNormal ? FW_BOLD : FW_NORMAL;
  157. VERIFY(m_fntNormal.CreateFontIndirect(pLogFont));
  158. pLogFont->lfWeight = FW_BOLD;
  159. VERIFY(m_fntBold.CreateFontIndirect(pLogFont));
  160. STRCPY_S(pLogFont->lfFaceName, LF_FACESIZE, CXTPDrawHelpers::GetVerticalFontName(FALSE));
  161. pLogFont->lfOrientation = 900;
  162. pLogFont->lfEscapement = 2700;
  163. pLogFont->lfHeight = pLogFont->lfHeight < 0 ? __min(-11, pLogFont->lfHeight) : pLogFont->lfHeight;
  164. pLogFont->lfWeight = m_bBoldNormal ? FW_BOLD : FW_NORMAL;
  165. VERIFY(m_fntVerticalNormal.CreateFontIndirect(pLogFont));
  166. pLogFont->lfWeight = FW_BOLD;
  167. VERIFY(m_fntVerticalBold.CreateFontIndirect(pLogFont));
  168. }
  169. void CXTPTabPaintManager::RefreshMetrics()
  170. {
  171. if (m_bUseStandardFont)
  172. {
  173. LOGFONT lfIcon;
  174. VERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIcon), &lfIcon, 0));
  175. SetFontIndirect(&lfIcon, TRUE);
  176. }
  177. m_pColorSet->RefreshMetrics();
  178. m_pAppearanceSet->RefreshMetrics();
  179. }
  180. void CXTPTabPaintManager::DisableLunaColors(BOOL bDisableLunaColors)
  181. {
  182. m_bDisableLunaColors = bDisableLunaColors;
  183. RefreshMetrics();
  184. OnPropertyChanged();
  185. }
  186. BOOL CXTPTabPaintManager::IsLunaColorsDisabled() const
  187. {
  188. return m_bDisableLunaColors || XTPColorManager()->IsLunaColorsDisabled();
  189. }
  190. COLORREF CXTPTabPaintManager::GetOneNoteColor(XTPTabOneNoteColor tabColor)
  191. {
  192. const COLORREF clrTable[] =
  193. {
  194. RGB(138, 168, 228), // xtpTabColorBlue    : Blue tab color used when OneNote colors enabled.
  195. RGB(255, 219, 117), // xtpTabColorYellow  : Yellow tab color used when OneNote colors enabled.
  196. RGB(189, 205, 159), // xtpTabColorGreen   : Green tab color used when OneNote colors enabled.
  197. RGB(240, 158, 159), // xtpTabColorRed     : Red tab color used when OneNote colors enabled.
  198. RGB(186, 166, 225), // xtpTabColorPurple  : Purple tab color used when OneNote colors enabled.
  199. RGB(154, 191, 180), // xtpTabColorCyan    : Cyan tab color used when OneNote colors enabled.
  200. RGB(247, 182, 131), // xtpTabColorOrange  : Orange tab color used when OneNote colors enabled.
  201. RGB(216, 171, 192)  // xtpTabColorMagenta : Magenta tab color used when OneNote colors enabled.
  202. };
  203. return clrTable[tabColor-xtpTabColorBlue];
  204. }
  205. void CXTPTabPaintManager::SetOneNoteColors(BOOL bOneNoteColors /* = TRUE */)
  206. {
  207. m_bOneNoteColors = bOneNoteColors;
  208. RefreshMetrics();
  209. }
  210. void CXTPTabPaintManager::DrawNavigateButton(CDC* pDC, CXTPTabManagerNavigateButton* pButton, CRect& rc)
  211. {
  212. FillNavigateButton(pDC, pButton, rc);
  213. COLORREF clr = pDC->GetTextColor();
  214. CXTPPenDC pen(*pDC, clr);
  215. if (pButton->IsEnabled())
  216. {
  217. CXTPBrushDC brush(*pDC, clr);
  218. pButton->DrawEntry(pDC, rc);
  219. }
  220. else
  221. {
  222. CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
  223. pButton->DrawEntry(pDC, rc);
  224. pDC->SelectObject(pOldBrush);
  225. }
  226. }
  227. void CXTPTabPaintManager::FillNavigateButton(CDC* pDC, CXTPTabManagerNavigateButton* pButton, CRect& rc)
  228. {
  229. m_pColorSet->FillNavigateButton(pDC, pButton, rc);
  230. }
  231. void CXTPTabPaintManager::DrawTabControl(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
  232. {
  233. m_pAppearanceSet->DrawTabControl(pTabManager, pDC, rcClient);
  234. }
  235. void CXTPTabPaintManager::DrawRowItems(CXTPTabManager* pTabManager, CDC* pDC, const CRect& rcClipBox, int nItemRow)
  236. {
  237. CXTPTabManagerItem* pSelected = NULL;
  238. CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();
  239. if (!pRowItems)
  240. return;
  241. if (nItemRow >= pTabManager->GetRowCount())
  242. return;
  243. int nFirstItem = pRowItems[nItemRow].nFirstItem;
  244. int nLastItem = pRowItems[nItemRow].nLastItem;
  245. BOOL bDrawRow = TRUE;
  246. if (m_pAppearanceSet->m_bButtonsReverseZOrder)
  247. {
  248. bDrawRow = FALSE;
  249. for (int i = nFirstItem; i <= nLastItem; i++)
  250. {
  251. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  252. if (!pItem)
  253. return;
  254. if (pItem->m_nItemRow != nItemRow)
  255. break;
  256. if (pItem->IsSelected())
  257. {
  258. nFirstItem = i;
  259. bDrawRow = TRUE;
  260. break;
  261. }
  262. if (pItem->IsVisible() && CRect().IntersectRect(rcClipBox, m_pAppearanceSet->GetButtonDrawRect(pItem)))
  263. {
  264. m_pAppearanceSet->DrawSingleButton(pDC, pItem);
  265. }
  266. }
  267. }
  268. if (bDrawRow)
  269. {
  270. for (int i = nLastItem; i >= nFirstItem; i--)
  271. {
  272. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  273. if (!pItem)
  274. return;
  275. if (pItem->m_nItemRow != nItemRow)
  276. break;
  277. if (pItem->IsVisible() && CRect().IntersectRect(rcClipBox, m_pAppearanceSet->GetButtonDrawRect(pItem)))
  278. {
  279. if (pItem->IsSelected())
  280. pSelected = pItem;
  281. else
  282. m_pAppearanceSet->DrawSingleButton(pDC, pItem);
  283. }
  284. }
  285. }
  286. if (pSelected)
  287. {
  288. m_pAppearanceSet->DrawSingleButton(pDC, pSelected);
  289. }
  290. }
  291. void CXTPTabPaintManager::DrawTabControlEx(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
  292. {
  293. if (pTabManager->IsDrawStaticFrame())
  294. {
  295. pDC->Draw3dRect(rcClient, GetColorSet()->m_clrFrameBorder, GetColorSet()->m_clrFrameBorder);
  296. CAppearanceSet::DeflateRectEx(rcClient, CRect(1, 1, 1, 1), pTabManager->GetPosition());
  297. pDC->Draw3dRect(rcClient, GetColorSet()->m_clrControlFace, GetColorSet()->m_clrControlFace);
  298. CAppearanceSet::DeflateRectEx(rcClient, CRect(1, 0, 1, 1), pTabManager->GetPosition());
  299. }
  300. if (m_bFillBackground)
  301. {
  302. pDC->FillSolidRect(rcClient, GetColorSet()->m_clrControlFace);
  303. }
  304. CAppearanceSet::DeflateRectEx(rcClient, m_rcControlMargin, pTabManager->GetPosition());
  305. pDC->SetBkMode(TRANSPARENT);
  306. if (m_bFillBackground)
  307. {
  308. m_pAppearanceSet->FillTabControl(pTabManager, pDC, rcClient);
  309. }
  310. int i;
  311. CRect rcClipBox;
  312. pDC->GetClipBox(rcClipBox);
  313. if (m_bClipHeader)
  314. rcClipBox.IntersectRect(rcClipBox, pTabManager->m_rcHeaderRect);
  315. if (!rcClipBox.IsRectEmpty())
  316. {
  317. CRgn rgn;
  318. if (m_bClipHeader)
  319. {
  320. CRect rcClipBoxViewport(rcClipBox);
  321. rcClipBoxViewport.OffsetRect(-pDC->GetWindowOrg());
  322. rgn.CreateRectRgnIndirect(rcClipBoxViewport);
  323. pDC->SelectClipRgn(&rgn);
  324. m_pColorSet->SelectClipRgn(pDC, rcClient, pTabManager);
  325. }
  326. int nRowCont = pTabManager->GetRowCount();
  327. for (int j = nRowCont - 1; j >= 0; j--)
  328. {
  329. DrawRowItems(pTabManager, pDC, rcClipBox, j);
  330. }
  331. if (m_bClipHeader)
  332. {
  333. pDC->SelectClipRgn(NULL);
  334. }
  335. }
  336. for (i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
  337. pTabManager->GetNavigateButton(i)->Draw(pDC);
  338. }
  339. int CXTPTabPaintManager::_GetButtonLength(int nValue, int nMin, int nMax)
  340. {
  341. nValue += m_rcButtonMargin.left +  m_rcButtonMargin.right;
  342. if (nMin > 0) nValue = max(nMin, nValue);
  343. if (nMax > 0) nValue = min(nMax, nValue);
  344. return nValue;
  345. }
  346. void CXTPTabPaintManager::StripMnemonics(CString& strClear)
  347. {
  348. CXTPDrawHelpers::StripMnemonics(strClear);
  349. }
  350. int CXTPTabPaintManager::GetPrefixTextExtent(CDC* pDC, const CString& str, UINT uFormat)
  351. {
  352. if (uFormat & DT_NOPREFIX)
  353. return pDC->GetTextExtent(str).cx;
  354. CString strClear = str;
  355. StripMnemonics(strClear);
  356. return pDC->GetTextExtent(strClear).cx;
  357. }
  358. void CXTPTabPaintManager::DrawTextPathEllipsis(CDC* pDC, const CString& strItem, CRect rcItem, UINT uFormat)
  359. {
  360. if (strItem.Find(_T('\')) != -1)
  361. {
  362. pDC->DrawText(strItem, rcItem, uFormat | DT_PATH_ELLIPSIS);
  363. return;
  364. }
  365. LPCTSTR strEllipsis = _T("...");
  366. int cxEllipsis = pDC->GetTextExtent(strEllipsis, 3).cx;
  367. int cxItem = GetPrefixTextExtent(pDC, strItem, uFormat);
  368. if (cxItem <= rcItem.Width())
  369. {
  370. pDC->DrawText(strItem, rcItem, uFormat);
  371. return;
  372. }
  373. if (rcItem.Width() <= cxEllipsis)
  374. {
  375. pDC->DrawText(strEllipsis, 3, rcItem, uFormat);
  376. return;
  377. }
  378. int nWidth = rcItem.Width() - cxEllipsis;
  379. int nResultLength = strItem.GetLength() * nWidth / cxItem;
  380. CString strResultLeft = strItem.Left(nResultLength - nResultLength / 2);
  381. CString strResultRight = strItem.Right(nResultLength / 2);
  382. while (GetPrefixTextExtent(pDC, strResultLeft, uFormat) + GetPrefixTextExtent(pDC, strResultRight, uFormat) < nWidth)
  383. {
  384. nResultLength++;
  385. strResultLeft = strItem.Left(nResultLength - nResultLength / 2);
  386. strResultRight = strItem.Right(nResultLength / 2);
  387. }
  388. while (GetPrefixTextExtent(pDC, strResultLeft, uFormat) + GetPrefixTextExtent(pDC, strResultRight, uFormat) > nWidth)
  389. {
  390. nResultLength--;
  391. strResultLeft = strItem.Left(nResultLength - nResultLength / 2);
  392. strResultRight = strItem.Right(nResultLength / 2);
  393. }
  394. pDC->DrawText(strResultLeft + strEllipsis + strResultRight, rcItem, uFormat);
  395. }
  396. void CXTPTabPaintManager::DrawFocusRect(CDC* pDC, CXTPTabManagerItem* /*pItem*/, CRect rcItem)
  397. {
  398. if (!m_bDrawFocusRect)
  399. return;
  400. rcItem.DeflateRect(3, 3, 3, 3);
  401. pDC->SetTextColor(0);
  402. pDC->SetBkColor(0xFFFFFF);
  403. pDC->DrawFocusRect(rcItem);
  404. }
  405. int CXTPTabPaintManager::DrawSingleButtonIconAndText(CDC* pDC, CXTPTabManagerItem* pItem, CRect rcItem, BOOL bDraw)
  406. {
  407. CXTPTabManager* pManager = pItem->GetTabManager();
  408. XTPTabLayoutStyle layout = pManager->GetLayout();
  409. BOOL bVertical = !pManager->IsHorizontalPosition();
  410. if (layout == xtpTabLayoutRotated) bVertical = !bVertical;
  411. CString strItem = pItem->GetCaption();
  412. CFont* pFont = m_bBoldSelected && pItem->IsSelected() && pManager->IsActive() ? GetBoldFont(bVertical) : GetFont(bVertical);
  413. CXTPFontDC fnt(pDC, pFont);
  414. CSize szIcon(m_szIcon);
  415. BOOL bDrawIcon = pManager->DrawIcon(pDC, 0, pItem, FALSE, szIcon);
  416. BOOL bDrawText = layout != xtpTabLayoutCompressed || pItem->IsSelected();
  417. int nNavigateButtonsLength = 0;
  418. if (bDrawText && pItem->GetNavigateButtons()->GetSize() > 0)
  419. {
  420. nNavigateButtonsLength = 0;
  421. for (int i = 0; i < (int)pItem->GetNavigateButtons()->GetSize(); i++)
  422. {
  423. CXTPTabManagerNavigateButton* pButton = pItem->GetNavigateButtons()->GetAt(i);
  424. if ((pButton->GetFlags() == xtpTabNavigateButtonAlways) ||
  425. ((pButton->GetFlags() == xtpTabNavigateButtonAutomatic) && pItem->IsSelected()))
  426. {
  427. CSize sz = pButton->GetSize();
  428. nNavigateButtonsLength += bVertical ? sz.cy : sz.cx;
  429. }
  430. }
  431. if (nNavigateButtonsLength > 0) nNavigateButtonsLength += 3;
  432. }
  433. if (bDraw)
  434. {
  435. if (nNavigateButtonsLength > 0)
  436. {
  437. m_pColorSet->SetTextColor(pDC, pItem);
  438. if (bVertical) rcItem.bottom -= 3; else rcItem.right -= 3;
  439. for (int i = (int)pItem->GetNavigateButtons()->GetSize() - 1; i >= 0; i--)
  440. {
  441. CXTPTabManagerNavigateButton* pButton = pItem->GetNavigateButtons()->GetAt(i);
  442. if ((pButton->GetFlags() == xtpTabNavigateButtonAlways) ||
  443. ((pButton->GetFlags() == xtpTabNavigateButtonAutomatic) && pItem->IsSelected()))
  444. {
  445. CSize szButton = pButton->GetSize();
  446. if (!bVertical)
  447. {
  448. pButton->SetRect(CRect(rcItem.right - szButton.cx,
  449. rcItem.CenterPoint().y + szButton.cy / 2 - szButton.cy, rcItem.right,
  450. rcItem.CenterPoint().y + szButton.cy / 2));
  451. rcItem.right -= szButton.cx;
  452. }
  453. else
  454. {
  455. pButton->SetRect(CRect(rcItem.CenterPoint().x - szButton.cx / 2,
  456. rcItem.bottom - szButton.cy, rcItem.CenterPoint().x - szButton.cx / 2 + szButton.cx, rcItem.bottom));
  457. rcItem.bottom -= szButton.cy;
  458. }
  459. pItem->GetNavigateButtons()->GetAt(i)->Draw(pDC);
  460. }
  461. }
  462. }
  463. m_pColorSet->SetTextColor(pDC, pItem);
  464. CRect rcFocus(rcItem);
  465. if (bVertical)
  466. {
  467. int nAvailLength = pItem->GetButtonLength() - pItem->GetContentLength();
  468. if (nAvailLength > 0)
  469. {
  470. rcItem.DeflateRect(0, nAvailLength / 2);
  471. }
  472. rcItem.top += m_rcButtonTextPadding.left + m_rcButtonMargin.left;
  473. if (pManager->GetPosition() == xtpTabPositionRight)
  474. rcItem.DeflateRect(m_rcButtonMargin.bottom, 0, m_rcButtonMargin.top, 0);
  475. else
  476. rcItem.DeflateRect(m_rcButtonMargin.top, 0, m_rcButtonMargin.bottom, 0);
  477. if (bDrawIcon)
  478. {
  479. CPoint pt(rcItem.CenterPoint().x - szIcon.cx/2, rcItem.top - 1);
  480. if (rcItem.Height() > szIcon.cy) pManager->DrawIcon(pDC, pt, pItem, TRUE, szIcon);
  481. rcItem.top += szIcon.cy + 2;
  482. }
  483. if (bDrawText && rcItem.bottom > rcItem.top + 8)
  484. {
  485. CSize szText = pDC->GetTextExtent(strItem);
  486. rcItem.left = rcItem.right - (rcItem.Width() - szText.cy - (pManager->GetPosition() == xtpTabPositionRight ? 1 : 0)) / 2;
  487. rcItem.right = rcItem.left + rcItem.Height();
  488. rcItem.bottom -= m_rcButtonMargin.right + max(0, m_rcButtonTextPadding.right - 4);
  489. if (!m_bDrawTextNoPrefix)
  490. StripMnemonics(strItem);
  491. if (m_bDrawTextPathEllipsis)
  492. {
  493. DrawTextPathEllipsis(pDC, strItem, rcItem, DT_SINGLELINE | DT_NOCLIP | DT_NOPREFIX);
  494. }
  495. else
  496. {
  497. pDC->DrawText(strItem, &rcItem, DT_SINGLELINE | DT_NOCLIP |
  498. DT_NOPREFIX | (m_bDrawTextEndEllipsis ? DT_END_ELLIPSIS : 0));
  499. }
  500. }
  501. }
  502. else
  503. {
  504. int nAvailLength = pItem->GetButtonLength() - pItem->GetContentLength();
  505. if (nAvailLength > 0)
  506. {
  507. rcItem.DeflateRect(nAvailLength / 2, 0);
  508. }
  509. rcItem.left += m_rcButtonTextPadding.left + m_rcButtonMargin.left;
  510. if (pManager->GetPosition() == xtpTabPositionBottom)
  511. rcItem.DeflateRect(0, m_rcButtonMargin.bottom, 0, m_rcButtonMargin.top);
  512. else
  513. rcItem.DeflateRect(0, m_rcButtonMargin.top, 0, m_rcButtonMargin.bottom);
  514. if (bDrawIcon)
  515. {
  516. CPoint pt(rcItem.left - 1, rcItem.CenterPoint().y - szIcon.cy/2);
  517. if (rcItem.Width() > szIcon.cx) pManager->DrawIcon(pDC, pt, pItem, TRUE, szIcon);
  518. rcItem.left += szIcon.cx + 2;
  519. }
  520. if (bDrawText && rcItem.right > rcItem.left)
  521. {
  522. rcItem.right -= m_rcButtonTextPadding.right + m_rcButtonMargin.right - (bDrawIcon ? 2 : 0);
  523. if (pItem->GetMarkupUIElement())
  524. {
  525. XTPMarkupSetDefaultFont(pItem->GetTabManager()->GetMarkupContext(), (HFONT)pFont->GetSafeHandle(), pDC->GetTextColor());
  526. CRect rcText(rcItem);
  527. if (m_nDrawTextFormat & DT_VCENTER)
  528. {
  529. CSize szText = XTPMarkupMeasureElement(pItem->GetMarkupUIElement());
  530. rcText.top = (rcText.top + rcText.bottom - szText.cy) / 2;
  531. rcText.bottom = rcText.top + szText.cy;
  532. }
  533. XTPMarkupRenderElement(pItem->GetMarkupUIElement(), pDC->GetSafeHdc(), rcText);
  534. }
  535. else if (m_bDrawTextPathEllipsis)
  536. {
  537. DrawTextPathEllipsis(pDC, strItem, rcItem, DT_SINGLELINE | m_nDrawTextFormat | (m_bDrawTextNoPrefix ? DT_NOPREFIX : 0));
  538. }
  539. else
  540. {
  541. if (m_bDrawTextHidePrefix)
  542. StripMnemonics(strItem);
  543. pDC->DrawText(strItem, rcItem, DT_SINGLELINE | m_nDrawTextFormat |
  544. (m_bDrawTextHidePrefix || m_bDrawTextNoPrefix ? DT_NOPREFIX : 0) | (m_bDrawTextEndEllipsis ? DT_END_ELLIPSIS : 0));
  545. }
  546. }
  547. }
  548. if (pItem->IsFocused())
  549. {
  550. DrawFocusRect(pDC, pItem, rcFocus);
  551. }
  552. return 0;
  553. }
  554. else
  555. {
  556. if (layout == xtpTabLayoutFixed)
  557. {
  558. return _GetButtonLength(m_nFixedTabWidth, m_nMinTabWidth, m_nMaxTabWidth);
  559. }
  560. if (layout == xtpTabLayoutCompressed)
  561. {
  562. if (!bDrawText)
  563. return _GetButtonLength(8 + (bVertical ? szIcon.cy : szIcon.cx), m_nMinTabWidth, m_nMaxTabWidth) ;
  564. CXTPFontDC fntItems(pDC, m_bBoldSelected && pManager->IsActive() ? GetBoldFont(bVertical) : GetFont(bVertical));
  565. int nLength = 0;
  566. for (int i = 0; i < pManager->GetItemCount(); i++)
  567. {
  568. CRect rcItemText(0, 0, 0, 0);
  569. pDC->DrawText(pManager->GetItem(i)->GetCaption(), rcItemText, DT_SINGLELINE | DT_CALCRECT | DT_NOCLIP | (m_bDrawTextNoPrefix ? DT_NOPREFIX : 0));
  570. nLength = max(nLength, rcItemText.Width());
  571. }
  572. return _GetButtonLength(nNavigateButtonsLength + nLength + m_rcButtonTextPadding.left + m_rcButtonTextPadding.right +
  573. (!bDrawIcon ? 0: bVertical ? szIcon.cy : szIcon.cx), m_nMinTabWidth, m_nMaxTabWidth);
  574. }
  575. CSize szText(0);
  576. if (pItem->GetMarkupUIElement())
  577. {
  578. XTPMarkupSetDefaultFont(pItem->GetTabManager()->GetMarkupContext(), (HFONT)pFont->GetSafeHandle(), pDC->GetTextColor());
  579. szText = XTPMarkupMeasureElement(pItem->GetMarkupUIElement());
  580. }
  581. else
  582. {
  583. pDC->DrawText(strItem, rcItem, DT_SINGLELINE | DT_CALCRECT | DT_NOCLIP | (m_bDrawTextNoPrefix ? DT_NOPREFIX : 0));
  584. szText = rcItem.Size();
  585. }
  586. return _GetButtonLength(nNavigateButtonsLength + szText.cx + m_rcButtonTextPadding.left + m_rcButtonTextPadding.right +
  587. (!bDrawIcon ? 0: bVertical ? szIcon.cy : szIcon.cx), m_nMinTabWidth, m_nMaxTabWidth);
  588. }
  589. }
  590. void CXTPTabPaintManager::AdjustClientRect(CXTPTabManager* pTabManager, CRect& rcClient)
  591. {
  592. if (pTabManager->IsDrawStaticFrame())
  593. CAppearanceSet::DeflateRectEx(rcClient, CRect(2, 1, 2, 2), pTabManager->GetPosition());
  594. if (pTabManager->GetItemCount() > 0)
  595. {
  596. m_pAppearanceSet->AdjustClientRect(pTabManager, rcClient);
  597. }
  598. }
  599. CRect CXTPTabPaintManager::RepositionNavigateButtons(CXTPTabManager* pTabManager, CRect rcClient)
  600. {
  601. CRect rcNavigateButtons = m_pAppearanceSet->GetHeaderRect(rcClient, pTabManager);
  602. if (pTabManager->IsHorizontalPosition())
  603. rcNavigateButtons.right -= 1;
  604. else
  605. rcNavigateButtons.bottom -= 1;
  606. for (int i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
  607. pTabManager->GetNavigateButton(i)->Reposition(rcNavigateButtons);
  608. return rcNavigateButtons;
  609. }
  610. void CXTPTabPaintManager::RepositionTabControl(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
  611. {
  612. pTabManager->m_rcHeaderRect.SetRectEmpty();
  613. pTabManager->m_rcClient = pTabManager->m_rcControl = rcClient;
  614. pTabManager->m_pRowIndexer->CreateIndexer(1);
  615. for (int i = 0; i < pTabManager->GetItemCount(); i++)
  616. {
  617. pTabManager->GetItem(i)->m_nItemRow = 0;
  618. }
  619. m_pAppearanceSet->RepositionTabControl(pTabManager, pDC, rcClient);
  620. AdjustClientRect(pTabManager, pTabManager->m_rcClient);
  621. }
  622. BOOL CXTPTabPaintManager::_CreateMultiRowIndexerBestFit(CXTPTabManager* pTabManager, int nWidth, int nRow, int nTotalLength)
  623. {
  624. const int nRowCount = pTabManager->GetRowCount();
  625. const int nLengthPerRow = !m_bMultiRowJustified ? nWidth : min(nTotalLength / (nRowCount - nRow), nWidth);
  626. CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();
  627. int x = 0;
  628. for (int i = pRowItems[nRow].nLastItem; i < pTabManager->GetItemCount(); i++)
  629. {
  630. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  631. int nLength = pItem->GetButtonLength();
  632. if (x + nLength > nLengthPerRow && x != 0 && nLength > 0)
  633. {
  634. if (nRow == nRowCount - 1)
  635. return FALSE;
  636. pRowItems[nRow + 1].nFirstItem = pRowItems[nRow + 1].nLastItem = i;
  637. if (_CreateMultiRowIndexerBestFit(pTabManager, nWidth, nRow + 1, nTotalLength - x))
  638. return TRUE;
  639. if (x + nLength > nWidth)
  640. return FALSE;
  641. }
  642. pRowItems[nRow].nLastItem = i;
  643. pItem->m_nItemRow = nRow;
  644. x += nLength;
  645. }
  646. return TRUE;
  647. }
  648. void CXTPTabPaintManager::CreateMultiRowIndexer(CXTPTabManager* pTabManager, CDC* pDC, int nWidth)
  649. {
  650. int x = 0;
  651. int nRowCount = 1;
  652. int i;
  653. int nTotalLength = 0;
  654. int nItemCount = pTabManager->GetItemCount();
  655. CXTPTabManagerItem* pSelectedItem = 0;
  656. for (i = 0; i < nItemCount; i++)
  657. {
  658. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  659. if (pItem->IsSelected())
  660. {
  661. pSelectedItem = pItem;
  662. }
  663. int nLength = pItem->m_nContentLength = pItem->m_nButtonLength =
  664. pItem->IsVisible() ? m_pAppearanceSet->GetButtonLength(pDC, pItem) : 0;
  665. if (x + nLength > nWidth && x != 0)
  666. {
  667. x = 0;
  668. nRowCount++;
  669. }
  670. x += nLength;
  671. nTotalLength += nLength;
  672. }
  673. CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->CreateIndexer(nRowCount);
  674. if (nRowCount == 1)
  675. return;
  676. pRowItems[0].nFirstItem = pRowItems[0].nLastItem = 0;
  677. VERIFY(_CreateMultiRowIndexerBestFit(pTabManager, nWidth, 0, nTotalLength));
  678. if (!m_bMultiRowFixedSelection && pSelectedItem)
  679. {
  680. int nSelectedRow = pSelectedItem->GetItemRow();
  681. CXTPTabManager::ROW_ITEMS selectedRow = pRowItems[nSelectedRow];
  682. pRowItems[nSelectedRow] = pRowItems[0];
  683. pRowItems[0] = selectedRow;
  684. }
  685. }
  686. void CXTPTabPaintManager::RepositionTabControlMultiRow(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
  687. {
  688. pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
  689. pTabManager->m_nHeaderOffset = 0;
  690. if (pTabManager->GetItemCount() == 0)
  691. return;
  692. CRect rcHeaderMargin = m_pAppearanceSet->GetHeaderMargin();
  693. int nButtonHeight = m_pAppearanceSet->GetButtonHeight(pTabManager);
  694. if (pTabManager->IsHorizontalPosition())
  695. {
  696. int nWidth = pTabManager->m_rcHeaderRect.Width() - (rcHeaderMargin.left + rcHeaderMargin.right);
  697. CreateMultiRowIndexer(pTabManager, pDC, nWidth);
  698. int nRowCount = pTabManager->GetRowCount();
  699. int nTop = 0;
  700. if (pTabManager->GetPosition() == xtpTabPositionBottom)
  701. {
  702. nTop = rcClient.bottom - (nButtonHeight * nRowCount + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
  703. - rcHeaderMargin.top;
  704. }
  705. else
  706. {
  707. nTop = rcClient.top +  (nButtonHeight * (nRowCount - 1) + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
  708. + rcHeaderMargin.top;
  709. }
  710. int nBottom = nTop + nButtonHeight;
  711. int nOffset = pTabManager->GetPosition() == xtpTabPositionBottom ?
  712. nButtonHeight + m_pAppearanceSet->m_nRowMargin: -(nButtonHeight + m_pAppearanceSet->m_nRowMargin);
  713. CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();
  714. int i;
  715. BOOL bSizeToFit = nRowCount > 1 && m_bMultiRowJustified;
  716. for (int nRow = 0; nRow < nRowCount; nRow++)
  717. {
  718. int nTotalLength = 0;
  719. int nItemInRow = pRowItems[nRow].nLastItem - pRowItems[nRow].nFirstItem + 1;
  720. int nFirstItem = pRowItems[nRow].nFirstItem;
  721. if (bSizeToFit)
  722. {
  723. for (i = 0; i < nItemInRow; i++)
  724. {
  725. nTotalLength += pTabManager->GetItem(nFirstItem + i)->GetButtonLength();
  726. }
  727. }
  728. int nTotalWidth = nWidth;
  729. int x = pTabManager->m_rcHeaderRect.left + rcHeaderMargin.left;
  730. for (i = 0; i < nItemInRow; i++)
  731. {
  732. CXTPTabManagerItem* pItem = pTabManager->GetItem(nFirstItem + i);
  733. ASSERT(pItem);
  734. if (!pItem)
  735. continue;
  736. int nButtonLength = pItem->m_nButtonLength;
  737. if (bSizeToFit)
  738. {
  739. int nLength = nButtonLength + (nTotalWidth - nTotalLength) / (nItemInRow - i);
  740. nTotalWidth -= nLength;
  741. nTotalLength -= nButtonLength;
  742. pItem->m_nButtonLength = nButtonLength = nLength;
  743. }
  744. pItem->SetRect(CRect(x, nTop, x + nButtonLength, nBottom));
  745. pItem->m_nItemRow = nRow;
  746. x += nButtonLength;
  747. }
  748. nTop += nOffset;
  749. nBottom += nOffset;
  750. }
  751. }
  752. else
  753. {
  754. int nWidth = pTabManager->m_rcHeaderRect.Height() - (rcHeaderMargin.left + rcHeaderMargin.right);
  755. CreateMultiRowIndexer(pTabManager, pDC, nWidth);
  756. int nRowCount = pTabManager->GetRowCount();
  757. int nLeft = 0;
  758. if (pTabManager->GetPosition() == xtpTabPositionRight)
  759. {
  760. nLeft = rcClient.right - (nButtonHeight * nRowCount + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
  761. - rcHeaderMargin.top;
  762. }
  763. else
  764. {
  765. nLeft = rcClient.left +  (nButtonHeight * (nRowCount - 1) + m_pAppearanceSet->m_nRowMargin * (nRowCount - 1))
  766. + rcHeaderMargin.top;
  767. }
  768. int nRight = nLeft + nButtonHeight;
  769. int nOffset = pTabManager->GetPosition() == xtpTabPositionRight ?
  770. nButtonHeight + m_pAppearanceSet->m_nRowMargin: -(nButtonHeight + m_pAppearanceSet->m_nRowMargin);
  771. CXTPTabManager::ROW_ITEMS* pRowItems = pTabManager->m_pRowIndexer->GetRowItems();
  772. int i;
  773. BOOL bSizeToFit = nRowCount > 1 && m_bMultiRowJustified;
  774. for (int nRow = 0; nRow < nRowCount; nRow++)
  775. {
  776. int nTotalLength = 0;
  777. int nItemInRow = pRowItems[nRow].nLastItem - pRowItems[nRow].nFirstItem + 1;
  778. int nFirstItem = pRowItems[nRow].nFirstItem;
  779. if (bSizeToFit)
  780. {
  781. for (i = 0; i < nItemInRow; i++)
  782. {
  783. nTotalLength += pTabManager->GetItem(nFirstItem + i)->GetButtonLength();
  784. }
  785. }
  786. int nTotalWidth = nWidth;
  787. int y = pTabManager->m_rcHeaderRect.top + rcHeaderMargin.left;
  788. for (i = 0; i < nItemInRow; i++)
  789. {
  790. CXTPTabManagerItem* pItem = pTabManager->GetItem(nFirstItem + i);
  791. ASSERT(pItem);
  792. if (!pItem)
  793. continue;
  794. int nButtonLength = pItem->m_nButtonLength;
  795. if (bSizeToFit)
  796. {
  797. int nLength = nButtonLength + (nTotalWidth - nTotalLength) / (nItemInRow - i);
  798. nTotalWidth -= nLength;
  799. nTotalLength -= nButtonLength;
  800. pItem->m_nButtonLength = nButtonLength = nLength;
  801. }
  802. pItem->SetRect(CRect(nLeft, y, nRight, y + nButtonLength));
  803. pItem->m_nItemRow = nRow;
  804. y += nButtonLength;
  805. }
  806. nLeft += nOffset;
  807. nRight += nOffset;
  808. }
  809. }
  810. pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
  811. }
  812. void CXTPTabPaintManager::RepositionTabControlEx(CXTPTabManager* pTabManager, CDC* pDC, CRect rcClient)
  813. {
  814. if (pTabManager->IsDrawStaticFrame())
  815. {
  816. CAppearanceSet::DeflateRectEx(rcClient, CRect(2, 1, 2, 2), pTabManager->GetPosition());
  817. }
  818. CAppearanceSet::DeflateRectEx(rcClient, m_rcControlMargin, pTabManager->GetPosition());
  819. int i;
  820. if (!m_bShowTabs)
  821. {
  822. pTabManager->m_rcHeaderRect.SetRectEmpty();
  823. for (i = 0; i < pTabManager->GetItemCount(); i++)
  824. {
  825. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  826. pItem->SetRect(CRect(0, 0, 0, 0));
  827. }
  828. for (i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
  829. pTabManager->GetNavigateButton(i)->SetRect(CRect(0, 0, 0, 0));
  830. return;
  831. }
  832. if (pTabManager->GetLayout() == xtpTabLayoutMultiRow)
  833. {
  834. RepositionTabControlMultiRow(pTabManager, pDC, rcClient);
  835. return;
  836. }
  837. for (i = 0; i < pTabManager->GetItemCount(); i++)
  838. {
  839. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  840. pItem->m_nButtonLength = pItem->m_nContentLength =
  841. pItem->IsVisible() ? m_pAppearanceSet->GetButtonLength(pDC, pItem) : 0;
  842. if (pItem->IsVisible())
  843. pItem->m_nButtonLength += m_nButtonExtraLength;
  844. }
  845. pTabManager->m_rcHeaderRect = m_pAppearanceSet->GetHeaderRect(rcClient, pTabManager);
  846. if (pTabManager->GetItemCount() == 0)
  847. {
  848. RepositionNavigateButtons(pTabManager, rcClient);
  849. return;
  850. }
  851. CRect rcHeaderMargin = m_pAppearanceSet->GetHeaderMargin();
  852. int nButtonHeight = m_pAppearanceSet->GetButtonHeight(pTabManager);
  853. if (pTabManager->IsHorizontalPosition())
  854. {
  855. int nTop = rcClient.top + rcHeaderMargin.top;
  856. if (pTabManager->GetPosition() == xtpTabPositionBottom)
  857. {
  858. nTop = rcClient.bottom - nButtonHeight - rcHeaderMargin.top;
  859. }
  860. int nBottom = nTop + nButtonHeight;
  861. if (pTabManager->GetLayout() == xtpTabLayoutSizeToFit)
  862. {
  863. int nWidth = rcClient.Width() - (rcHeaderMargin.right + rcHeaderMargin.left);
  864. for (i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
  865. pTabManager->GetNavigateButton(i)->AdjustWidth(nWidth);
  866. SizeToFit(pTabManager, nWidth);
  867. }
  868. pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
  869. if (pTabManager->m_nHeaderOffset < 0)
  870. {
  871. int nLength = pTabManager->GetItemsLength();
  872. int nNavigateButtonsWidth = pTabManager->m_rcHeaderRect.Width() - rcHeaderMargin.left - rcHeaderMargin.right;
  873. if (nLength + pTabManager->m_nHeaderOffset < nNavigateButtonsWidth)
  874. {
  875. pTabManager->m_nHeaderOffset = min(0, nNavigateButtonsWidth - nLength);
  876. pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
  877. }
  878. }
  879. int x = pTabManager->m_rcHeaderRect.left + rcHeaderMargin.left + pTabManager->GetHeaderOffset();
  880. if (pTabManager->GetLayout() == xtpTabLayoutRotated)
  881. {
  882. if (pTabManager->GetPosition() == xtpTabPositionTop)
  883. {
  884. nBottom = pTabManager->m_rcHeaderRect.bottom - rcHeaderMargin.bottom;
  885. }
  886. else
  887. {
  888. nTop = pTabManager->m_rcHeaderRect.top + rcHeaderMargin.bottom;
  889. }
  890. for (i = 0; i < pTabManager->GetItemCount(); i++)
  891. {
  892. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  893. if (pTabManager->GetPosition() == xtpTabPositionTop)
  894. {
  895. pItem->SetRect(CRect(x, nBottom - pItem->m_nButtonLength, x + nButtonHeight, nBottom));
  896. }
  897. else
  898. {
  899. pItem->SetRect(CRect(x, nTop, x + nButtonHeight, nTop + pItem->m_nButtonLength));
  900. }
  901. x += nButtonHeight;
  902. }
  903. }
  904. else
  905. {
  906. for (i = 0; i < pTabManager->GetItemCount(); i++)
  907. {
  908. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  909. pItem->SetRect(CRect(x, nTop, x + pItem->m_nButtonLength, nBottom));
  910. x += pItem->m_nButtonLength;
  911. }
  912. }
  913. }
  914. else
  915. {
  916. int nLeft = rcClient.left + rcHeaderMargin.top;
  917. if (pTabManager->GetPosition() == xtpTabPositionRight)
  918. {
  919. nLeft = rcClient.right - nButtonHeight - rcHeaderMargin.top;
  920. }
  921. int nRight = nLeft + nButtonHeight;
  922. if (pTabManager->GetLayout() == xtpTabLayoutSizeToFit)
  923. {
  924. int nWidth = rcClient.Height() - (rcHeaderMargin.right + rcHeaderMargin.left);
  925. for (i = pTabManager->GetNavigateButtonCount() - 1; i >= 0; i--)
  926. pTabManager->GetNavigateButton(i)->AdjustWidth(nWidth);
  927. SizeToFit(pTabManager, nWidth);
  928. }
  929. pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
  930. if (pTabManager->m_nHeaderOffset < 0)
  931. {
  932. int nLength = pTabManager->GetItemsLength();
  933. int nNavigateButtonsWidth = pTabManager->m_rcHeaderRect.Height() - rcHeaderMargin.left - rcHeaderMargin.right;
  934. if (nLength + pTabManager->m_nHeaderOffset < nNavigateButtonsWidth)
  935. {
  936. pTabManager->m_nHeaderOffset = min(0, nNavigateButtonsWidth - nLength);
  937. pTabManager->m_rcHeaderRect = RepositionNavigateButtons(pTabManager, rcClient);
  938. }
  939. }
  940. int y = pTabManager->m_rcHeaderRect.top + rcHeaderMargin.left + pTabManager->GetHeaderOffset();
  941. if (pTabManager->GetLayout() == xtpTabLayoutRotated)
  942. {
  943. if (pTabManager->GetPosition() == xtpTabPositionLeft)
  944. {
  945. nRight = pTabManager->m_rcHeaderRect.right - rcHeaderMargin.bottom;
  946. }
  947. else
  948. {
  949. nLeft = pTabManager->m_rcHeaderRect.left + rcHeaderMargin.bottom;
  950. }
  951. for (i = 0; i < pTabManager->GetItemCount(); i++)
  952. {
  953. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  954. if (pTabManager->GetPosition() == xtpTabPositionLeft)
  955. {
  956. pItem->SetRect(CRect(nRight - pItem->m_nButtonLength, y, nRight, y + nButtonHeight));
  957. }
  958. else
  959. {
  960. pItem->SetRect(CRect(nLeft, y, nLeft + pItem->m_nButtonLength, y + nButtonHeight));
  961. }
  962. y += nButtonHeight;
  963. }
  964. }
  965. else
  966. {
  967. for (i = 0; i < pTabManager->GetItemCount(); i++)
  968. {
  969. CXTPTabManagerItem* pItem = pTabManager->GetItem(i);
  970. pItem->SetRect(CRect(nLeft, y, nRight, y + pItem->m_nButtonLength));
  971. y += pItem->m_nButtonLength;
  972. }
  973. }
  974. }
  975. }
  976. void CXTPTabPaintManager::EnsureVisible(CXTPTabManager* pTabManager, CXTPTabManagerItem* pItem)
  977. {
  978. CRect rcHeader = pTabManager->m_rcHeaderRect;
  979. CRect rcItem = pItem->GetRect();
  980. if (rcHeader.IsRectEmpty() || rcItem.IsRectEmpty())
  981. return;
  982. if (GetLayout() == xtpTabLayoutSizeToFit)
  983. return;
  984. if (pTabManager->IsHorizontalPosition())
  985. {
  986. if (rcItem.left < rcHeader.left)
  987. {
  988. pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.left + rcHeader.left + m_pAppearanceSet->GetHeaderMargin().left);
  989. }
  990. else if (rcItem.right > rcHeader.right)
  991. {
  992. pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.right + rcHeader.right - 2);
  993. }
  994. }
  995. else
  996. {
  997. if (rcItem.top < rcHeader.top)
  998. {
  999. pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.top + rcHeader.top + m_pAppearanceSet->GetHeaderMargin().left);
  1000. }
  1001. else if (rcItem.bottom > rcHeader.bottom)
  1002. {
  1003. pTabManager->SetHeaderOffset(pTabManager->GetHeaderOffset() - rcItem.bottom + rcHeader.bottom - 2);
  1004. }
  1005. }
  1006. }
  1007. int _cdecl CXTPTabPaintManager::_SizeToFitCompare(const void *arg1, const void *arg2)
  1008. {
  1009. int nLength1 = (*((CXTPTabManagerItem**)arg1))->GetButtonLength();
  1010. int nLength2 = (*((CXTPTabManagerItem**)arg2))->GetButtonLength();
  1011. return nLength1 - nLength2;
  1012. };
  1013. void CXTPTabPaintManager::SizeToFit(CXTPTabManager* pTabManager, int nWidth)
  1014. {
  1015. int nLength = pTabManager->GetItemsLength();
  1016. int nCount = pTabManager->GetItemCount();
  1017. if (nCount == 0)
  1018. return;
  1019. if (nWidth < nLength)
  1020. {
  1021. if (nCount == 1)
  1022. pTabManager->GetItem(0)->m_nButtonLength = nWidth;
  1023. else
  1024. {
  1025. CXTPTabManagerItem** pItems = new CXTPTabManagerItem*[nCount];
  1026. if (!pItems)
  1027. return;
  1028. for (int c = 0; c < nCount; c++)
  1029. {
  1030. pItems[c] = pTabManager->GetItem(c);
  1031. }
  1032. qsort(pItems, nCount, sizeof(CXTPTabManagerItem*), _SizeToFitCompare);
  1033. for (int i = 0; i < nCount; i++)
  1034. {
  1035. int nButtonLength = pItems[i]->m_nButtonLength;
  1036. if (nButtonLength * (nCount - i) >= nWidth)
  1037. {
  1038. for (int j = i; j < nCount; j++)
  1039. {
  1040. nButtonLength = nWidth / (nCount - j);
  1041. pItems[j]->m_nButtonLength = nButtonLength;
  1042. nWidth -= nButtonLength;
  1043. }
  1044. break;
  1045. }
  1046. nWidth -= nButtonLength;
  1047. }
  1048. delete[] pItems;
  1049. }
  1050. }
  1051. }
  1052. XTPTabAppearanceStyle CXTPTabPaintManager::GetAppearance() const
  1053. {
  1054. return m_tabAppearance;
  1055. }
  1056. XTPTabColorStyle CXTPTabPaintManager::GetColor() const
  1057. {
  1058. return m_tabColor;
  1059. }
  1060. void CXTPTabPaintManager::SetPosition(XTPTabPosition tabPosition)
  1061. {
  1062. m_tabPosition = tabPosition;
  1063. OnPropertyChanged();
  1064. }
  1065. void CXTPTabPaintManager::SetLayout(XTPTabLayoutStyle tabLayout)
  1066. {
  1067. m_tabLayout = tabLayout;
  1068. OnPropertyChanged();
  1069. }
  1070. XTPTabPosition CXTPTabPaintManager::GetPosition() const
  1071. {
  1072. return m_tabPosition;
  1073. }
  1074. XTPTabLayoutStyle CXTPTabPaintManager::GetLayout() const
  1075. {
  1076. return m_tabLayout;
  1077. }
  1078. void CXTPTabPaintManager::OnPropertyChanged()
  1079. {
  1080. for (int i = 0; i < m_arrObservers.GetSize(); i++)
  1081. {
  1082. m_arrObservers[i]->OnPropertyChanged();
  1083. }
  1084. }
  1085. void CXTPTabPaintManager::AddObserver(CXTPTabManagerAtom* pObserver)
  1086. {
  1087. for (int i = 0; i < m_arrObservers.GetSize(); i++)
  1088. {
  1089. if (m_arrObservers[i] == pObserver)
  1090. return;
  1091. }
  1092. m_arrObservers.Add(pObserver);
  1093. }
  1094. //////////////////////////////////////////////////////////////////////////