Duilib中的TitleLayoutUI默认是竖向滚动展示,以Troy的DuiLib_Ultimate为例,如图显示
现在想做成横向滑动显示,如下图:
下面说一下修改的方法,其实很简单,就是将CTileLayoutUI::SetPos函数中的所有的x改成y,y改成x;top和bottom改成left和right,left和right改成top和bottom;Hor改成Ver,Ver改成Hor就可以了,因为源码已经写的很好了。
下面是修改后的代码:
//头文件
#pragma once
class CMyTileLayoutUI :public CTileLayoutUI {
public:
CMyTileLayoutUI();
virtual ~CMyTileLayoutUI();
virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
virtual void SetPos(RECT rc, bool bNeedInvalidate = true);
void SetHSLayout(bool bHSLayout);//设置横线滑动
protected:
virtual void SetPos_hor(RECT rc, bool bNeedInvalidate = true);
protected:
int m_nRows;//行数
bool m_bHSLayout;//默认false
};
//源文件
#include "stdafx.h"
#include "UIMyTileLayout.h"
CMyTileLayoutUI::CMyTileLayoutUI():m_nRows(1),m_bHSLayout(false) {}
CMyTileLayoutUI::~CMyTileLayoutUI() {}
void CMyTileLayoutUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) {
if (_tcscmp(pstrName, _T("hslayout")) == 0)
SetHSLayout(_tcscmp(pstrValue, _T("true")) == 0);
else CTileLayoutUI::SetAttribute(pstrName, pstrValue);
}
void CMyTileLayoutUI::SetHSLayout(bool bHSLayout) {
m_bHSLayout = bHSLayout;
}
void CMyTileLayoutUI::SetPos(RECT rc, bool bNeedInvalidate/* = true*/) {
if (m_bHSLayout) {
SetPos_hor(rc, bNeedInvalidate);
}
else {
CTileLayoutUI::SetPos(rc, bNeedInvalidate);
}
}
void CMyTileLayoutUI::SetPos_hor(RECT rc, bool bNeedInvalidate/* = true*/){
CControlUI::SetPos(rc, bNeedInvalidate);
rc = m_rcItem;
// Adjust for inset
rc.left += m_rcInset.left;
rc.top += m_rcInset.top;
rc.right -= m_rcInset.right;
rc.bottom -= m_rcInset.bottom;
if (m_items.GetSize() == 0) {
ProcessScrollBar(rc, 0, 0);
return;
}
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();
// Position the elements
if (szItem.cy > 0) m_nRows = (rc.bottom - rc.top) / szItem.cy;//求行数
if (m_nRows == 0) m_nRows = 1;
int cxNeeded = 0;
int cyHeight = (rc.bottom - rc.top) / m_nRows;
if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())
cyHeight = (rc.bottom - rc.top + m_pVerticalScrollBar->GetScrollRange()) / m_nRows;
int cxWidth = 0;
int iCount = 0;
POINT ptTile = { rc.left, rc.top };
if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible()) {
ptTile.x -= m_pHorizontalScrollBar->GetScrollPos();
}
int iPosY = rc.top;
if (m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible()) {
iPosY -= m_pVerticalScrollBar->GetScrollPos();
ptTile.y = iPosY;
}
for (int it1 = 0; it1 < m_items.GetSize(); it1++) {
CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);
if (!pControl->IsVisible()) continue;
if (pControl->IsFloat()) {
SetFloatPos(it1);
continue;
}
// Determine size
RECT rcTile = { ptTile.x, ptTile.y, ptTile.x, ptTile.y + cyHeight };
if ((iCount % m_nRows) == 0)
{
int iIndex = iCount;
for (int it2 = it1; it2 < m_items.GetSize(); it2++) { //一列item中找到width最大的那个,并记录width,以该值作为这一列的宽度
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 };
SIZE szAvailable = { 9999, rcTile.bottom - rcTile.top - rcPadding.top - rcPadding.bottom };
if (iIndex == iCount || (iIndex + 1) % m_nRows == 0) {
szAvailable.cy -= m_iChildPadding / 2;
}
else {
szAvailable.cy -= m_iChildPadding;
}
if (szAvailable.cy < pControl->GetMinHeight()) szAvailable.cy = pControl->GetMinHeight();
if (szAvailable.cy > pControl->GetMaxHeight()) szAvailable.cy = pControl->GetMaxHeight();
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();
cxWidth = MAX(cxWidth, szTile.cx + rcPadding.left + rcPadding.right);
if ((++iIndex % m_nRows) == 0) break;
}
}
RECT rcPadding = pControl->GetPadding();
rcTile.top += rcPadding.top + m_iChildPadding / 2;
rcTile.bottom -= rcPadding.bottom + m_iChildPadding / 2;
if ((iCount % m_nRows) == 0) {
rcTile.top -= m_iChildPadding / 2;
}
if (((iCount + 1) % m_nRows) == 0) {
rcTile.bottom += m_iChildPadding / 2;
}
// Set position
rcTile.left = ptTile.x + rcPadding.left;
rcTile.right = ptTile.x + cxWidth;
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_nRows) == 0) {
ptTile.y = iPosY;
ptTile.x += cxWidth + m_iChildPadding;
cxWidth = 0;
}
else {
ptTile.y += cyHeight;
}
cxNeeded = rcTile.right - rc.left;
if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible()) cxNeeded += m_pHorizontalScrollBar->GetScrollPos();
}
ProcessScrollBar(rc, cxNeeded, 0);
}