// CSqueegee.cpp: implementation of the CSqueegee class. // ////////////////////////////////////////////////////////////////////// #include "CSqueegee.h" extern TextureBrush *g_paBrCleanBkg; extern Bitmap *g_paBmDirtyBkg; CSqueegee::CSqueegee() { ZeroMemory(&m_rDesktop,sizeof(m_rDesktop)); ZeroMemory(&m_vLastPos,sizeof(m_vLastPos)); m_flSqueegeeWidth=0.0f; m_paSqueegee=NULL; m_paBackground=NULL; m_flLastAngle=0.0f; } CSqueegee::~CSqueegee() { Destroy(); } void CSqueegee::Destroy() { if (m_paSqueegee!=NULL) { delete m_paSqueegee; m_paSqueegee=NULL; } if (m_paBackground!=NULL) { delete m_paBackground; m_paBackground=NULL; } } BOOL CSqueegee::Init(HWND hWnd) { float flWidth; float flHeight; Destroy(); // Get desktop dimensions (left/top can be negative on multimon) GetClientRect(hWnd,&m_rDesktop); flWidth=(float)m_rDesktop.right; flHeight=(float)m_rDesktop.bottom; m_rDesktop.top+=GetSystemMetrics(SM_YVIRTUALSCREEN); m_rDesktop.bottom+=GetSystemMetrics(SM_YVIRTUALSCREEN); m_rDesktop.left+=GetSystemMetrics(SM_XVIRTUALSCREEN); m_rDesktop.right+=GetSystemMetrics(SM_XVIRTUALSCREEN); m_flVelMax=((float)rand()/(float)RAND_MAX)*10.0f+35.0f; m_paSqueegee=LoadTGAResource(MAKEINTRESOURCE(IDR_SQUEEGEE)); m_nSnapshotSize=(int)sqrt(m_paSqueegee->GetWidth()*m_paSqueegee->GetWidth()+(m_paSqueegee->GetHeight()+m_flVelMax*2.0f)*(m_paSqueegee->GetHeight()+m_flVelMax*2.0f)); m_paBackground=new Bitmap(m_nSnapshotSize,m_nSnapshotSize,PixelFormat32bppPARGB); m_flSqueegeeWidth=m_paSqueegee->GetWidth()-6.0f; // Squeegees start from top left corner m_vPos.X=(float)m_rDesktop.left-(float)m_nSnapshotSize/2.0f; m_vPos.Y=(float)m_rDesktop.top+m_flSqueegeeWidth/2.0f; m_vVel.X=m_flVelMax; m_vVel.Y=0.0f; m_vAcc.X=0.0f; m_vAcc.Y=0.0f; m_vLastPos=m_vPos; m_flLastAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f); return true; } BOOL CSqueegee::Move(Graphics *g) // Returns true if moved on screen, false if moved outside screen { // Update position and other variables m_vLastPos=m_vPos; m_vPos=m_vPos+m_vVel; if ((m_vPos.X<(float)m_rDesktop.left-(float)m_nSnapshotSize) || (m_vPos.X>(float)m_rDesktop.right+(float)m_nSnapshotSize)) { // If past the left/right edge of the screen, turn around and move down a notch m_vPos.Y+=m_flSqueegeeWidth-10.0f; m_vVel.X*=-1.0f; m_flLastAngle+=180.0f; } else if (m_vPos.Y>(float)m_rDesktop.bottom+(float)m_nSnapshotSize) { // If past the bottom of the screen, its done return false; } Wipe(g); return true; } void CSqueegee::Wipe(Graphics *g) { Graphics *gBackground; RectF rect(0.0f,0.0f,m_flSqueegeeWidth,m_flVelMax); RectF rect2(0.0f,0.0f,(float)m_paSqueegee->GetWidth(),(float)m_paSqueegee->GetHeight()+m_flVelMax); Matrix mat; GraphicsPath Path; Graphics *gDirty; // Set up the brush transform (opposite from original transform) g_paBrCleanBkg->ResetTransform(); mat.Reset(); mat.Translate((float)m_paSqueegee->GetWidth()/2.0f-5.0f,-(float)m_paSqueegee->GetHeight()+30.0f); mat.Rotate(-m_flLastAngle-90.0f); mat.Translate(-m_vLastPos.X+m_rDesktop.left,-m_vLastPos.Y+m_rDesktop.top); g_paBrCleanBkg->SetTransform(&mat); // Set up original transform and erase from DirtyBkg a rectangle where the squeegee moved gDirty=new Graphics(g_paBmDirtyBkg); gDirty->TranslateTransform(m_vLastPos.X-m_rDesktop.left,m_vLastPos.Y-m_rDesktop.top); gDirty->RotateTransform(m_flLastAngle+90.0f); gDirty->TranslateTransform(-(float)m_paSqueegee->GetWidth()/2.0f+5.0f,(float)m_paSqueegee->GetHeight()-30.0f); gDirty->FillRectangle(g_paBrCleanBkg,rect); delete gDirty; // Get the bounds of the squeegee after rotations Path.AddRectangle(rect2); mat.Reset(); mat.Translate(m_vLastPos.X-m_rDesktop.left,m_vLastPos.Y-m_rDesktop.top); mat.Rotate(m_flLastAngle+90.0f); mat.Translate(-m_flSqueegeeWidth/2.0f,0.0); Path.GetBounds(&rect,&mat,NULL); // Draw on a temp surface whatever was on the dirty background where the squeegee is to be drawn gBackground=new Graphics(m_paBackground); gBackground->DrawImage(g_paBmDirtyBkg,0,0,(int)rect.X,(int)rect.Y,(int)rect.Width,(int)rect.Height,UnitPixel); // Draw squeegee on temp surface gBackground->ResetTransform(); gBackground->TranslateTransform(rect.Width/2.0f,rect.Height/2.0f); gBackground->RotateTransform(m_flLastAngle+90.0f); gBackground->TranslateTransform(-(float)m_paSqueegee->GetWidth()/2.0f,-(float)m_paSqueegee->GetHeight()/2.0f-m_flVelMax); gBackground->DrawImage(m_paSqueegee,0,0,0,0,m_paSqueegee->GetWidth(),m_paSqueegee->GetHeight(),UnitPixel); delete gBackground; // Draw temp surface to screen g->ResetTransform(); g->DrawImage(m_paBackground,(int)rect.X,(int)rect.Y,0,0,(int)rect.Width,(int)rect.Height,UnitPixel); }