duilib中的V和H布局中滚动条问题
来源:互联网 发布:python语言就业前景 编辑:程序博客网 时间:2024/05/16 01:06
<?xml version="1.0" encoding="utf-8"?><Window size="300,200" caption="0,0,300,20"><HorizontalLayout name="aaaa" bkcolor="#FFEEEEEE" ><VerticalLayout name="xxxxxx" float="true" pos="50,20,250,195" hscrollbar="true" vscrollbar="true" sepheight="4" ><Label name="child1" text="text1" float="false" pos="0,0,300,200" bordercolor="#FFEE00EE" bkcolor="#FF0000EE" textcolor="#FF010101"/><Label name="child2" text="text2" float="false" pos="0,0,200,200" bordercolor="#FFEE00EE" bkcolor="#FF0000EE" textcolor="#FF01FF01"/></VerticalLayout></HorizontalLayout></Window>
这是一个窗口,它包含一个竖的布局,显示出来初始状态是这样的:
在布局中,2个子控件所需要的长和宽,比布局本身的大小要大,所以需要2个滚动条来拉动显示。
我们可以看到横竖两个滚动条。
不过,我们拉动滚动条,却不能完全展示子控件。如下图:
虽然横向滚动条拉到了最右边,但Label控件child1的右边没有展示出来。
检查代码,发现CVerticalLayoutUI的SetPos方法如下:
void CVerticalLayoutUI::SetPos(RECT rc){...省略若干代码// Process the scrollbarProcessScrollBar(rc, 0, cyNeeded);}
在最后面,调用了基类CContainerUI的ProcessScrollBar方法,来设置滚动条信息,ProcessScrollBar函数的第二个参数是设置横向滚动条信息,第三个参数是竖向滚动条。此时设置横向的参数为0,竖向的是cyNeeded。显然,这里忽略了横向的,所以在竖向布局VerticalLayout中,横向滚动条不能正常显示。
在CVerticalLayoutUI::SetPos中,所有涉及到cyNeeded的代码如下:
int cyNeeded = 0;int cyExpand = 0;if( nAdjustables > 0 ) cyExpand = MAX(0, (szAvailable.cy - cyFixed) / nAdjustables);// Position the elementsSIZE szRemaining = szAvailable;int iPosY = rc.top;if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) {iPosY -= m_pVerticalScrollBar->GetScrollPos();}int iPosX = rc.left;if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {iPosX -= m_pHorizontalScrollBar->GetScrollPos();}int iAdjustable = 0;int cyFixedRemaining = cyFixed;for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) {CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);if( !pControl->IsVisible() ) continue;if( pControl->IsFloat() ) {SetFloatPos(it2);continue;}RECT rcPadding = pControl->GetPadding();szRemaining.cy -= rcPadding.top;SIZE sz = pControl->EstimateSize(szRemaining);if( sz.cy == 0 ) {iAdjustable++;sz.cy = cyExpand;// Distribute remaining to last element (usually round-off left-overs)if( iAdjustable == nAdjustables ) {sz.cy = MAX(0, szRemaining.cy - rcPadding.bottom - cyFixedRemaining);} if( sz.cy < pControl->GetMinHeight() ) sz.cy = pControl->GetMinHeight();if( sz.cy > pControl->GetMaxHeight() ) sz.cy = pControl->GetMaxHeight();}else {if( sz.cy < pControl->GetMinHeight() ) sz.cy = pControl->GetMinHeight();if( sz.cy > pControl->GetMaxHeight() ) sz.cy = pControl->GetMaxHeight();cyFixedRemaining -= sz.cy;}sz.cx = pControl->GetFixedWidth();if( sz.cx == 0 ) sz.cx = szAvailable.cx - rcPadding.left - rcPadding.right;if( sz.cx < 0 ) sz.cx = 0;if( sz.cx < pControl->GetMinWidth() ) sz.cx = pControl->GetMinWidth();if( sz.cx > pControl->GetMaxWidth() ) sz.cx = pControl->GetMaxWidth();RECT rcCtrl = { iPosX + rcPadding.left, iPosY + rcPadding.top, iPosX + rcPadding.left + sz.cx, iPosY + sz.cy + rcPadding.top + rcPadding.bottom };pControl->SetPos(rcCtrl);iPosY += sz.cy + m_iChildPadding + rcPadding.top + rcPadding.bottom;cyNeeded += sz.cy + rcPadding.top + rcPadding.bottom;szRemaining.cy -= sz.cy + m_iChildPadding + rcPadding.bottom;}cyNeeded += (nEstimateNum - 1) * m_iChildPadding;在for循环里,会统计所有非float子控件的高度
在 cyNeeded += sz.cy + rcPadding.top + rcPadding.bottom; 里,sz.cy是1个子控件的高度,而rcPadding = pControl->GetPadding(); 是控件的padding属性,也就是外边距。
最后yNeeded += (nEstimateNum - 1) * m_iChildPadding; m_iChildPadding是布局的childpadding属性,也就是子控件之间的额外距离。
我们可以仿照cyNeeded的计算方式,来算出cxNeeded。因为是竖向布局,所以 cyNeeded += sz.cy 这里是累加,但是横向值,应该取最宽的控件的值,
所以for循环中的代码应该是这样:
int tmp = sz.cx + rcPadding.left + rcPadding.right;
cxNeeded = (tmp > cxNeeded) ? tmp: cxNeeded;
最后cxNeeded += (nEstimateNum - 1) * m_iChildPadding;
此时通过对代码的了解,可以得知:布局在计算容量面积时,只计算非float类型的子控件,忽略了float类型的子控件。
算出了布局的宽度后,就应用起来
修改原来的代码为:ProcessScrollBar(rc, cxNeeded, cyNeeded);
改完后,发现问题依然。于是,检查了下ProcessScrollBar的代码,如下
void CContainerUI::ProcessScrollBar(RECT rc, int cxRequired, int cyRequired){if( m_pHorizontalScrollBar != NULL && m_pHorizontalScrollBar->IsVisible() ) {RECT rcScrollBarPos = { rc.left, rc.bottom, rc.right, rc.bottom + m_pHorizontalScrollBar->GetFixedHeight()};m_pHorizontalScrollBar->SetPos(rcScrollBarPos);}if( m_pVerticalScrollBar == NULL ) return;if( cyRequired > rc.bottom - rc.top && !m_pVerticalScrollBar->IsVisible() ) {m_pVerticalScrollBar->SetVisible(true);m_pVerticalScrollBar->SetScrollRange(cyRequired - (rc.bottom - rc.top));m_pVerticalScrollBar->SetScrollPos(0);m_bScrollProcess = true;SetPos(m_rcItem);m_bScrollProcess = false;return;}// No scrollbar requiredif( !m_pVerticalScrollBar->IsVisible() ) return;// Scroll not needed anymore?int cyScroll = cyRequired - (rc.bottom - rc.top);if( cyScroll <= 0 && !m_bScrollProcess) {m_pVerticalScrollBar->SetVisible(false);m_pVerticalScrollBar->SetScrollPos(0);m_pVerticalScrollBar->SetScrollRange(0);SetPos(m_rcItem);}else{RECT rcScrollBarPos = { rc.right, rc.top, rc.right + m_pVerticalScrollBar->GetFixedWidth(), rc.bottom };m_pVerticalScrollBar->SetPos(rcScrollBarPos);if( m_pVerticalScrollBar->GetScrollRange() != cyScroll ) {int iScrollPos = m_pVerticalScrollBar->GetScrollPos();m_pVerticalScrollBar->SetScrollRange(::abs(cyScroll));if( m_pVerticalScrollBar->GetScrollRange() == 0 ) {m_pVerticalScrollBar->SetVisible(false);m_pVerticalScrollBar->SetScrollPos(0);}if( iScrollPos > m_pVerticalScrollBar->GetScrollPos() ) {SetPos(m_rcItem);}}}}很明显,cxRequired根本没有用到。
对于横向滚动条,只使用了这3行代码:
if( m_pHorizontalScrollBar != NULL && m_pHorizontalScrollBar->IsVisible() ) {RECT rcScrollBarPos = { rc.left, rc.bottom, rc.right, rc.bottom + m_pHorizontalScrollBar->GetFixedHeight()};m_pHorizontalScrollBar->SetPos(rcScrollBarPos);}于是,我们需要仿照设置竖向滚动条的方式,来设置横向滚动条:
void CContainerUI::ProcessScrollBar(RECT rc, int cxRequired, int cyRequired){while(m_pHorizontalScrollBar){if (cxRequired > rc.right - rc.left && !m_pHorizontalScrollBar->IsVisible()){m_pHorizontalScrollBar->SetVisible(true);m_pHorizontalScrollBar->SetScrollRange(cxRequired - (rc.right - rc.left));m_pHorizontalScrollBar->SetScrollPos(0);m_bScrollProcess = true;SetPos(m_rcItem);m_bScrollProcess = false;break;}if( !m_pHorizontalScrollBar->IsVisible() ) break;int cxScroll = cxRequired - (rc.right - rc.left);if (cxScroll <= 0 && !m_bScrollProcess){m_pHorizontalScrollBar->SetVisible(false);m_pHorizontalScrollBar->SetScrollPos(0);m_pHorizontalScrollBar->SetScrollRange(0);SetPos(m_rcItem);}else{RECT rcScrollBarPos = { rc.left, rc.bottom, rc.right, rc.bottom + m_pHorizontalScrollBar->GetFixedHeight() };m_pHorizontalScrollBar->SetPos(rcScrollBarPos);if( m_pHorizontalScrollBar->GetScrollRange() != cxScroll ) {int iScrollPos = m_pHorizontalScrollBar->GetScrollPos();m_pHorizontalScrollBar->SetScrollRange(::abs(cxScroll));if( m_pHorizontalScrollBar->GetScrollRange() == 0 ) {m_pHorizontalScrollBar->SetVisible(false);m_pHorizontalScrollBar->SetScrollPos(0);}if( iScrollPos > m_pHorizontalScrollBar->GetScrollPos() ) {SetPos(m_rcItem);}}}break;}while(m_pVerticalScrollBar){if( cyRequired > rc.bottom - rc.top && !m_pVerticalScrollBar->IsVisible() ) {m_pVerticalScrollBar->SetVisible(true);m_pVerticalScrollBar->SetScrollRange(cyRequired - (rc.bottom - rc.top));m_pVerticalScrollBar->SetScrollPos(0);m_bScrollProcess = true;SetPos(m_rcItem);m_bScrollProcess = false;break;}// No scrollbar requiredif( !m_pVerticalScrollBar->IsVisible() ) break;// Scroll not needed anymore?int cyScroll = cyRequired - (rc.bottom - rc.top);if( cyScroll <= 0 && !m_bScrollProcess) {m_pVerticalScrollBar->SetVisible(false);m_pVerticalScrollBar->SetScrollPos(0);m_pVerticalScrollBar->SetScrollRange(0);SetPos(m_rcItem);}else{RECT rcScrollBarPos = { rc.right, rc.top, rc.right + m_pVerticalScrollBar->GetFixedWidth(), rc.bottom };m_pVerticalScrollBar->SetPos(rcScrollBarPos);if( m_pVerticalScrollBar->GetScrollRange() != cyScroll ) {int iScrollPos = m_pVerticalScrollBar->GetScrollPos();m_pVerticalScrollBar->SetScrollRange(::abs(cyScroll));if( m_pVerticalScrollBar->GetScrollRange() == 0 ) {m_pVerticalScrollBar->SetVisible(false);m_pVerticalScrollBar->SetScrollPos(0);}if( iScrollPos > m_pVerticalScrollBar->GetScrollPos() ) {SetPos(m_rcItem);}}}break;}}
看看效果
可以看到控件child1的右边框。
HorizontalLayout也有同样的问题,可类似修改。
- duilib中的V和H布局中滚动条问题
- duilib中的V和H布局中滚动条问题
- duilib 滚动条不能拖动 问题处理
- DuiLib : 在CListUI中得到滚动条滚动通知
- Duilib 中滚动条自动滚动到底的方法
- Duilib 中滚动条自动滚动到底的方法
- EXT TABPANEL嵌套的布局和滚动条问题
- duilib的Combo控件滚动条不显示的问题
- duilib问题解决:滚动条不见了
- duilib combo 滚动条不起作用
- CFormView中的滚动条问题
- CFormView中的滚动条问题
- VS2005中滚动条问题
- DuiLib界面库滚动条拖动注意事项
- duilib 的IE浏览器控件去边框和去滚动条的代码
- android中在布局中添加滚动条
- MFC LISTBOX滚动条(垂直滚动条和水平滚动条)问题
- Div绝对布局和相对布局 And 不同层调出滚动条 And 滚动条滚动事件
- 第十二周项目三 用递归方法求解(返回第n个Fibnacci数)
- C语言中变量的作用域与存储类型
- 用二叉树实现表达式中缀式变后缀式并求值
- 身份证号码验证
- C/C++中的内存分配机制
- duilib中的V和H布局中滚动条问题
- UVA 10714
- 手把手教你用matlab生成STM32官方IIR滤波器的系数(三)
- UVA10128 - Queue(dp)
- BZOJ 1251 序列终结者 Splay
- Zxing和QR CODE 生成与解析二维码实例(带logo篇)
- Wildcard Matching
- jsp-简单标签及案例
- 循环-10. 求序列前N项和