解决CListCtrl闪烁及水平滚动条不能跟踪拖动的问题(MFC)
来源:互联网 发布:按网络的覆盖区域分为 编辑:程序博客网 时间:2024/05/21 14:59
项目中用到一个界面如下图所示,在View上有个CPropertySheet,其上有几个CPropertyPage,每个属性页上有个CListCtrl,供用户查看信息。由于CListCtrl中的信息每隔200ms就要刷新一次,导致这个区域不停的闪烁。同时,由于空间不够,CListCtrl上有个水平滚动条,当我们想拉动滚动条到中间位置查看后面几列数据时,刚拉过去就由于刷新又被拉回起点,导致很难查看后面几列数据,我们将这个问题称为水平滚动条不能跟踪问题。本文主要就这两点来记录相关的解决方法。
(1)解决闪烁问题
我们知道,造成绘图闪烁的原因是因为在每次重绘之前会调用OnEraseBkgnd用背景色对区域进行擦除(默认为白色),导致前后图像反差太大,引起视觉上的闪烁。要去除闪烁,就是要降低这种反差。一种较好的方法就是采用双缓冲绘图,即在内存中开辟一个画布,用来绘图,然后将绘制好的图形复制到设备中显示(http://www.diybl.com/course/3_program/c++/cppjs/200867/123361.html)。另外,防止CListCtrl闪烁的问题,网友也有总结(http://blog.sina.com.cn/s/blog_5ee42ba30100g50j.html)。
在查阅上述资料,结合本身的问题,设计如下的解决方案,来解决闪烁问题。
首先,由于显示数据全部在CListCtrl上更新,对于View、CPropertySheet、CPropertyPage而言,并没有什么改动,每次重绘时可以禁止其用背景色擦除区域,减少反差。分别重载这三者的OnEraseBkgnd消息函数,改成 return FALSE; 。
其次,对于CListCtrl闪烁的问题,可以采用双缓冲来解决。如下所示:
void CMyListCtrl::OnPaint(){//使用双缓冲的方法绘制背景CPaintDC dc(this); // device context for paintingCRect rect;CRect headerRect;CDC MenDC;//内存DC CBitmap MemMap;GetClientRect(&rect); GetDlgItem(0)->GetWindowRect(&headerRect); MenDC.CreateCompatibleDC(&dc); MemMap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); MenDC.SelectObject(&MemMap);MenDC.FillSolidRect(&rect,RGB(255,255,255)); //调用默认的OnPaint(),把图形画在内存DC表上 DefWindowProc(WM_PAINT,(WPARAM)MenDC.m_hDC,(LPARAM)0); //输出到显示设备dc.BitBlt(0,headerRect.Height(), rect.Width(), rect.Height(), &MenDC, 0, headerRect.Height(), SRCCOPY); MenDC.DeleteDC();MemMap.DeleteObject();}BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC){// TODO: Add your message handler code here and/or call default//return CListCtrl::OnEraseBkgnd(pDC);return FALSE;}至此,可解决整体的闪烁问题。
(2)解决水平滚动条不能跟踪问题
对于这个问题,我一开始比较迷茫,不知道怎么解决,从网上搜了一下,有人提出用GetScrollPos + Scroll,也有人提出用EnsureVisible。第一个方法我试了,主要是记录当前滚动条的位置,然后在刷新后设置到记录的位置,这个方法并不能很好的回到记录的位置,且这样做的话会重新引入闪烁问题(滚动条从记录位置到起始位置再到记录位置,反差很大)。第二种方法貌似只能用于多行,对于多列好像不行。
于是,我重新思考这个问题。我在程序里的做法是每次刷新时,首先删除所有的行项,然后重新插入包含新数据信息的行项。其实这个行数还是保持不变的,每次更新的只是一些Item的内容而已,于是我想能不能每次只是更新这些数据,不进行行项的删除和重新插入操作,除非有新的行项加入才进行这个操作。如果还无法回到滚动条位置,那么能否根据当前view的视图大小,计算当前需要更新的CListCtrl的Item项,即每次不对所有的Item列项进行更新数据,只对当前View显示视图区域内的内容进行更新(后来发现这点已经不必做了,第一点已经能够解决这个问题)。
对程序做了更改后,可以实现水平滚动条的跟踪问题。
void UpdateItem(){ //...... CString str; BOOL bInsertItem = FALSE; if(m_bInsertItem) { m_bInsertItem = FALSE;bInsertItem = TRUE;m_listInfo.DeleteAllItems();//删除原有的数据 } for(i=0; i<CNT; i++) { str.Format(_T("%d"), i+1);//序号if(bInsertItem) m_listInfo.InsertItem(i, str);//插入行,显示序号str.Format(_T("ID=%d"), xxx);m_listInfo.SetItemText(i, 1, str); //插入其他内容...... //...... }}
- 解决CListCtrl闪烁及水平滚动条不能跟踪拖动的问题(MFC)
- 解决CListCtrl闪烁及水平滚动条不能跟踪拖动的问题(MFC)
- 解决CListCtrl闪烁及水平滚动条不能跟踪拖动的问题(MFC)
- 关于对话框中拖动滚动条闪烁的问题
- 解决MFC中CListCtrl(virtual)控件闪烁问题
- 解决MFC中CListCtrl(virtual)控件闪烁问题
- 禁止CListCtrl 的水平滚动条
- 水平滚动条拖动
- MFC LISTBOX滚动条(垂直滚动条和水平滚动条)问题
- clistctrl出现水平滚动条
- JavaScript中Textarea滚动条不能拖动的问题
- 解决CListCtrl闪烁问题
- duilib 滚动条不能拖动 问题处理
- 解决JScrollPane水平滚动条不显示的问题
- Winform中DataGridView横向拖动滚动条时闪烁问题很严重的处理办法
- silverlight中datagrid的水平滚动条拖动bug及解决方法
- 解决jscollpan不能出现水平滑动条的问题
- CListCtrl滚动条的一些问题搜集
- 并查集
- 基于phonegap开发的移动应用插入广告的方法
- USB Video Class Specification 笔记
- C语言之#define用法总结
- flex_警告窗口自定义示例;
- 解决CListCtrl闪烁及水平滚动条不能跟踪拖动的问题(MFC)
- Java数据类型及对应取值范围
- 如何自定义添加基于FTDI的调试器
- 教你如何迅速秒杀掉:99%的海量数据处理面试题
- vc获取硬盘物理序列号
- eclipse中设置svn提交快捷键
- Ubuntu 11.04 下安装JDK6,Tomcat7
- Virtual Keyboards on iPhone and Android
- Android电源信息