转载请说明出处,谢谢~~: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的修复的更多相关文章

  1. duilib List控件,横向滚动时列表项不移动或者移动错位的bug的修复

    转载请说明出处,谢谢~~ 这篇博客已经作废,只是留作记录,新的bug修复博客地址:http://blog.csdn.net/zhuhongshu/article/details/42264673 之前 ...

  2. duilib combo控件,当鼠标滚动时下拉列表自动关闭的bug的修复

    转载请说明出处,谢谢~~ 群里有朋友提到了使用Combo控件时,当下拉列表出现,此时鼠标滚轮滚动,下拉列表就自动消失了.我看了一下源码,这个bug的修复很简单. CComboUI控件被单击时创建CCo ...

  3. iOS 9应用开发教程之使用开关滑块控件以及滚动部署视图

    iOS 9应用开发教程之使用开关滑块控件以及滚动部署视图 使用ios9中的开关.滑块控件 开关和滑块也是用于和用户进行交互的控件.本节将主要讲解这两种控件. ios9开关 开关控件常用来控制某个功能的 ...

  4. Winform禁止容器内控件获得焦点时改变容器显示范围坐标

    在Winform中当容器的可视高度无法显示所有控件并且容器的AutoScroll属性设置为True的情况下,但点击容器内某个未显示完整的控件时,会出现容器的滚动条自动下滚的情况. 这是由于控件获得焦点 ...

  5. 五种情况下会刷新控件状态(刷新所有子FWinControls的显示)——从DFM读取数据时、新增加子控件时、重新创建当前控件的句柄时、设置父控件时、显示状态被改变时

    五种情况下会刷新控件状态(刷新控件状态才能刷新所有子FWinControls的显示): 在TWinControls.PaintControls中,对所有FWinControls只是重绘了边框,而没有整 ...

  6. DS控件库 Win7链接列表框的仿Windows开始菜单样式

    Win7链接列表框是依照Windows7的开始菜单开发的,同时进行了属性和功能的扩展. 效果图 项属性 控件属性 控件主要事件 点击项(Sender As Win7链接列表框, Itm As 链接项, ...

  7. 关于使用UniForm以其他控件为Parent时应该注意的问题

    关于使用UniForm以其他控件为Parent时应该注意的问题: 1,不能在其他组件的oncreate,onbeforeshow,onshow等事件中来生成这样的uniform,否则其上的组件不能显示 ...

  8. WPF控件获得焦点时去除虚线框

    原文:WPF控件获得焦点时去除虚线框 <Setter Property="FocusVisualStyle" Value="{x:Null}" />

  9. DevExpress控件使用经验总结- GridView列表行号显示操作

    DevExpress是一个比较有名的界面控件套件,提供了一系列的界面控件套件的DotNet界面控件.本文主要介绍我在使用DevExpress控件过程中,遇到或者发现的一些问题解决方案,或者也可以所示一 ...

随机推荐

  1. struts2与struts1整合,Unable to load configuration. - interceptor-ref ... struts.xml

    struts.xml中为了与struts1的MVC模式整合,需要类似如下的拦截器的引用 <interceptor-stack name="integration"> & ...

  2. sublime3配置Quick-X+自动错误提示

    sublime3配置 安装Package Control 配置Quick-x API提示 配置Lua自动语法错误提示 sublime3 安装 Package Control View->Show ...

  3. PHP高级特性一之正则表达式用法

    在PHP中,我们进行字符串处理时,能用字符串处理函数时我们当然要使用简单的字符串处理函数,但字符串处理函数的能力是有限的,所以我们就需要利用一个更强大的工具,那就是正则表达式. 简述正则表达式 正则表 ...

  4. 【Tech】android真机测试——小米3

    开始学习android了,自带的虚拟AVD慢的不忍直视,只能拿自己的小米3开刀了.弄了好久,记录如下. 首先,我承认到现在我不知道小米3的驱动到底是怎么安装的,我按照网上的方法自己下载过小米的驱动,但 ...

  5. 一些practice和总结(转载)

    转自 http://boundary.cc/2013/05/java-app-server-develop/ by JOKER on 2013/05/05 最近状态不是很好,负能量堆到积爆表,静下心来 ...

  6. ZOJ 3367 Counterfeit Money(最大相同子矩阵)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3909 题意:给出两个矩阵A和B,找出最大的相同子矩阵S.输出S的高和 ...

  7. C# treeview控件部分节点添加checkbox

    一.先初始化treeview this.treeView1.CheckBoxes = true; this.treeView1.ShowLines = false; this.treeView1.Dr ...

  8. 动态设置easyui datagrid URL

    动态设置easyui datagrid URL$('#tt').datagrid({url:'website/jsp/servlet',        queryParams:{method:'xx' ...

  9. 为Gradle添加UTF-8支持

    gradle默认使用系统字符编码,大多数中文系统是使用GBK编码 但程序员绝大部分都是使用UTF-8写各类java文件以及其他资源文件 编译时很容易报错,比如下面的错误: ”警告:编码 GBK 的不可 ...

  10. 51nod1437 迈克步

    傻叉单调栈 #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> ...