- 浏览: 2001942 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (651)
- ACE (35)
- BAT (9)
- C/C++ (116)
- fast-cgi (14)
- COM (27)
- python (59)
- CGI (4)
- C# (2)
- VC (84)
- DataBase (29)
- Linux (96)
- P2P (6)
- PHP (15)
- Web (6)
- Memcached (7)
- IME输入法 (11)
- 设计模式 (2)
- 搜索引擎 (1)
- 个人情感 (4)
- 笔试/面试 (3)
- 一亩三分地 (33)
- 历史 (2)
- 地理 (1)
- 人物 (3)
- 经济 (0)
- 不仅仅是笑哦 (43)
- 小故事大道理 (2)
- http://www.bjdsmyysjk120.com/ (0)
- http://www.bjdsmyy120.com/ (0)
- 它山之石可以攻玉 (15)
- 大学生你关注些什么 (28)
- 数据恢复 (1)
最新评论
-
luokaichuang:
这个规范里还是没有让我明白当浏览器上传文件时,STDIN的消息 ...
FastCGI规范 -
effort_fan:
好文章!学习了,谢谢分享!
com技术简介 -
vcell:
有错误os.walk(strPath)返回的已经是全部的文件和 ...
通过python获取目录的大小 -
feifeigd:
feifeigd 写道注意:文章中的CPP示例第二行 #inc ...
ATL入门:利用ATL编写简单的COM组件 -
feifeigd:
注意:文章中的CPP示例第二行 #include " ...
ATL入门:利用ATL编写简单的COM组件
1、将Invalidate()替换为InvalidateRect()
Invalidate()会导致整个窗口的图象重画,需要的时间比较长,而InvalidateRect()仅仅重画Rect区域内的内容,所以所需时间会少一些。虫虫以前很懒,经常为一小块区域的重画就调用Invalidate(),不愿意自己去计算需要重画的Rect,但是事实是,如果你确实需要改善闪烁的情况,计算一个Rect所用的时间比起重画那些不需要重画的内容所需要的时间要少得多。
2、禁止系统搽除你的窗口
系统在需要重画窗口的时候会帮你用指定的背景色来搽除窗口。可是,也许需要重画的区域也许非常小。或者,在你重画这些东西之间还要经过大量的计算才能开始。这个时候你可以禁止系统搽掉原来的图象。直到你已经计算好了所有的数据,自己把那些需要搽掉的部分用背景色覆盖掉(如:dc.FillRect(rect,&brush);rect是需要搽除的区域,brush是带背景色的刷子),再画上新的图形。要禁止系统搽除你的窗口,可以重载OnEraseBkgnd()函数,让其直接返回pUE就可以了。如
BOOL CMyWin::OnEraseBkgnd(CDC* pDC)
{
return pUE;
//return CWnd::OnEraseBkgnd(pDC);//把系统原来的这条语句注释掉。
}
3、有效的进行搽除
搽除背景的时候,不要该搽不该搽的地方都搽。比如,你在一个窗口上放了一个很大的Edit框,几乎占了整个窗口,那么你频繁的搽除整个窗口背景将导致Edit不停重画形成剧烈的闪烁。事实上你可以CRgn创建一个需要搽除的区域,只搽除这一部分。如
GetClientRect(rectClient);
rgn1.CreateRectRgnIndirect(rectClient);
rgn2.CreateRectRgnIndirect(m_rectEdit);
if(rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR) == ERROR)//处理后的rgn1只包括了Edit框之外的客户区域,这样,Edit将不会被我的背景覆盖而导致重画。
{
ASSERT(FALSE);
return ;
}
brush.CreateSolidBrush(m_clrBackgnd);
pDC->FillRgn(&rgn1,&brush);
brush.DeleteObject();
注意:在使用这个方法的时候要同时使用方法二。别忘了,到时候又说虫虫的办法不灵。
4、使用MemoryDC先在内存里把图画好,再复制到屏幕上
这对于一次画图过程很长的情况比较管用。毕竟内存操作比较快,而且复制到屏幕又是一次性的,至少不会出现可以明显看出一个东东从左画到右的情况。
void CMyWin::OnPaint()
{
CPaintDC dc1(this); // device context for painting
dcMemory.CreateCompatibleDC(&dc1);
CBitmap bmp;//这里的Bitmap是必须的,否则当心弄出一个大黑块哦。
bmp.CreateCompatibleBitmap(&dc1,rectClient.Width(),rectClient.Height());
dcMemory.SelectObject(&bmp);
//接下来你想怎么画就怎么画吧。
//dcMemory.FillRect(rectClient,&brush);
dc1.BitBlt(0,0,rectClient.Width(),rectClient.Height(),&dcMemory,0,0,SRCCOPY);
dcMemory.DeleteDC();
// Do not call CWnd::OnPaint() for painting messages
}
争议
上述方法确实有效,但在有很多控件的情况下,计算一个窗口中需要擦除并重绘的“空白区域”是一件很麻烦的事情。为了方便这种方法的实际应用,我写了一组宏来完成”计算空白区域“的功能:
/*************************************************************************/
/************************************************************************/
/* 宏功能: 界面刷新时仅刷新指定控件以外的空白区域;可有效避免窗口闪烁
/* 使用于: WM_ERASEBKGND 消息处理函数 OnEraseBkgnd();
/************************************************************************/
#define ERASE_BKGND_BEGIN \
CRect bgRect;\
GetWindowRect(&bgRect);\
CRgn bgRgn;\
bgRgn.CreateRectRgnIndirect(bgRect);
//#define ERASE_BKGND_BEGIN
// Marco parameter 'IDC' specifies the identifier of the control
#define ADD_NOERASE_CONTROL(IDC)\
{\
CRect controlRect;\
GetDlgItem(IDC)->GetWindowRect(&controlRect);\
CRgn controlRgn;\
controlRgn.CreateRectRgnIndirect(controlRect);\
if(bgRgn.CombineRgn(&bgRgn, &controlRgn, RGN_XOR)==ERROR)\
return false;\
}
// Marco parameter 'noEraseRect' specifies a screen coordinates based RECT,
// which needn't erase.
#define ADD_NOERASE_RECT(noEraseRect)\
{\
CRgn noEraseRgn;\
noEraseRgn.CreateRectRgnIndirect(noEraseRect);\
if(bgRgn.CombineRgn(&bgRgn, &noEraseRgn, RGN_XOR)==ERROR)\
return false;\
}
// Marco parameter 'pDC' is a kind of (CDC *) type.
// Marco parameter 'clBrushColor' specifies the color to brush the area.
#define ERASE_BKGND_END(pDC, clBrushColor)\
CBrush brush;\
brush.CreateSolidBrush(clBrushColor);\
CPoint saveOrg = (pDC)->GetWindowOrg();\
(pDC)->SetWindowOrg(bgRect.TopLeft());\
(pDC)->FillRgn(&bgRgn, &brush);\
(pDC)->SetWindowOrg(saveOrg);\
brush.DeleteObject();\
//#define ERASE_BKGND_END
/*************************************************/
说明:
1)宏 ERASE_BKGND_BEGIN 和 ERASE_BKGND_END(pDC, clBrushColor) 搭配使用。
2)宏 ADD_NOERASE_CONTROL(IDC) 和 ADD_NOERASE_RECT(noEraseRect) 根据需要放在上面两个宏的中间,用来添加不需要重绘背景的区域(正是这些区域导致了闪烁),使用次数不限。其中参数noEraseRect是一个屏幕坐标系的RECT类型或CRect类型。
使用举例1:
在当前窗体的类中重写WM_ERASEBKGND消息处理函数如下:
BOOL CMyWnd::OnEraseBkgnd(CDC* pDC)
{
ERASE_BKGND_BEGIN;
ADD_NOERASE_RGN(IDC_BUTTON2);
ADD_NOERASE_RGN(IDC_BUTTON1);
ADD_NOERASE_RGN(IDC_LIST_STAT);
ERASE_BKGND_END(pDC, GetSysColor(COLOR_3DFACE));
return false;
}
上面的IDC_BUTTON2,IDC_BUTTON1,IDC_LIST_STAT即窗体上的控件。
你可以指定其他已存在的控件。
这样,窗口在擦除背景时,将只对上述控件以后的”空白区域“使用系统色重绘,有效避免了闪烁。
备注:
重载WM_ERASEBKGND消息处理函数OnEraseBkgnd的方法,选择View->ClassWizard->classinfo选项卡:message filter下拉框:
选择window,然后再选择message maps选项卡,在messages下拉框应该可以找到wm_erasebkgnd.双击添加.
使用举例2:防止CListCtrl在拉动窗口时闪烁。
/* * No further full-erasing is required,
* to prevent screen flashing caused by background erase and view repaint.
* Only erase the blank area.
*/
BOOL CExListCtrl::OnEraseBkgnd(CDC* pDC) {
//compute the holding-data-items area of this list control CRect rect;
CPoint dataRgnTopLeftPoint;
CPoint dataRgnBottomRightPoint;
GetItemPosition(0 , &dataRgnTopLeftPoint);
GetItemPosition(GetItemCount() , &dataRgnBottomRightPoint);
if(!GetHeaderCtrl()->GetItemRect(GetHeaderCtrl()->GetItemCount()-1, rect)) return
CListCtrl::OnEraseBkgnd(pDC);
dataRgnBottomRightPoint.x = rect.right;
rect.SetRect(dataRgnTopLeftPoint, (CPoint)(dataRgnBottomRightPoint - CPoint(2,2)));
ClientToScreen(dataRgnRect);
//compute and erase the blank area. Using the Marco. ERASE_BKGND_BEGIN;
ADD_NOERASE_RECT(dataRgnRect);
ERASE_BKGND_END(pDC, GetBkColor());
return false;
}
说明:CListCtrl在拉动的时候,会前以背景色重刷背景,再在上面绘制有数据的Items, 而没有数据的区域则保持背景色。因此,如果在BOOL CExListCtrl::OnEraseBkgnd(CDC* pDC) 函数中简单的return false,那么没有数据的区域将显示不正常。 故举例2中先计算出有数据的items的区域,这是不需要以背景重刷的区域。 再使用本文的宏,就可以有效避免CListCtrl在拉动时候的闪烁。
发表评论
-
__declspec(novtable) 的用法
2010-11-27 14:37 1536__declspec(novtable) 的用法 __d ... -
解决URLDownloadToFile缓存问题的两种方法
2010-09-09 15:18 2825解决URLDownloadToFile缓存问题的两种方法 ... -
修改richedit背景
2010-07-19 22:52 1606RichEditCtrl::SetBackgroundCo ... -
使用ADO封装类的数据库程序开发实例(下)
2010-07-12 15:30 1436使用ADO封装类的数据库 ... -
使用ADO封装类的数据库程序开发实例(上)
2010-07-12 15:28 1179使用ADO封装类的数据库 ... -
防止窗口闪烁地办法
2010-07-09 21:13 1471防止窗口闪烁地办法 也许我们都碰到过这种情况,当你 ... -
使用ADO _ConnectionPtr
2010-07-06 16:04 5228// GetUser.cpp : Defines the ... -
VC用ADO访问数据库全攻略
2010-07-06 15:29 1770VC用ADO访问数据库全 ... -
深入GetMessage和PeekMessage (引自-MSDN技术组)
2010-06-10 16:59 3681深入GetMessage和PeekMessage (引自 ... -
界面编程总结(1)
2010-06-02 13:32 3969原文地址:http://blog.csdn.net/byx ... -
获取信息的有关Windows API
2010-05-27 10:01 3094获取信息的有关Windows API 1.窗口信息 ... -
VC中如何实现窗口的隐藏
2010-05-13 10:08 7803VC中如何实现窗口的隐藏 用MFC做的Dialog ... -
SetConsoleCtrlHandler 处理控制台消息
2010-05-07 17:32 17999SetConsoleCtrlHandler 处理控制台消 ... -
解决决错误: error C2850: 'PCH header file'
2010-04-27 19:45 1893解决决错误: error C2850: 'PCH hea ... -
VC++ GDI+编程的字体和文本绘制
2010-04-13 13:12 7914字体是文字显示和打印的外观形式,它包括了文字的字样、风格和尺寸 ... -
VC利用GDI+显示透明的PNG图片
2010-04-12 16:59 114791.在你将要使用GDI+的工程中,完成初始化 ... -
GDI+编程基础(一)GDI+ Vs GDI
2010-04-12 15:59 2303下载源代码一、GDI GDI是位于应用程序与不同硬件之间 ... -
VC画图
2010-04-12 15:50 1494BOOL DrawPic(HDC hdc, TCHAR* ... -
对话框的数据交换--MFC深入浅出
2010-04-12 10:43 2408对话框数据交换指以下两种动作,或者是把内存数据写入对应的控 ... -
MFC中获取命令行参数的几种方法
2010-04-08 18:09 2935在MFC程序中,可以用以下几种方法来获取命令行参数。为方便 ...
相关推荐
VC窗口闪烁问题的解决,很全面
02_MyActiveX2 为ActiveX控件增加属性和方法。 03_ActiveXInDlg 在应用程序中使用ActiveX控件。 04_ActiveXInWeb 在浏览器中使用ActiveX控件。 05_MyActiveX3 在VC中显示动态的GIF动画。 06_RegOCX 在...
这里写了一个简易的多线程实例,另外对于窗口重绘,只重绘特定控件,值得一看
防止描画時画面闪烁 表现颜色(VC++) 打印 使用打印机 打印坐标紙 程序控制 资源文件国际化 直接从DLL调用函数 防止应用程序重复起动 CException类的派生与使用 实现VB的DoEvents函数 用CWinThread...
...................\关于内存DC绘图防止屏幕闪烁说明.doc ...................\创建有个性的对话框之MFC篇.doc ...................\利用VC编程在界面上实现3D文字.doc ...................\利用钩子实现菜单...
VC++自绘窗口, 自绘控件,自绘边框,高速绘图不闪烁, 窗口可以拉伸改变大小, 标题栏也可以双击最大化或最小化
2.实现功能:用MFC自带的控件,实现文本多行滚动显示,适合于显示大量信息的场合,类似VS调试窗口 3.解决相关的问题: a.使用VS自带控件,方便快捷稳定 b.运行效率高,显示速度快,不闪烁,不上下刷屏 c.如果文字数...
学习MO+VC时的学习总结,和大家分享。参考了不少网络的资料,现在自己也还一点给网络吧~! 1, 添加MO控件。 2, 控件在窗口显示范围:CTESTVIEW中添加WM_SIZE事件。添加语句 if (m_map.m_hWnd) { m_map....
45、当向列表框中添加多个项时如何防止闪烁 46、如何向编辑控件中添加文本 47、如何访问预定义的GDI对象 48、如何获取GDI对象的属性信息 49、如何实现一个橡皮区矩形 50、如何更新翻转背景颜色的文本 51、如何创建...
相关网站 7 设置窗口最大最小 7 ...更改窗口控件的能动和不能动(以按钮控件为例) 120 窗口响应键盘事件 120 密码框输入受保护 121 最高窗口的实现 122 实现窗口动态写入汉字和改变汉字颜色形状 123
VC常用操作源码(**经过排版编辑和修正过的word文档**),内容如下: CD-ROM 1 关闭计算机 1 重启计算机 1 枚举所有字体 1 只运行一个程序实例 2 得到鼠标位置 2 显示和隐藏程序菜单 2 获取可执行文件的图标 3 窗口...
收集了近100个VC 界面类编程的相关技巧资料,全部都是 Word格式,涉及界面编程的方方面面,下面简要列举一些: 百叶窗式面板组.doc ... Visual C 窗口标题改变的几种方法.doc 还有更多…………
相关网站 7 设置窗口最大最小 7 ...更改窗口控件的能动和不能动(以按钮控件为例) 120 窗口响应键盘事件 120 密码框输入受保护 121 最高窗口的实现 122 实现窗口动态写入汉字和改变汉字颜色形状 123
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
45、当向列表框中添加多个项时如何防止闪烁 15 46、如何向编辑控件中添加文本 15 47、如何访问预定义的GDI对象 15 48、如何获取GDI对象的属性信息 16 49、如何实现一个橡皮区矩形 16 50、如何更新翻转背景颜色的文本...
拖拽窗口,观察界面控件是否有明显闪烁 如发生界面闪烁,则说明界面绘制的处理有些问题。 软件启动速度 界面库产品应该对图片等资源加载做优化,以尽可能的减少界面库加载等带来的时间开销。也可以通过比较...
有其它方法来计算窗口的尺寸吗? 73 (99) 我在文档类中设置了一个整型变量。但是,当我试图把该变量写入Serialize函数中的archive文件中时,出现了类型错误。而文档中的其它变量没有问题。为什么? 73 (100) 如何控制...
MFC控件CListCtrl虚拟列表的使用实例,只要你内存够大百万级、千万级甚至更大的的数据显示都不会有问题,可随意流畅的拖动滚动条。 PS1:借鉴了网上找来的一份VC6.0实现的代码(此代码编译有错误),重新使用VS2019...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...