duilib List控件,横向滚动时列表项不移动或者显示错位的bug的修复
转载请说明出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42264673
关于这个bug的修复我之前写过一篇博客,连接为:http://blog.csdn.net/zhuhongshu/article/details/40622705
本以为已经修复好,但是后来有网友私聊我,反映到还存在bug。原本已经解决的bug如下:
1.当List出现滚动条后,拖动滚动条,这时ListContainElementUI控件内部的子控件跟随Header自动调节位置会有差错,明显看到偏移不正确
2.当List出现滚动条后,拖动滚动条到任意位置让ListContainElementUI控件内部的子控件位移,然后最小化窗体再恢复。发现本应该发生偏移的子控件这时却跑到了原位。
新的bug是:当List出现滚动条后,拖动滚动条到任意位置让ListContainElementUI控件内部的子控件位移,然后最大化窗体,就发现列表项的偏移不正确,再次恢复后的列表项位置也有问题。
尝试从ListContainElementUI控件的SetPos函数解决问题,发现总是无法十全十美,没办法既顾及到最小化又顾及最大化,同时还要计算偏移。尝试修复几个小时都不成功。
回头想想,前面的三个问题的根源都在于,List容器先重新计算列表项的位置,再去计算表头的位置。而列表项要根据表头的位置去自适应。之前的做法一直是在列表项调整位置时去尝试计算表头的位置,而这样做的致命缺点就是,当最小化和最大化后表头的位置会有突然的变化而知道计算失误。
换个思路,只要让列表先计算表头的位置,再去计算列表项的位置,自然就没问题了。······,感觉以前的思路好傻。
通过这个思路可以简单有效的修复所有bug,之前的文章的修复过程全部作废,bug的修复过程如下:
修复过程:
一、List控件的SetPos函数源码如下:
void CListUI::SetPos(RECT rc)
{
CVerticalLayoutUI::SetPos(rc); if( m_pHeader == NULL ) return;
// Determine general list information and the size of header columns
m_ListInfo.nColumns = MIN(m_pHeader->GetCount(), UILIST_MAX_COLUMNS);
// The header/columns may or may not be visible at runtime. In either case
// we should determine the correct dimensions... if( !m_pHeader->IsVisible() ) {
for( int it = 0; it < m_pHeader->GetCount(); it++ ) {
static_cast<CControlUI*>(m_pHeader->GetItemAt(it))->SetInternVisible(true);
}
m_pHeader->SetPos(CDuiRect(rc.left, 0, rc.right, 0));
}
int iOffset = m_pList->GetScrollPos().cx;
for( int i = 0; i < m_ListInfo.nColumns; i++ ) {
CControlUI* pControl = static_cast<CControlUI*>(m_pHeader->GetItemAt(i));
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) continue; RECT rcPos = pControl->GetPos();
if( iOffset > 0 ) {
rcPos.left -= iOffset;
rcPos.right -= iOffset;
pControl->SetPos(rcPos);
}
m_ListInfo.rcColumn[i] = pControl->GetPos();
}
if( !m_pHeader->IsVisible() ) {
for( int it = 0; it < m_pHeader->GetCount(); it++ ) {
static_cast<CControlUI*>(m_pHeader->GetItemAt(it))->SetInternVisible(false);
}
} }
代码里首先调用父类的SetPos函数,在父类的SetPos里面会初始化表头和列表项的位置,然后可以看到List的SetPos根据滚动条的位置重新调整了表头的位置。
首先要在函数的最后加入这句代码来重新计算列表项的位置:
m_pList->SetPos(m_pList->GetPos());
二、当横向滚动条控件移动时,会通知父控件已经移动来让父控件做出响应。也就是列表滚动条控件会调用List的SetScrollPos函数,而List控件的SetScrollPos函数会调用CListBodyUI控件的SetScrollPos函数,CListBodyUI控件是所有列表项的容器。在CListBodyUI控件的SetScrollPos函数里,先计算了列表项的位置,后计算表头的位置。所以修改对应代码的位置就可以了,修改后的代码如下:
void CListBodyUI::SetScrollPos(SIZE szPos)
{
int cx = 0;
int cy = 0;
if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) {
int iLastScrollPos = m_pVerticalScrollBar->GetScrollPos();
m_pVerticalScrollBar->SetScrollPos(szPos.cy);
cy = m_pVerticalScrollBar->GetScrollPos() - iLastScrollPos;
} if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) {
int iLastScrollPos = m_pHorizontalScrollBar->GetScrollPos();
m_pHorizontalScrollBar->SetScrollPos(szPos.cx);
cx = m_pHorizontalScrollBar->GetScrollPos() - iLastScrollPos;
} if( cx == 0 && cy == 0 ) return; if( cx != 0 && m_pOwner ) {
CListHeaderUI* pHeader = m_pOwner->GetHeader();
if( pHeader == NULL ) return;
TListInfoUI* pInfo = m_pOwner->GetListInfo();
pInfo->nColumns = MIN(pHeader->GetCount(), UILIST_MAX_COLUMNS); if( !pHeader->IsVisible() ) {
for( int it = 0; it < pHeader->GetCount(); it++ ) {
static_cast<CControlUI*>(pHeader->GetItemAt(it))->SetInternVisible(true);
}
}
for( int i = 0; i < pInfo->nColumns; i++ ) {
CControlUI* pControl = static_cast<CControlUI*>(pHeader->GetItemAt(i));
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) continue; RECT rcPos = pControl->GetPos();
rcPos.left -= cx;
rcPos.right -= cx;
pControl->SetPos(rcPos);
pInfo->rcColumn[i] = pControl->GetPos();
}
if( !pHeader->IsVisible() ) {
for( int it = 0; it < pHeader->GetCount(); it++ ) {
static_cast<CControlUI*>(pHeader->GetItemAt(it))->SetInternVisible(false);
}
}
} RECT rcPos;
for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) {
CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) continue; rcPos = pControl->GetPos();
rcPos.left -= cx;
rcPos.right -= cx;
rcPos.top -= cy;
rcPos.bottom -= cy;
pControl->SetPos(rcPos);
} Invalidate(); }
三、当表头的位置计算好后,最后修改ListContainElementUI的SetPos函数去计算他的子控件的位置,代码比以前的版本简单了很多:
void CListContainerElementUI::SetPos(RECT rc)
{
CHorizontalLayoutUI::SetPos(rc);
if( m_pOwner == NULL ) return; CListUI* pList = static_cast<CListUI*>(m_pOwner);
if (pList == NULL) return; CListHeaderUI *pHeader = pList->GetHeader();
if (pHeader == NULL || !pHeader->IsVisible())
return; int nCount = m_items.GetSize();
for (int i = 0; i < nCount; i++)
{
CControlUI *pListItem = static_cast<CControlUI*>(m_items[i]); CControlUI *pHeaderItem = pHeader->GetItemAt(i);
if (pHeaderItem == NULL)
return; RECT rcHeaderItem = pHeaderItem->GetPos();
if (pListItem != NULL && !(rcHeaderItem.left ==0 && rcHeaderItem.right ==0) )
{
RECT rt = pListItem->GetPos();
rt.left =rcHeaderItem.left;
rt.right = rcHeaderItem.right;
pListItem->SetPos(rt);
} } }
总结:
有这个修复代码后,以前的文章的修复代码就作废了。
如果要修改ListContainElementUI的朋友可以根据我上面给出的代码修改,也可以直接下载我自己的Duilib库。
我的Duilib库代码下载地址:点击打开链接
Redrain 2014.12.30
duilib List控件,横向滚动时列表项不移动或者显示错位的bug的修复的更多相关文章
- duilib List控件,横向滚动时列表项不移动或者移动错位的bug的修复
转载请说明出处,谢谢~~ 这篇博客已经作废,只是留作记录,新的bug修复博客地址:http://blog.csdn.net/zhuhongshu/article/details/42264673 之前 ...
- duilib combo控件,当鼠标滚动时下拉列表自动关闭的bug的修复
转载请说明出处,谢谢~~ 群里有朋友提到了使用Combo控件时,当下拉列表出现,此时鼠标滚轮滚动,下拉列表就自动消失了.我看了一下源码,这个bug的修复很简单. CComboUI控件被单击时创建CCo ...
- iOS 9应用开发教程之使用开关滑块控件以及滚动部署视图
iOS 9应用开发教程之使用开关滑块控件以及滚动部署视图 使用ios9中的开关.滑块控件 开关和滑块也是用于和用户进行交互的控件.本节将主要讲解这两种控件. ios9开关 开关控件常用来控制某个功能的 ...
- Winform禁止容器内控件获得焦点时改变容器显示范围坐标
在Winform中当容器的可视高度无法显示所有控件并且容器的AutoScroll属性设置为True的情况下,但点击容器内某个未显示完整的控件时,会出现容器的滚动条自动下滚的情况. 这是由于控件获得焦点 ...
- 五种情况下会刷新控件状态(刷新所有子FWinControls的显示)——从DFM读取数据时、新增加子控件时、重新创建当前控件的句柄时、设置父控件时、显示状态被改变时
五种情况下会刷新控件状态(刷新控件状态才能刷新所有子FWinControls的显示): 在TWinControls.PaintControls中,对所有FWinControls只是重绘了边框,而没有整 ...
- DS控件库 Win7链接列表框的仿Windows开始菜单样式
Win7链接列表框是依照Windows7的开始菜单开发的,同时进行了属性和功能的扩展. 效果图 项属性 控件属性 控件主要事件 点击项(Sender As Win7链接列表框, Itm As 链接项, ...
- 关于使用UniForm以其他控件为Parent时应该注意的问题
关于使用UniForm以其他控件为Parent时应该注意的问题: 1,不能在其他组件的oncreate,onbeforeshow,onshow等事件中来生成这样的uniform,否则其上的组件不能显示 ...
- WPF控件获得焦点时去除虚线框
原文:WPF控件获得焦点时去除虚线框 <Setter Property="FocusVisualStyle" Value="{x:Null}" />
- DevExpress控件使用经验总结- GridView列表行号显示操作
DevExpress是一个比较有名的界面控件套件,提供了一系列的界面控件套件的DotNet界面控件.本文主要介绍我在使用DevExpress控件过程中,遇到或者发现的一些问题解决方案,或者也可以所示一 ...
随机推荐
- POJ3176——Cow Bowling(动态规划)
Cow Bowling DescriptionThe cows don't use actual bowling balls when they go bowling. They each take ...
- 10位IT领袖给应届毕业生的10条忠告
10位IT领袖给应届毕业生的10条忠告,在走向独立和自主的伟大征程中,吸取他们的经验. 在毕业生们迈出象牙塔之时,他们应该听从哪些人的建议?在走向独立和自主的伟大征程中,他们该吸取哪些教训?听一听各领 ...
- ArcGIS Engine中的8种数据访问
数据是GIS的基础, 访问数据也是进行任何复杂的空间分析及空间可视化表达的前提.ArcGIS支持的数据格式比较丰富,对不同的数据格式支持的程度也有很大差异.本文主要介绍一下以下八种数据格式在ArcGI ...
- [原]poj-2524(裸并查集)
题目链接: http://poj.org/problem?id=2524 题意: n个人,m对人宗教相同,输出一共有多少个不同的宗教. 代码如下: #include<iostream> # ...
- POJ-2718 Smallest Difference
http://poj.org/problem?id=2718 从一些数里面选择一个子集组成一个数,余下的数组成另外一个数,(数不能以0开头)问两个数的差的绝对值最小是多少! 不管是奇数还是偶数,要想绝 ...
- MXF素材文件交换格式深入研究
MXF素材文件交换格式深入研究 2012-09-03 | 访问次数:262 | 新闻来源:电科网 [摘要]DCI规定数字电影需采用MXF封装音视频等节目素材内容.为了深 ...
- HDU 4658 Integer Partition(整数拆分)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4658 题意:给出n.k.求n的拆分方案数.要求拆分中每个数不超过k. i64 f[N]; void i ...
- 在AChartEngine上绘图,手指标记当前位置
最近要做一个绘图项目,需要在ACE折线图上再绘出一条红标记当前坐标,经过这几天研究,可以给大家分享一下了.先上效果图吧! 代码里的注释还是比较清楚,就不作说明了. package com.exampl ...
- ssh传输出现encountered 1 errors during the transfer解决办法
以下方法简单排序,从简单到复杂: 法一:在SSH Secure File Transfer(上传文件那个),打开“Operation”菜单,打开“File Transfer Mode”子菜单,再选择“ ...
- Balsamiq Mockups简单介绍(UI草图绘制工具)
什么是Balsamiq Mockups Balsamiq Mockups出自加利福尼亚州的Balsamiq工作室,创始人Peldi在2008年6月推出了这款手绘风格的产品原型设计工具,并广受好评.2年 ...