调用Invalidate();CWnd::Invalidate void Invalidate( BOOL bErase = TRUE );ParametersbEraseSpecifies whether the background within the update region is to be erased.
The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT message occurs or until the region is validated by using the ValidateRect or ValidateRgn function. The system sends a WM_PAINT message to a window whenever its update region is not empty and there are no other messages in the application queue for that window.
RedrawWindow();
Invalidate(0);2.你不填充颜色不就是无色吗(看你用什么函数绘制椭圆的)
或者:
dc.SelectStockObject(NULL_BRUSH);//选入空刷子
....
dc.Ellipse(10,10,200,200);
NULL_BRUSH方法就是:pDC->SelectStockObject(NULL_BRUSH);
//pDC 为当前设备环境的指针
我的第二个问题已经解决了。
可是第一个问题还没解决:
由于每次调用OnMouseMove函数都绘制一个椭圆,如何清除前面绘制的椭圆只保留最后一次画的椭圆呢?
调用Invalidate();CWnd::Invalidate
void Invalidate( BOOL bErase = TRUE );ParametersbEraseSpecifies whether the background within the update region is to be erased.
1。OnPaint 函数的执行是靠什么来驱动的?是不是每个很短的时间自动调用的?
2。如果给InvalidateRec函数制定某一个Rec,它是通过调用OnPaint来刷新这个Rec的吗?
执行InvalidateRec之后是不是就执行OnPaint呢?谢谢!
画椭圆无外乎就是两点,而鼠标点上的时候,这是一个起始点。记录下来。 当鼠标移动的时候,记录当前点。然后调用invalidata(), 这样会自动触发ondraw,然后再ondraw中 利用这两点画椭圆。
//不是,OnPaint是在窗体变化的时候由于发送了WM_PAINT才发生OnPaint的,比如移动窗体,有窗体从上面移动过,或者最大最小化等等。
2。如果给InvalidateRec函数制定某一个Rec,它是通过调用OnPaint来刷新这个Rec的吗?
执行InvalidateRec之后是不是就执行OnPaint呢?
//InvalidateRec就是让OnPaint刷新这一个局部,不会对整个窗体重绘。
//InvalidateRec相当于传递一个矩形和一个WM_PAINT消息。
你说:InvalidateRec相当于传递一个矩形和一个WM_PAINT消息。也就是调用InvalidateRec之后就执行OnPaint,可是我在OnPaint函数中有绘制其他区域的代码,那不也就把其他区域也刷新了吗?另外,OnPaint函数并没有要绘制的矩形这样一个参数啊?是无参函数谢谢!
void CXXX::OnLButtonUp()
{
// 先刷
InvalidateRect();
// 再画
DrawEllipse();
}
参数省略
但是由于WM_PAINT消息是系统发送的,不是简单的在Invalidate之后就会有WM_PAINT消息,如果连续发送多个Invalidate或者InvalidateRect,可能只会有一个WM_PAINT消息,因此无效矩形是通过计算后包含了最大的无效区域。还有一个函数GetClipRgn,可以更精确地得到无效区域。
GDI本身具有的优化使得你在无效矩形之外绘制的图形不会显示出来,但是绘制的代码还是运行了,所以为了提高绘制效率,可以在绘制之前判断是否在无效矩形里面,以决定是否重新绘制。下面给个例子说明“在无效矩形之外绘制的图形不会显示出来”:
视图类中建立一个成员变量,初始化为FALSE:
BOOL m_bUpdate;
建立一个菜单项Test,在视图中响应:
void C...View::OnTest()
{
// TODO: 在此添加命令处理程序代码
m_bUpdate = TRUE;
InvalidateRect(CRect(100, 100, 130, 130));}
在OnDraw中:
void C...View::OnDraw(CDC* pDC)
{
C...Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return; // TODO: 在此处为本机数据添加绘制代码
pDC->FillSolidRect(0, 0, 200, 200, RGB(100, 100, 100));
if (m_bUpdate)
{
pDC->Ellipse(90, 90, 150, 150);
}
}你会看到,点击菜单后,灰色背景中是一个白色矩形而不是圆形。然后如果你改变窗口大小,或者切换窗口,那么就会变成灰色背景中一个白色圆形,因为这时候系统刷新了窗口区域,整个客户区都无效了。
我感觉有那么点儿意思,但是恕我愚昧还没看懂。
1。你说“GDI本身具有的优化使得你在无效矩形之外绘制的图形不会显示出来,但是绘制的代码还是运行了”,这样说来,刷新局部跟刷新整个客户区域还是没什么区别啊。当你点击Test之后,m_bUpdate = TRUE;以后刷新整个客户区还是执行了绘制椭圆的代码啊
2。我碰到一个与之有关的问题:有两个矩形区域,比如(0,0,50,50)和(100,0,150,50),里面都绘制有东西,当用Invalidate刷新第一个区域时,对第二个区域没有影响(只有第一个区域有闪烁),但是当刷新第二个区域时,第一个区域也有闪烁。我发现刷新的时候似乎是按照从客户区的左上角沿x、y方向刷新的,由于第二个区域的x坐标比第一个大,刷新它时必然要先刷新它前面的区域,是这样吗?非常感谢Mackz!!!
2 不是的。如果你明白了我的例子,应该可以理解这一点。
我在这儿等着你回来,等着你回来,把那问题解 ^_^
首先你用了某一种颜色画前一个椭圆,记录这个椭圆的位置.
然后你在第2次画的时候需要画2个椭圆.
先把画笔改为反色绘制,pDC->SetROP2(R2_NOT); 然后在记录的位置绘制一个椭圆,这时你绘制的椭圆会和背景色一致,巧妙的覆盖了你前面画出来的椭圆.
然后你再在新的坐标绘制一个你需要的椭圆就行了.
然后,凡是你绘制的东西的边界矩形和这个rect相交的,就绘制,不相交的,不用理会.
我试试看吧
你说的“代码开始处调用pDC->GetClipBox(rect)”是在InvalidateRec后还是在OnPaint的开始处?
还有,如何解释这个现象呢:我碰到一个与之有关的问题——有两个矩形区域,比如(0,0,50,50)和(100,0,150,50),里面都绘制有东西,当用Invalidate刷新第一个区域时,对第二个区域没有影响(只有第一个区域有闪烁),但是当刷新第二个区域时,第一个区域也有闪烁。我发现刷新的时候似乎是按照从客户区的左上角沿x、y方向刷新的,由于第二个区域的x坐标比第一个大,刷新它时必然要先刷新它前面的区域,请问是这样吗?
void CMatchDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(rbuttondown)//右键按下
{
CRect rc2(281, 560, 591, 670);
CRect rc3(641, 560, 951, 670);
InvalidateRect(rc2, TRUE);
InvalidateRect(rc3, TRUE);
}
CDialog::OnMouseMove(nFlags, point);
}
我删掉了中间一些不重要的代码。大致是这样
麻烦分析一下原因
等到秋风起,秋叶落成堆。