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控件过程中,遇到或者发现的一些问题解决方案,或者也可以所示一 ...
随机推荐
- ubuntu12.10升级至14.04
之前执行apt-get 不管是什么软件或apt-get update都会遇到fail to fetch http://us.archive.ubuntu.com quantal-updates/mai ...
- leetcode:Intersection of Two Linked Lists(两个链表的交叉点)
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- Searching in a Radius using Postgres[Marked]
Searching in a Radius using Postgres Creating a GEO application has never been easier. You can have ...
- java.lang.ClassNotFoundException
在项目的properties中的Java Build Path里将Order and Export里的类库勾选上.
- android 开发如何做内存优化
不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露.其实如果我 们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造 ...
- window-messager(消息框)
所有的消息框都是异步的.用户可以在交互消息之后使用回调函数去处理结果或做一些自己需要处理的事情. 一.alert(警告框) <script type="text/javascript& ...
- xmlWriter 以UTF-8格式写xml问题
dom4j中的XMLWriter提供以下几种构造方法: XMLWriter() XMLWriter(OutputFormat format) XMLWriter(OutputStream out) X ...
- HDU 1950 Bridging signals
那么一大篇的题目描述还真是吓人. 仔细一读其实就是一个LIS,还无任何变形. 刚刚学会了个二分优化的DP,1A无压力. //#define LOCAL #include <iostream> ...
- ASP.NET vs MVC vs WebForms
许多ASP.NET开发人员开始接触MVC认为MVC与ASP.NET完全没有关系,是一个全新的Web开发,事实上ASP.NET是创建WEB应用的框架而MVC是能够用更好的方法来组织并管理代码的一种更高级 ...
- BZOJ 1724 切割木板
合并果子. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm& ...