InvalidateRect(rect) 防止图片移动时发生闪烁

Invalidate();   运行时,是先用背景刷清屏以后。再又一次绘画

  InvalidateRect(rect), 他运行时, rect区域以背景刷清屏。rect以外的区域不调用背景刷。而是将屏幕上现有的内容(如图片图形等)作为背景,在这个背景上直接绘图。

 

 若是,图片和背景反差非常大。则使用Invalidate() 会发生闪烁

                                                而使用Invalidate(rect), 则能够将闪烁减少到图片的边缘位置

 

详细方法例如以下:

 

   平移时,假设直接翻盖原来的图片,则不会闪烁,但是这时,图片移动后。原图片的边缘位置已经无效,但是因为我们没有清屏,所以它还显示在图片上,这是不应该的。

   假设能让图片直接覆盖原有的图片。而且,又让图片失效的边缘部分清屏的话。那我们就能够解决问题了。

    

     首先, 我们确定好边缘处须要刷新的区域shuanxinRect

   然后。调用InvalidateRect(rect) 就可以

      注意,移动时。不要使的整个客户区clientRect都清屏。由于那样,会产生闪烁。

 

     我们的原则是:改直接覆盖的。则直接覆盖。改清屏的则清屏

 

     同一时候,要注意:InvalidateRect(rect)  使用的是对话框的坐标系,而不是画图控件的坐标系。

   所以,若是两坐标系不同的话,先要通过 kongJian->ClientToScreen(&rect);   this->ScreenToClient(&rect) 进行转换,转换完成后,才干够调用InvalidateRect(rect);

 

   以下是我在项目中摘取的一段演示样例程序:使用四个方向键来控制图片的平移

void CShowImageDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
   // TODO: 在此加入消息处理程序代码和/或调用默认值
   switch (nChar)
   {
   case VK_LEFT:
       m_isKeyMoving=TRUE;
       if(!m_lock) //移动图片   用方向键控制移动图片
       {
           GetDlgItem(IDC_MOVE)->SetFocus();
           CRect rect;
           m_RectTracker.GetTrueRect(&rect);
           m_RectTracker.m_rect.SetRect(rect.TopLeft().x-10,rect.TopLeft().y,rect.BottomRight().x-10,rect.BottomRight().y);
           m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置
           m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());


           CRect clientRect;
           m_image.GetClientRect(&clientRect);
           CRect shuanxinRect;
           if (rect.BottomRight().x<clientRect.BottomRight().x)  //确定刷新区域
           {
               shuanxinRect.TopLeft().x=rect.BottomRight().x;
               if(rect.TopLeft().y>0)
                   shuanxinRect.TopLeft().y=rect.TopLeft().y;
               else
                   shuanxinRect.TopLeft().y=0;
               shuanxinRect.BottomRight().x=clientRect.BottomRight().x;
               shuanxinRect.BottomRight().y=clientRect.BottomRight().y;

               //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标。 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标
               //所以在使用InvalidateRect RedrawWindow 之前 必须将其它坐标系下的坐标进行转换,否则不能按预想的运行
               m_image.ClientToScreen(shuanxinRect);
               this->ScreenToClient(shuanxinRect);
               RedrawWindow(shuanxinRect);
           }

           DrawRectLock();
       }else{
           GetDlgItem(IDC_LOCK)->SetFocus();
           int width=0;
           int height=0;
           int x=0;
           int y=0;
           CRectTracker_Lock *p=headRectTraker;
           if(p!=NULL)
           {
               //画区域
               width=m_step;
               height=p->rectLock.m_rect.Height();
               x=p->rectLock.m_rect.TopLeft().x-m_step;
               y=p->rectLock.m_rect.TopLeft().y;
               int image_x=p->radio_distance_x*m_pImageObj->GetWidth()-((double)m_step/m_RectTracker.m_rect.Width())*m_pImageObj->GetWidth();
               int image_y=p->radio_distance_y*m_pImageObj->GetHeight();
               int image_width=((double)m_step/m_RectTracker.m_rect.Width())*m_pImageObj->GetWidth();
               int image_height=p->radio_height*m_pImageObj->GetHeight();

               Pen pen(Color(255,255,0,0),2);
               m_pGraphics->DrawRectangle(&pen,x,y,width,height);
               CRect rect2;
               m_RectTracker2.m_rect.SetRect(0,0,image_width,image_height);
               m_RectTracker2.GetTrueRect(&rect2);
               RectF rect2Des;
               rect2Des.X=rect2.TopLeft().x;
               rect2Des.Y=rect2.TopLeft().y;
               rect2Des.Width=rect2.Width();
               rect2Des.Height=rect2.Height();

               m_image2.ClientToScreen(rect2);
               this->ScreenToClient(rect2);
               Graphics graphics2(m_image2.GetDC()->GetSafeHdc());
               graphics2.DrawImage(m_pImageObj,rect2Des,image_x,image_y,image_width,image_height,UnitPixel);
           }
       }
       break;
       case VK_RIGHT:
           m_isKeyMoving=TRUE;
           if(!m_lock) //移动图片   用方向键控制移动图片
           {
               GetDlgItem(IDC_MOVE)->SetFocus();
               CRect rect;
               m_RectTracker.GetTrueRect(&rect);
               m_RectTracker.m_rect.SetRect(rect.TopLeft().x+10,rect.TopLeft().y,rect.BottomRight().x+10,rect.BottomRight().y);
               m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置
               m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());
               CRect clientRect;
               m_image.GetClientRect(&clientRect);
               CRect shuanxinRect;

               if (rect.TopLeft().x>clientRect.TopLeft().x)
               {
                   shuanxinRect.TopLeft().x=clientRect.TopLeft().x;
                   shuanxinRect.TopLeft().y=clientRect.TopLeft().y;
                   shuanxinRect.BottomRight().x=rect.TopLeft().x;
                   shuanxinRect.BottomRight().y=clientRect.BottomRight().y;

                   //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标, 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标
                   //所以在使用InvalidateRect RedrawWindow 之前 必须将其它坐标系下的坐标进行转换。否则不能按预想的运行
                   m_image.ClientToScreen(shuanxinRect);
                    this->ScreenToClient(shuanxinRect);
                    RedrawWindow(shuanxinRect);
                }
                DrawRectLock();
            }
            break;
        case VK_DOWN:
            m_isKeyMoving=TRUE;
            if(!m_lock) //移动图片   用方向键控制移动图片
            {
                GetDlgItem(IDC_MOVE)->SetFocus();
                CRect rect;
                m_RectTracker.GetTrueRect(&rect);
                m_RectTracker.m_rect.SetRect(rect.TopLeft().x,rect.TopLeft().y+10,rect.BottomRight().x,rect.BottomRight().y+10);
                m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置
                m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());

                CRect clientRect;
                m_image.GetClientRect(&clientRect);
                CRect shuanxinRect;
                if (rect.TopLeft().y>clientRect.TopLeft().y)
                {
                    shuanxinRect.TopLeft().x=clientRect.TopLeft().x;
                    shuanxinRect.TopLeft().y=clientRect.TopLeft().y;
                    shuanxinRect.BottomRight().x=clientRect.BottomRight().x;
                    shuanxinRect.BottomRight().y=rect.TopLeft().y;

                    //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标, 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标
                    //所以在使用InvalidateRect RedrawWindow 之前 必须将其它坐标系下的坐标进行转换,否则不能按预想的运行
                    m_image.ClientToScreen(shuanxinRect);
                    this->ScreenToClient(shuanxinRect);
                    RedrawWindow(shuanxinRect);
                }
                DrawRectLock();
            }
            break;
        case VK_UP:
            m_isKeyMoving=TRUE;
            if(!m_lock) //移动图片   用方向键控制移动图片
            {
                GetDlgItem(IDC_MOVE)->SetFocus();
                CRect rect;
                m_RectTracker.GetTrueRect(&rect);
                m_RectTracker.m_rect.SetRect(rect.TopLeft().x,rect.TopLeft().y-10,rect.BottomRight().x,rect.BottomRight().y-10);
                m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置
                m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());
                CRect clientRect;
                m_image.GetClientRect(&clientRect);
                CRect shuanxinRect;
                if (rect.BottomRight().y<clientRect.BottomRight().y)
                {
                    shuanxinRect.TopLeft().x=clientRect.TopLeft().x;
                    shuanxinRect.TopLeft().y=rect.BottomRight().y;
                    shuanxinRect.BottomRight().x=clientRect.BottomRight().x;
                    shuanxinRect.BottomRight().y=clientRect.BottomRight().y;

                    //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标, 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标
                    //所以在使用InvalidateRect RedrawWindow 之前 必须将其它坐标系下的坐标进行转换,否则不能按预想的运行
                    m_image.ClientToScreen(shuanxinRect);
                    this->ScreenToClient(shuanxinRect);
                    RedrawWindow(shuanxinRect);
                }
                DrawRectLock();
            }

            break;
    }
    CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}



posted on 2017-07-11 14:08  wgwyanfs  阅读(227)  评论(0编辑  收藏  举报

导航