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