首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

还是窗口重绘的有关问题

2012-03-17 
还是窗口重绘的问题下面的代码(一部分),也是 vc++技术内幕 里面的代码,实现的是可以用鼠标拖动一个

还是窗口重绘的问题
下面的代码(一部分),也是 < <vc++技术内幕> > 里面的代码,实现的是可以用鼠标拖动一个圆:
void   CEx05cView::OnDraw(CDC*   pDC)
{
        CBrush   brushHatch(HS_DIAGCROSS,   RGB(255,   0,   0));
        CPoint   point(0,   0);                                     //   logical   (0,   0)
       
        pDC-> LPtoDP(&point);                                   //   In   device   coordinates,
        pDC-> SetBrushOrg(point);                           //     align   the   brush   with
                                                                                  //     the   window   origin
        pDC-> SelectObject(&brushHatch);
        pDC-> Ellipse(CRect(m_pointTopLeft,   m_sizeEllipse));
        pDC-> SelectStockObject(BLACK_BRUSH);   //   Deselect   brushHatch
        pDC-> Rectangle(CRect(100,   -100,   200,   -200));   //   Test   invalid   rect
}

void   CEx05cView::OnMouseMove(UINT   nFlags,   CPoint   point)  
{
        if   (m_bCaptured)   {
                CClientDC   dc(this);
                OnPrepareDC(&dc);
                CRect   rectOld(m_pointTopLeft,   m_sizeEllipse);
                dc.LPtoDP(rectOld);
                InvalidateRect(rectOld,   TRUE);

                m_pointTopLeft   =   point   -   m_sizeOffset;
                dc.DPtoLP(&m_pointTopLeft);
                CRect   rectNew(m_pointTopLeft,   m_sizeEllipse);
                dc.LPtoDP(rectNew);
                InvalidateRect(rectNew,   TRUE);
        }
}

我只是想问一下,为什么OnMouseMove里面两次调用invalidate函数呢
第一次调用是使老矩形无效,第二次是使新矩形无效,但是两次应该都是引起ondraw重绘窗口的啊,那怎么实现擦除原来的圆的效果的?

[解决办法]
两次InvalidateRect实际只能产生一个WM_PAINT消息(就是OnDraw只能被调用一次,因为这个消息会被合并),但是被擦除的区域是包含了rectOld和rectNew两个部分的。
InvalidateRect的第二个参数TRUE是说要擦除背景,OnDraw被调用之前rectOld和rectNew两个矩形都被擦成背景色了(就是说原来的圆被擦掉了),OnDraw里只画了新的圆。最后你看到的就是一个新的圆。
[解决办法]
InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT
InvalidateRect只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管InvalidateRect放哪里,都是最后执行的。



所以说InvalidateRect(rectOld, TRUE);之前,你又新画了一个圆,所以原来老矩形的位置将会根据你新画圆的位置重画整个窗口,除非你的新圆还在原地,不然的话老矩形的位置上的圆将会被擦除.

热点排行