UITileLayout.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "StdAfx.h"
  2. #include "UITileLayout.h"
  3. namespace DuiLib
  4. {
  5. IMPLEMENT_DUICONTROL(CTileLayoutUI)
  6. CTileLayoutUI::CTileLayoutUI() : m_nColumns(1)
  7. {
  8. m_szItem.cx = m_szItem.cy = 0;
  9. }
  10. LPCTSTR CTileLayoutUI::GetClass() const
  11. {
  12. return _T("TileLayoutUI");
  13. }
  14. LPVOID CTileLayoutUI::GetInterface(LPCTSTR pstrName)
  15. {
  16. if( _tcsicmp(pstrName, DUI_CTR_TILELAYOUT) == 0 ) return static_cast<CTileLayoutUI*>(this);
  17. return CContainerUI::GetInterface(pstrName);
  18. }
  19. SIZE CTileLayoutUI::GetItemSize() const
  20. {
  21. if(m_pManager != NULL) return m_pManager->GetDPIObj()->Scale(m_szItem);
  22. return m_szItem;
  23. }
  24. void CTileLayoutUI::SetItemSize(SIZE szItem)
  25. {
  26. if( m_szItem.cx != szItem.cx || m_szItem.cy != szItem.cy ) {
  27. m_szItem = szItem;
  28. NeedUpdate();
  29. }
  30. }
  31. int CTileLayoutUI::GetColumns() const
  32. {
  33. return m_nColumns;
  34. }
  35. void CTileLayoutUI::SetColumns(int nCols)
  36. {
  37. if( nCols <= 0 ) return;
  38. m_nColumns = nCols;
  39. NeedUpdate();
  40. }
  41. void CTileLayoutUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
  42. {
  43. if( _tcsicmp(pstrName, _T("itemsize")) == 0 ) {
  44. SIZE szItem = { 0 };
  45. LPTSTR pstr = NULL;
  46. szItem.cx = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
  47. szItem.cy = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  48. SetItemSize(szItem);
  49. }
  50. else if( _tcsicmp(pstrName, _T("columns")) == 0 ) SetColumns(_ttoi(pstrValue));
  51. else CContainerUI::SetAttribute(pstrName, pstrValue);
  52. }
  53. void CTileLayoutUI::SetPos(RECT rc, bool bNeedInvalidate)
  54. {
  55. CControlUI::SetPos(rc, bNeedInvalidate);
  56. rc = m_rcItem;
  57. // 内边距调整
  58. RECT rcInset = GetInset();
  59. rc.left += rcInset.left;
  60. rc.top += rcInset.top;
  61. rc.right -= rcInset.right;
  62. rc.bottom -= rcInset.bottom;
  63. if (m_items.GetSize() == 0)
  64. {
  65. ProcessScrollBar(rc, 0, 0);
  66. return;
  67. }
  68. // 预留滚动条空间
  69. if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())
  70. rc.right -= m_pVerticalScrollBar->GetFixedWidth();
  71. if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())
  72. rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
  73. SIZE szItem = GetItemSize();
  74. if (szItem.cx <= 0) szItem.cx = 100;
  75. if (szItem.cy <= 0) szItem.cy = 100;
  76. int cxItemWithPadding = szItem.cx + m_iChildPadding;
  77. m_nColumns = (rc.right - rc.left) / cxItemWithPadding;
  78. if (m_nColumns <= 0) m_nColumns = 1;
  79. if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())
  80. {
  81. int nTotalWidth = rc.right - rc.left + m_pHorizontalScrollBar->GetScrollRange();
  82. m_nColumns = nTotalWidth / cxItemWithPadding;
  83. if (m_nColumns <= 0) m_nColumns = 1;
  84. }
  85. int cyNeeded = 0;
  86. int iCount = 0;
  87. int nVisibleCount = 0;
  88. POINT ptTile = { rc.left, rc.top };
  89. if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())
  90. ptTile.y -= m_pVerticalScrollBar->GetScrollPos();
  91. int iPosX = rc.left;
  92. if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())
  93. {
  94. iPosX -= m_pHorizontalScrollBar->GetScrollPos();
  95. ptTile.x = iPosX;
  96. }
  97. for (int it1 = 0; it1 < m_items.GetSize(); it1++)
  98. {
  99. CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);
  100. if (!pControl->IsVisible()) continue;
  101. if (pControl->IsFloat())
  102. {
  103. SetFloatPos(it1);
  104. continue;
  105. }
  106. nVisibleCount++;
  107. RECT rcTile = {
  108. ptTile.x,
  109. ptTile.y,
  110. ptTile.x + szItem.cx,
  111. ptTile.y + szItem.cy
  112. };
  113. RECT rcPos = {
  114. rcTile.left,
  115. rcTile.top,
  116. rcTile.left + szItem.cx,
  117. rcTile.top + szItem.cy
  118. };
  119. pControl->SetPos(rcPos, bNeedInvalidate);
  120. iCount++;
  121. if (iCount % m_nColumns == 0)
  122. {
  123. ptTile.x = iPosX;
  124. ptTile.y += szItem.cy + m_iChildPadding;
  125. }
  126. else
  127. {
  128. ptTile.x += szItem.cx + m_iChildPadding;
  129. }
  130. }
  131. // 修正1:按“实际行数”计算内容高度,避免最后一个元素正好换行时多算一行
  132. if (nVisibleCount > 0)
  133. {
  134. int nRows = (nVisibleCount - 1) / m_nColumns + 1;
  135. cyNeeded = nRows * szItem.cy + (nRows - 1) * m_iChildPadding;
  136. }
  137. else
  138. {
  139. cyNeeded = 0;
  140. }
  141. // 修正2:滚动中的内容总高度需要补回当前滚动偏移
  142. if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())
  143. cyNeeded += m_pVerticalScrollBar->GetScrollPos();
  144. ProcessScrollBar(rc, 0, cyNeeded);
  145. }
  146. }