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


 

 

 

 

 

 

 

 

 

你可能感兴趣的:(image,null,UP,图形,distance)