invalidaterect
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
- 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);
相关阅读
Invalidate(TRUE)与Invalidate(FALSE)区别
使用Invalidate(TRUE)函数时,它会向消息队列中添加了WM_ERASEBKGND和WM_PAINT两个消息。 使用Invalidate(FALSE)函数时,它只会向消
简单讲下postInvalidate和Invalidate的区别
invalidate 这里我们从源码中去简单扒一下View的invalidate()的方法: 1 /** 2 * Invalidate the whole v
notifyDataSetChanged和notifyDataSetInvalidated区别
notifyDataSetChanged和notifyDataSetInvalidated区别以及观察者模式的使用 看Observer和Observable的时候,爬了下Listview的
当浏览器第一次请求时,服务器创建一个session对象,同时生成一个sessionId,并在此次响应中将sessionId 以响应报文的方式传回客户端浏