再谈鼠标移动画图时,图像不断闪烁问题

来源:互联网 发布:拼图很多图软件 编辑:程序博客网 时间:2024/05/29 02:46

 

      在前面一篇文章中版

InvalidateRect( LPCRECT lpRect) 以及 RedrawWindow( LPCRECT lpRect) 中的重绘部分区域 是什么含义

 

      曾提到鼠标移动时,其它图形也跟着闪烁的问题,当时用的方法是SetTimer(1,40,NULL)定时刷新,而不是鼠标移动一下就刷新一下,这只是缓解了闪烁问题,未从根本上解决,而且用鼠标画的实时矩形还不能立刻更新,也达不到我们的要求,只是一个不得已而为之的方法。

       今天,终于想好了另一种策略,几乎完美的解决了这个问题:即能让鼠标所画的矩形可以实时显示出来,冲刷掉移动前的无效矩形,又可以使其它位置已经画好的矩形不再跟着鼠标移动而发生闪烁。

     思路:

       我们想要鼠标所画的图形实时更改,就必须刷掉鼠标刚刚移动前的矩形, 而若是调用InvalidateRect等 则其它地方又会闪烁;若不调用刷新消息,则鼠标移动前和移动后的矩形便会同时显现,这样跟着鼠标移动时,所留在屏幕上的便不再是一个实时矩形,而是还要很多无效的矩形。

      刷新有问题,不刷新也有问题,实在是两难选择,且都是效果不好的选择 

      好,今天突然来了思路:

      可以实现,在不刷新的情况下,实时显现鼠标所画的矩形。

      这样,因为不刷新,所以其它已经画好的矩形也不会产生闪烁了:》

 

      方法如下:

      假设,跟随鼠标的实时矩形为:rect

 

     第一步: 我们在背景上(我的背景是图片,在图片上画矩形)同样的位置,选择大一号的矩形,比如每个方向上都大5像素BigRect

 

     第二步: 在画矩形时,先将BigRect 重绘到背景上,因为两图几乎一样,所以不会有闪烁,同时由于是覆盖在背景上的,所以把鼠标这次移动前的无效矩形都给覆盖掉了。

 

      第三步:画矩形rect

 

       这样,便完成我们的效果了

 

      注:之所以要用大一点的BigRect,是因为要是鼠标实时矩形比原先矩形小时,我们也可以用这个大点的矩形区域将原先的矩形覆盖掉

 

以下是所用的核心程序:

 

 

OnMouseMove(UINT nFlags, CPoint point){...Pen pen(Color(255,255,0,0),2);int width_w=point.x-m_leftBnDown.x;int height_h=point.y-m_leftBnDown.y;m_width_w=width_w;m_height_h=height_h;CRect rect(m_leftBnDown.x,m_leftBnDown.y,m_leftBnDown.x+width_w,m_leftBnDown.y+height_h);DrawRectImageOnImageOne(rect);  //将rect中的背景原图覆盖  m_pGraphics->DrawRectangle(&pen,m_leftBnDown.x,m_leftBnDown.y,width_w,height_h);...}


 

void  CShowImageDlg::DrawRectImageOnImageOne(CRect &rect) //在m_image1上画图片{int distanceToyuandian_x;int distanceToyuandian_y;double radio_distance_x;double radio_distance_y;double radio_width;double radio_height;distanceToyuandian_x=rect.TopLeft().x-5-m_RectTracker.m_rect.TopLeft().x;distanceToyuandian_y=rect.TopLeft().y-5-m_RectTracker.m_rect.TopLeft().y;radio_distance_x=(double)distanceToyuandian_x/(double)m_RectTracker.m_rect.Width();radio_distance_y=(double)distanceToyuandian_y/(double)m_RectTracker.m_rect.Height();radio_width=(double)(rect.Width()+10)/(double)m_RectTracker.m_rect.Width();radio_height=(double)(rect.Height()+10)/(double)m_RectTracker.m_rect.Height();RectF souce_imageRectF;souce_imageRectF.X=radio_distance_x*m_pImageObj->GetWidth();souce_imageRectF.Y=radio_distance_y*m_pImageObj->GetHeight();souce_imageRectF.Width=radio_width*m_pImageObj->GetWidth();souce_imageRectF.Height=radio_height*m_pImageObj->GetHeight();RectF rect2Des;rect2Des.X=rect.TopLeft().x-5;rect2Des.Y=rect.TopLeft().y-5;rect2Des.Width=rect.Width()+10;rect2Des.Height=rect.Height()+10;  //BigRect 比原rect稍微大一点m_pGraphics->DrawImage(m_pImageObj,rect2Des,souce_imageRectF.X,souce_imageRectF.Y,souce_imageRectF.Width,souce_imageRectF.Height,UnitPixel);}