• 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);
    }
    

    
  • 相关阅读:
    深度学习之Python 脚本训练keras mnist 数字识别模型
    Hive udtf 报错 java.lang.String cannot be cast to java.lang.Integer
    vue 中 created 和 mounted 钩子生命周期 问题
    vue和 jsplumb 集成 出现下面的错误
    Cognos 中 javascript jQuery 的使用
    Hadoop 下常用的命令
    剑指offer30:连续子数组的最大和
    剑指offer29:最小的k个数
    剑指offer28:找出数组中超过一半的数字。
    剑指offer27:按字典序打印出该字符串中字符的所有排列
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7150226.html
Copyright © 2020-2023  润新知