好久没发问,先问个关于paint的问题

rainfall19831109 2005-01-09 03:07:00
做了个屏幕取色的程序
在程序里,我用InvalidateRect(rc)强制刷新画图区
导致出来的效果是闪烁,不是很满意,然后尝试过用SendMessage(WM_PAINT),这样的话连paint都不paint了~~
大家有什么好的方法,可以不使画图区闪烁吗??
...全文
117 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
guangsan 2005-01-09
  • 打赏
  • 举报
回复
同意一楼的说法,取色为何要刷新呢?

如果只是想去掉屏幕闪烁,参考

http://search.csdn.net/Expert/topic/2356/2356465.xml?temp=.3671533

还有很多方法,请搜索
fanqing 2005-01-09
  • 打赏
  • 举报
回复
InvalidateRect(rc);
UpdateWindow();
fanqing 2005-01-09
  • 打赏
  • 举报
回复
介绍
在论坛中经常见到关于刷新时界面闪烁的帖子,如何控制在进行高效绘图时不出现界面闪烁的感觉呢,下文就双缓冲方法进行讲解.

正文
图形为什么会闪烁的原因是:我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的,其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。
如何实现双缓冲:在OnDraw(CDC *pDC)中:
CDC MemDC; //首先定义一个显示设备对象
CBitmap MemBitmap;//定义一个位图对象
//随后建立与屏幕显示兼容的内存显示设备
MemDC.CreateCompatibleDC(NULL);
//这时还不能绘图,因为没有地方画 ^_^
//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
//先用背景色将位图清除干净,这里我用的是白色作为背景
//你也可以用自己应该用的颜色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
//绘图
MemDC.MoveTo(……);
MemDC.LineTo(……);
//将内存中的图拷贝到屏幕上进行显示
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);
//绘图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();

以论坛的一个帖子例子为例来说明一些具体如何解决问题.
帖子那容是:

我想让一个区域动起来,
如何解决窗口刷新时区域的闪烁。
void CJhkljklView::OnDraw(CDC* pDC)
{
CJhkljklDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
int i;
int x[20],y[20];
CPen hPen;
POINT w[5];

x[0]=a/100+10;
x[1]=a/100+30;
x[2]=a/100+80;
x[3]=a/100+30;
x[4]=a/100+10;

y[0]=10;
y[1]=10;
y[2]=25;
y[3]=40;
y[4]=40;

for (i=0;i<5;i++)
{ w[i].x=x[i];
w[i].y=y[i];
}
//CClientDC dc(this);
//hPen=CreatePen(PS_SOLID,1,RGB(255,0,0));
CRgn argn,Brgn;
CBrush abrush(RGB(40,30,20));
argn.CreatePolygonRgn(w, 5, 1);// point为CPoint数组,
pDC->FillRgn(&argn, &abrush);
abrush.DeleteObject();
}

void CJhkljklView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
InvalidateRect(NULL,true);
UpdateWindow();
a+=100;
CView::OnTimer(nIDEvent);
}

int CJhkljklView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here
SetTimer(1,10,NULL);
return 0;
}

利用定时器直接进行10毫秒的屏幕刷新,这样效果会出现不停的闪烁的情况.

解决方法利用双缓冲,首先触发WM_ERASEBKGND,然后修改返回TRUE;
定义变量:
CBitmap *m_pBitmapOldBackground ;
CBitmap m_bitmapBackground ;
CDC m_dcBackground;

//绘制背景
if(m_dcBackground.GetSafeHdc()== NULL|| (m_bitmapBackground.m_hObject == NULL))
{
m_dcBackground.CreateCompatibleDC(&dc);
m_bitmapBackground.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height()) ;
m_pBitmapOldBackground = m_dcBackground.SelectObject(&m_bitmapBackground) ;
//DrawMeterBackground(&m_dcBackground, rect);
CBrush brushFill, *pBrushOld;
// 背景色黑色
brushFill.DeleteObject();
brushFill.CreateSolidBrush(RGB(255, 255, 255));
pBrushOld = m_dcBackground.SelectObject(&brushFill);
m_dcBackground.Rectangle(rect);
m_dcBackground.SelectObject(pBrushOld);
}
memDC.BitBlt(0, 0, rect.Width(), rect.Height(),
&m_dcBackground, 0, 0, SRCCOPY) ;

//绘制图形
int i;
int x[20],y[20];
CPen hPen;
POINT w[5];

x[0]=a/100+10;
x[1]=a/100+30;
x[2]=a/100+80;
x[3]=a/100+30;
x[4]=a/100+10;

y[0]=10;
y[1]=10;
y[2]=25;
y[3]=40;
y[4]=40;



for (i=0;i<5;i++)
{ w[i].x=x[i];
w[i].y=y[i];
}
//CClientDC dc(this);
//hPen=CreatePen(PS_SOLID,1,RGB(255,0,0));
CRgn argn,Brgn;
CBrush abrush(RGB(40,30,20));
argn.CreatePolygonRgn(w, 5, 1);// point为CPoint数组,
memDC.FillRgn(&argn, &abrush);
abrush.DeleteObject();
}

这样编译运行程序就会出现屏幕不闪烁的情况了.

如果有什么问题请和我联系:13975102873@hnmcc.com




fanqing 2005-01-09
  • 打赏
  • 举报
回复
连续取色很难避免闪烁,就算是用双缓冲也效果不好.因为你在不停的重绘.
rainfall19831109 2005-01-09
  • 打赏
  • 举报
回复
楼上的可否说详细点啊???
你看我就一块绿色小砖就知我菜啦。。。。
zhaogaojian 2005-01-09
  • 打赏
  • 举报
回复
用双缓冲
rainfall19831109 2005-01-09
  • 打赏
  • 举报
回复
我是连续取色的,因此画图区也不停地paint
另外,我的InvalidateRect(rc)是放在我的事件处理里面(OnMouseMove)~~
fanqing 2005-01-09
  • 打赏
  • 举报
回复
你的意思是不是,你取色(取一次,不是连续取色)后想画出来,但是画出的图片总是闪啊!
会不会你将InvalidateRect(rc);放到了onpaint中了.这样会导致不停的发WM_PAINT重绘无效区,
所以会闪

rainfall19831109 2005-01-09
  • 打赏
  • 举报
回复
to楼上:
如果我用UpdateWindow(),则结果依然
用画图区的UpdateWindow(),则画图区没有效果。。。
fanqing 2005-01-09
  • 打赏
  • 举报
回复
InvalidateRect(rc);
UpdateWindow();
你试过 了吗?
Maconel 2005-01-09
  • 打赏
  • 举报
回复
得到屏幕上颜色需要刷新吗?
HDC hdc = GetDC(0);
POINT point;
GetCursorPos(&point);
COLORREF color = GetPixel(hdc, point.x, point.y);
ReleaseDC(0, hdc);

color就是得到的颜色了。
rainfall19831109 2005-01-09
  • 打赏
  • 举报
回复
你们都误会我的意思了~~
得到屏幕颜色的话,我当然要显示出来啦~~
那就当然要paint啦~~
现在我做出来的效果就是画图区闪烁,想请问一下有什么办法解决。。。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧