|
@@ -64,131 +64,116 @@ namespace DuiLib
|
|
|
CControlUI::SetPos(rc, bNeedInvalidate);
|
|
CControlUI::SetPos(rc, bNeedInvalidate);
|
|
|
rc = m_rcItem;
|
|
rc = m_rcItem;
|
|
|
|
|
|
|
|
|
|
+ // 内边距调整
|
|
|
RECT rcInset = GetInset();
|
|
RECT rcInset = GetInset();
|
|
|
- // Adjust for inset
|
|
|
|
|
rc.left += rcInset.left;
|
|
rc.left += rcInset.left;
|
|
|
rc.top += rcInset.top;
|
|
rc.top += rcInset.top;
|
|
|
rc.right -= rcInset.right;
|
|
rc.right -= rcInset.right;
|
|
|
rc.bottom -= rcInset.bottom;
|
|
rc.bottom -= rcInset.bottom;
|
|
|
|
|
|
|
|
- if( m_items.GetSize() == 0) {
|
|
|
|
|
|
|
+ if (m_items.GetSize() == 0)
|
|
|
|
|
+ {
|
|
|
ProcessScrollBar(rc, 0, 0);
|
|
ProcessScrollBar(rc, 0, 0);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) rc.right -= m_pVerticalScrollBar->GetFixedWidth();
|
|
|
|
|
- if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
|
|
|
|
|
|
|
+ // 预留滚动条空间
|
|
|
|
|
+ if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())
|
|
|
|
|
+ rc.right -= m_pVerticalScrollBar->GetFixedWidth();
|
|
|
|
|
+ if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())
|
|
|
|
|
+ rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
|
|
|
|
|
|
|
|
|
|
+ // ========== 核心:固定子控件尺寸(不再动态计算) ==========
|
|
|
SIZE szItem = GetItemSize();
|
|
SIZE szItem = GetItemSize();
|
|
|
- // Position the elements
|
|
|
|
|
- if( szItem.cx > 0 ) m_nColumns = (rc.right - rc.left) / szItem.cx;
|
|
|
|
|
- if( m_nColumns == 0 ) m_nColumns = 1;
|
|
|
|
|
|
|
+ // 确保ItemSize有效,避免除0
|
|
|
|
|
+ if (szItem.cx <= 0) szItem.cx = 100; // 兜底默认宽度
|
|
|
|
|
+ if (szItem.cy <= 0) szItem.cy = 100; // 兜底默认高度
|
|
|
|
|
|
|
|
- int cyNeeded = 0;
|
|
|
|
|
- int cxWidth = szItem.cx + m_iChildPadding; // 固定列宽
|
|
|
|
|
|
|
+ // ========== 核心:固定列数计算(基于固定宽度+水平间距) ==========
|
|
|
|
|
+ int cxItemWithPadding = szItem.cx + m_iChildPadding; // 单个子控件占宽(含水平间距)
|
|
|
|
|
+ m_nColumns = (rc.right - rc.left) / cxItemWithPadding;
|
|
|
|
|
+ if (m_nColumns <= 0) m_nColumns = 1;
|
|
|
|
|
|
|
|
|
|
+ // 滚动条兼容处理
|
|
|
if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())
|
|
if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())
|
|
|
{
|
|
{
|
|
|
- // 考虑滚动条的情况
|
|
|
|
|
int nTotalWidth = rc.right - rc.left + m_pHorizontalScrollBar->GetScrollRange();
|
|
int nTotalWidth = rc.right - rc.left + m_pHorizontalScrollBar->GetScrollRange();
|
|
|
- m_nColumns = nTotalWidth / cxWidth;
|
|
|
|
|
- if (m_nColumns == 0) m_nColumns = 1;
|
|
|
|
|
|
|
+ m_nColumns = nTotalWidth / cxItemWithPadding;
|
|
|
|
|
+ if (m_nColumns <= 0) m_nColumns = 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- int cyHeight = 0;
|
|
|
|
|
|
|
+ // 布局初始化
|
|
|
|
|
+ int cyNeeded = 0;
|
|
|
int iCount = 0;
|
|
int iCount = 0;
|
|
|
POINT ptTile = { rc.left, rc.top };
|
|
POINT ptTile = { rc.left, rc.top };
|
|
|
- if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 垂直滚动条偏移
|
|
|
|
|
+ if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())
|
|
|
ptTile.y -= m_pVerticalScrollBar->GetScrollPos();
|
|
ptTile.y -= m_pVerticalScrollBar->GetScrollPos();
|
|
|
- }
|
|
|
|
|
|
|
+ // 水平滚动条偏移
|
|
|
int iPosX = rc.left;
|
|
int iPosX = rc.left;
|
|
|
- if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {
|
|
|
|
|
|
|
+ if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())
|
|
|
|
|
+ {
|
|
|
iPosX -= m_pHorizontalScrollBar->GetScrollPos();
|
|
iPosX -= m_pHorizontalScrollBar->GetScrollPos();
|
|
|
ptTile.x = iPosX;
|
|
ptTile.x = iPosX;
|
|
|
}
|
|
}
|
|
|
- for( int it1 = 0; it1 < m_items.GetSize(); it1++ ) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // ========== 遍历子控件:固定宽高+固定间距布局 ==========
|
|
|
|
|
+ for (int it1 = 0; it1 < m_items.GetSize(); it1++)
|
|
|
|
|
+ {
|
|
|
CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);
|
|
CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);
|
|
|
- if( !pControl->IsVisible() ) continue;
|
|
|
|
|
- if( pControl->IsFloat() ) {
|
|
|
|
|
|
|
+ if (!pControl->IsVisible()) continue;
|
|
|
|
|
+ if (pControl->IsFloat())
|
|
|
|
|
+ {
|
|
|
SetFloatPos(it1);
|
|
SetFloatPos(it1);
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Determine size
|
|
|
|
|
- RECT rcTile = { ptTile.x, ptTile.y, ptTile.x + cxWidth, ptTile.y };
|
|
|
|
|
- if( (iCount % m_nColumns) == 0 )
|
|
|
|
|
|
|
+ // ========== 核心1:固定子控件位置(无动态尺寸计算) ==========
|
|
|
|
|
+ RECT rcTile = {
|
|
|
|
|
+ ptTile.x, // 左
|
|
|
|
|
+ ptTile.y, // 上
|
|
|
|
|
+ ptTile.x + szItem.cx, // 右(固定宽度)
|
|
|
|
|
+ ptTile.y + szItem.cy // 下(固定高度)
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 忽略子控件自身padding,强制使用固定尺寸(如需保留padding可删除此段)
|
|
|
|
|
+ // RECT rcPadding = pControl->GetPadding();
|
|
|
|
|
+ // rcTile.left += rcPadding.left;
|
|
|
|
|
+ // rcTile.right -= rcPadding.right;
|
|
|
|
|
+ // rcTile.top += rcPadding.top;
|
|
|
|
|
+ // rcTile.bottom -= rcPadding.bottom;
|
|
|
|
|
+
|
|
|
|
|
+ // ========== 核心2:强制子控件尺寸为ItemSize(覆盖所有动态计算) ==========
|
|
|
|
|
+ RECT rcPos = {
|
|
|
|
|
+ rcTile.left,
|
|
|
|
|
+ rcTile.top,
|
|
|
|
|
+ rcTile.left + szItem.cx,
|
|
|
|
|
+ rcTile.top + szItem.cy
|
|
|
|
|
+ };
|
|
|
|
|
+ pControl->SetPos(rcPos, bNeedInvalidate);
|
|
|
|
|
+
|
|
|
|
|
+ // ========== 核心3:固定间距更新坐标 ==========
|
|
|
|
|
+ iCount++;
|
|
|
|
|
+ // 换行:重置X坐标,Y坐标 += 固定高度 + 垂直间距
|
|
|
|
|
+ if (iCount % m_nColumns == 0)
|
|
|
{
|
|
{
|
|
|
- int iIndex = iCount;
|
|
|
|
|
- for( int it2 = it1; it2 < m_items.GetSize(); it2++ ) {
|
|
|
|
|
- CControlUI* pLineControl = static_cast<CControlUI*>(m_items[it2]);
|
|
|
|
|
- if( !pLineControl->IsVisible() ) continue;
|
|
|
|
|
- if( pLineControl->IsFloat() ) continue;
|
|
|
|
|
-
|
|
|
|
|
- RECT rcPadding = pLineControl->GetPadding();
|
|
|
|
|
- SIZE szAvailable = { rcTile.right - rcTile.left - rcPadding.left - rcPadding.right, 9999 };
|
|
|
|
|
- if( iIndex == iCount || (iIndex + 1) % m_nColumns == 0 ) {
|
|
|
|
|
- szAvailable.cx -= m_iChildPadding / 2;
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
- szAvailable.cx -= m_iChildPadding;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if( szAvailable.cx < pControl->GetMinWidth() ) szAvailable.cx = pControl->GetMinWidth();
|
|
|
|
|
- if( szAvailable.cx > pControl->GetMaxWidth() ) szAvailable.cx = pControl->GetMaxWidth();
|
|
|
|
|
-
|
|
|
|
|
- SIZE szTile = pLineControl->EstimateSize(szAvailable);
|
|
|
|
|
- if( szTile.cx < pControl->GetMinWidth() ) szTile.cx = pControl->GetMinWidth();
|
|
|
|
|
- if( szTile.cx > pControl->GetMaxWidth() ) szTile.cx = pControl->GetMaxWidth();
|
|
|
|
|
- if( szTile.cy < pControl->GetMinHeight() ) szTile.cy = pControl->GetMinHeight();
|
|
|
|
|
- if( szTile.cy > pControl->GetMaxHeight() ) szTile.cy = pControl->GetMaxHeight();
|
|
|
|
|
-
|
|
|
|
|
- cyHeight = MAX(cyHeight, szTile.cy + rcPadding.top + rcPadding.bottom);
|
|
|
|
|
- if( (++iIndex % m_nColumns) == 0) break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- RECT rcPadding = pControl->GetPadding();
|
|
|
|
|
-
|
|
|
|
|
- rcTile.left += rcPadding.left + m_iChildPadding / 2;
|
|
|
|
|
- rcTile.right -= rcPadding.right + m_iChildPadding / 2;
|
|
|
|
|
- if( (iCount % m_nColumns) == 0 ) {
|
|
|
|
|
- rcTile.left -= m_iChildPadding / 2;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if( ( (iCount + 1) % m_nColumns) == 0 ) {
|
|
|
|
|
- rcTile.right += m_iChildPadding / 2;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Set position
|
|
|
|
|
- rcTile.top = ptTile.y + rcPadding.top;
|
|
|
|
|
- rcTile.bottom = ptTile.y + cyHeight;
|
|
|
|
|
-
|
|
|
|
|
- SIZE szAvailable = { rcTile.right - rcTile.left, rcTile.bottom - rcTile.top };
|
|
|
|
|
- SIZE szTile = pControl->EstimateSize(szAvailable);
|
|
|
|
|
- if( szTile.cx == 0 ) szTile.cx = szAvailable.cx;
|
|
|
|
|
- if( szTile.cy == 0 ) szTile.cy = szAvailable.cy;
|
|
|
|
|
- if( szTile.cx < pControl->GetMinWidth() ) szTile.cx = pControl->GetMinWidth();
|
|
|
|
|
- if( szTile.cx > pControl->GetMaxWidth() ) szTile.cx = pControl->GetMaxWidth();
|
|
|
|
|
- if( szTile.cy < pControl->GetMinHeight() ) szTile.cy = pControl->GetMinHeight();
|
|
|
|
|
- if( szTile.cy > pControl->GetMaxHeight() ) szTile.cy = pControl->GetMaxHeight();
|
|
|
|
|
- RECT rcPos = {(rcTile.left + rcTile.right - szTile.cx) / 2, (rcTile.top + rcTile.bottom - szTile.cy) / 2,
|
|
|
|
|
- (rcTile.left + rcTile.right - szTile.cx) / 2 + szTile.cx, (rcTile.top + rcTile.bottom - szTile.cy) / 2 + szTile.cy};
|
|
|
|
|
- pControl->SetPos(rcPos);
|
|
|
|
|
-
|
|
|
|
|
- if( (++iCount % m_nColumns) == 0 ) {
|
|
|
|
|
ptTile.x = iPosX;
|
|
ptTile.x = iPosX;
|
|
|
- ptTile.y += cyHeight + m_iChildPadding;
|
|
|
|
|
- cyHeight = 0;
|
|
|
|
|
|
|
+ ptTile.y += szItem.cy + m_iChildPadding; // 垂直间距 = m_iChildPadding
|
|
|
}
|
|
}
|
|
|
- else {
|
|
|
|
|
- ptTile.x += cxWidth;
|
|
|
|
|
|
|
+ // 不换行:X坐标 += 固定宽度 + 水平间距
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ ptTile.x += szItem.cx + m_iChildPadding; // 水平间距 = m_iChildPadding
|
|
|
}
|
|
}
|
|
|
- cyNeeded = rcTile.bottom - rc.top;
|
|
|
|
|
- if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) cyNeeded += m_pVerticalScrollBar->GetScrollPos();
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 更新总高度(用于滚动条)
|
|
|
|
|
+ cyNeeded = ptTile.y - rc.top + szItem.cy;
|
|
|
|
|
+ if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())
|
|
|
|
|
+ cyNeeded += m_pVerticalScrollBar->GetScrollPos();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Process the scrollbar
|
|
|
|
|
|
|
+ // 处理滚动条
|
|
|
ProcessScrollBar(rc, 0, cyNeeded);
|
|
ProcessScrollBar(rc, 0, cyNeeded);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|