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

来源:互联网 发布:mac搜不到wifi 编辑:程序博客网 时间:2024/06/05 06:42

 http://blog.csdn.net/shuilan0066/article/details/6676229

 Invalidate();   执行时,是先用背景刷清屏以后,再重新绘画

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

 

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

                                                而使用Invalidate(rect), 则可以将闪烁降低到图片的边缘位置

 

具体方法如下:

 

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

   如果能让图片直接覆盖原有的图片,并且,又让图片失效的边缘部分清屏的话,那我们就可以解决这个问题了。

    

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

   然后,调用InvalidateRect(rect) 即可

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

 

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

 

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

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

 

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

 

[cpp] view plaincopy
  1. void CShowImageDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
  2. {  
  3.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  4.     switch (nChar)  
  5.     {  
  6.     case VK_LEFT:  
  7.         m_isKeyMoving=TRUE;  
  8.         if(!m_lock) //移动图片   用方向键控制移动图片  
  9.         {  
  10.             GetDlgItem(IDC_MOVE)->SetFocus();  
  11.             CRect rect;  
  12.             m_RectTracker.GetTrueRect(&rect);  
  13.             m_RectTracker.m_rect.SetRect(rect.TopLeft().x-10,rect.TopLeft().y,rect.BottomRight().x-10,rect.BottomRight().y);  
  14.             m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置  
  15.             m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());  
  16.   
  17.   
  18.             CRect clientRect;  
  19.             m_image.GetClientRect(&clientRect);  
  20.             CRect shuanxinRect;  
  21.             if (rect.BottomRight().x<clientRect.BottomRight().x)  //确定刷新区域  
  22.             {  
  23.                 shuanxinRect.TopLeft().x=rect.BottomRight().x;  
  24.                 if(rect.TopLeft().y>0)  
  25.                     shuanxinRect.TopLeft().y=rect.TopLeft().y;  
  26.                 else  
  27.                     shuanxinRect.TopLeft().y=0;  
  28.                 shuanxinRect.BottomRight().x=clientRect.BottomRight().x;  
  29.                 shuanxinRect.BottomRight().y=clientRect.BottomRight().y;  
  30.   
  31.                 //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标, 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标  
  32.                 //所以在使用InvalidateRect RedrawWindow 之前 必须将其他坐标系下的坐标进行转换,否则不能按预想的执行  
  33.                 m_image.ClientToScreen(shuanxinRect);  
  34.                 this->ScreenToClient(shuanxinRect);  
  35.                 RedrawWindow(shuanxinRect);  
  36.             }  
  37.   
  38.             DrawRectLock();  
  39.         }else{  
  40.             GetDlgItem(IDC_LOCK)->SetFocus();  
  41.             int width=0;  
  42.             int height=0;  
  43.             int x=0;  
  44.             int y=0;  
  45.             CRectTracker_Lock *p=headRectTraker;  
  46.             if(p!=NULL)  
  47.             {  
  48.                 //画区域  
  49.                 width=m_step;  
  50.                 height=p->rectLock.m_rect.Height();  
  51.                 x=p->rectLock.m_rect.TopLeft().x-m_step;  
  52.                 y=p->rectLock.m_rect.TopLeft().y;  
  53.                 int image_x=p->radio_distance_x*m_pImageObj->GetWidth()-((double)m_step/m_RectTracker.m_rect.Width())*m_pImageObj->GetWidth();  
  54.                 int image_y=p->radio_distance_y*m_pImageObj->GetHeight();  
  55.                 int image_width=((double)m_step/m_RectTracker.m_rect.Width())*m_pImageObj->GetWidth();  
  56.                 int image_height=p->radio_height*m_pImageObj->GetHeight();  
  57.   
  58.                 Pen pen(Color(255,255,0,0),2);  
  59.                 m_pGraphics->DrawRectangle(&pen,x,y,width,height);  
  60.                 CRect rect2;  
  61.                 m_RectTracker2.m_rect.SetRect(0,0,image_width,image_height);  
  62.                 m_RectTracker2.GetTrueRect(&rect2);  
  63.                 RectF rect2Des;  
  64.                 rect2Des.X=rect2.TopLeft().x;  
  65.                 rect2Des.Y=rect2.TopLeft().y;  
  66.                 rect2Des.Width=rect2.Width();  
  67.                 rect2Des.Height=rect2.Height();  
  68.   
  69.                 m_image2.ClientToScreen(rect2);  
  70.                 this->ScreenToClient(rect2);  
  71.                 Graphics graphics2(m_image2.GetDC()->GetSafeHdc());  
  72.                 graphics2.DrawImage(m_pImageObj,rect2Des,image_x,image_y,image_width,image_height,UnitPixel);  
  73.             }  
  74.         }  
  75.         break;  
  76.         case VK_RIGHT:  
  77.             m_isKeyMoving=TRUE;  
  78.             if(!m_lock) //移动图片   用方向键控制移动图片  
  79.             {  
  80.                 GetDlgItem(IDC_MOVE)->SetFocus();  
  81.                 CRect rect;  
  82.                 m_RectTracker.GetTrueRect(&rect);  
  83.                 m_RectTracker.m_rect.SetRect(rect.TopLeft().x+10,rect.TopLeft().y,rect.BottomRight().x+10,rect.BottomRight().y);  
  84.                 m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置  
  85.                 m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());  
  86.                 CRect clientRect;  
  87.                 m_image.GetClientRect(&clientRect);  
  88.                 CRect shuanxinRect;  
  89.   
  90.                 if (rect.TopLeft().x>clientRect.TopLeft().x)  
  91.                 {  
  92.                     shuanxinRect.TopLeft().x=clientRect.TopLeft().x;  
  93.                     shuanxinRect.TopLeft().y=clientRect.TopLeft().y;  
  94.                     shuanxinRect.BottomRight().x=rect.TopLeft().x;  
  95.                     shuanxinRect.BottomRight().y=clientRect.BottomRight().y;  
  96.   
  97.                     //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标, 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标  
  98.                     //所以在使用InvalidateRect RedrawWindow 之前 必须将其他坐标系下的坐标进行转换,否则不能按预想的执行  
  99.                     m_image.ClientToScreen(shuanxinRect);  
  100.                     this->ScreenToClient(shuanxinRect);  
  101.                     RedrawWindow(shuanxinRect);  
  102.                 }  
  103.                 DrawRectLock();  
  104.             }  
  105.             break;  
  106.         case VK_DOWN:  
  107.             m_isKeyMoving=TRUE;  
  108.             if(!m_lock) //移动图片   用方向键控制移动图片  
  109.             {  
  110.                 GetDlgItem(IDC_MOVE)->SetFocus();  
  111.                 CRect rect;  
  112.                 m_RectTracker.GetTrueRect(&rect);  
  113.                 m_RectTracker.m_rect.SetRect(rect.TopLeft().x,rect.TopLeft().y+10,rect.BottomRight().x,rect.BottomRight().y+10);  
  114.                 m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置  
  115.                 m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());  
  116.   
  117.                 CRect clientRect;  
  118.                 m_image.GetClientRect(&clientRect);  
  119.                 CRect shuanxinRect;  
  120.                 if (rect.TopLeft().y>clientRect.TopLeft().y)  
  121.                 {  
  122.                     shuanxinRect.TopLeft().x=clientRect.TopLeft().x;  
  123.                     shuanxinRect.TopLeft().y=clientRect.TopLeft().y;  
  124.                     shuanxinRect.BottomRight().x=clientRect.BottomRight().x;  
  125.                     shuanxinRect.BottomRight().y=rect.TopLeft().y;  
  126.   
  127.                     //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标, 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标  
  128.                     //所以在使用InvalidateRect RedrawWindow 之前 必须将其他坐标系下的坐标进行转换,否则不能按预想的执行  
  129.                     m_image.ClientToScreen(shuanxinRect);  
  130.                     this->ScreenToClient(shuanxinRect);  
  131.                     RedrawWindow(shuanxinRect);  
  132.                 }  
  133.                 DrawRectLock();  
  134.             }  
  135.             break;  
  136.         case VK_UP:  
  137.             m_isKeyMoving=TRUE;  
  138.             if(!m_lock) //移动图片   用方向键控制移动图片  
  139.             {  
  140.                 GetDlgItem(IDC_MOVE)->SetFocus();  
  141.                 CRect rect;  
  142.                 m_RectTracker.GetTrueRect(&rect);  
  143.                 m_RectTracker.m_rect.SetRect(rect.TopLeft().x,rect.TopLeft().y-10,rect.BottomRight().x,rect.BottomRight().y-10);  
  144.                 m_RectTracker.GetTrueRect(&rect); // 调整以后,取得的新矩形位置  
  145.                 m_pGraphics->DrawImage(m_pImageObj,rect.TopLeft().x,rect.TopLeft().y,rect.Width(),rect.Height());  
  146.                 CRect clientRect;  
  147.                 m_image.GetClientRect(&clientRect);  
  148.                 CRect shuanxinRect;  
  149.                 if (rect.BottomRight().y<clientRect.BottomRight().y)  
  150.                 {  
  151.                     shuanxinRect.TopLeft().x=clientRect.TopLeft().x;  
  152.                     shuanxinRect.TopLeft().y=rect.BottomRight().y;  
  153.                     shuanxinRect.BottomRight().x=clientRect.BottomRight().x;  
  154.                     shuanxinRect.BottomRight().y=clientRect.BottomRight().y;  
  155.   
  156.                     //clientRect与rect  shuanxinRect  用的都是m_image客户区坐标, 而InvalidateRect  RedrawWindow用的却是对话框客户区坐标  
  157.                     //所以在使用InvalidateRect RedrawWindow 之前 必须将其他坐标系下的坐标进行转换,否则不能按预想的执行  
  158.                     m_image.ClientToScreen(shuanxinRect);  
  159.                     this->ScreenToClient(shuanxinRect);  
  160.                     RedrawWindow(shuanxinRect);  
  161.                 }  
  162.                 DrawRectLock();  
  163.             }  
  164.   
  165.             break;  
  166.     }  
  167.     CDialog::OnKeyDown(nChar, nRepCnt, nFlags);  
  168. }  
0 0