[CProgress :Netscape style busy(downloading) bar ] |
Environment: Win 95/98 VC6 SP4
CProgress is a CWnd derived class that imitates the busy mode window (that is contained is Netscape Navigator status bar) . CProgress does animation. by that it resembles CILVideo , and if you look into the source code you'll fing much similiarity. This means that the same code appears twice! Why? I wanted to reduce dependencies : so you won't have to add many classes to your project: (you may add these classes very rarely if any).
Parts of the code : Drawing stuff are taken from MSJ 1997 : A program of Paul DiLascia called GradientCap (class name : CCaptionPainter).Thanks.
CProgess window is located in the second pane of status bar (pane index 1): (although you cant see animation here)
:jpg image is distorted , activate the sample app enclosed.
Creation of window is done by using:
BOOL Create(UINT nID,CWnd *pParent,RECT &rc,BOOL bAllowResize=FALSE,COLORREF clrBK=::GetSysColor(COLOR_3DFACE)); BOOL CreateFromStatic(UINT nID,CWnd *pParent,BOOL bAllowResize=FALSE,COLORREF clrBK=::GetSysColor(COLOR_3DFACE));You may set the size of bar . This is the area where animation scrolls over and over. In most cases : the default (bar captures the whole client area) is suitable. (or maybe you want to do something else with the rest of the window. Whenever the whole client area is used , whenever you resize the window it is re-calculated, If you need a different behaviour , override this cllas and provide a different implementation to WM_SIZE message: an implementation that will reset again (RECT) rcBar. (The member that keeps the area of scrolled bar.
void SetFadeEffect(BOOL bSet) { m_bUseFadeEffect = bSet; } BOOL GetFadeEffect() { return m_bUseFadeEffect; }Some functions to manage animation : stop,play it etc. You may also reset frequency. Whenever you change frequency , timer stops , timer is reset with new frequency and animation starts again (if it originally was on) with the new frequency. You may also set a position yourself (SetProgressPosition).
BOOL Play(); BOOL Pause(); int SetFrequency(int nFrequency=60); BOOL IsPlaying() { return this->m_bPlaying; } BOOL SetProgressPosition(int nPos,BOOL bShowText=TRUE);Some functions are still unimplemented such as "SetTextFormat". wait for the next version. You may set text to window (WM_SETTEXT is handled) , but it still causes much flickerring. (drawing should be optimized)
Drawing is done in two major functions
void PaintBarArea(CDC &dc,int x,int y,int w,int h,COLORREF color); void PaintBar(CDC &dc,LPCTSTR lpszTitle);As for drawing the function "PaintBarArea" draws a vertical line of the same color. (This function is called many times! and slow!)
void CProgress::PaintBarArea(CDC &dc,int x,int y,int w,int h,COLORREF color) { CBrush brush(color); CBrush* pOldBrush = dc.SelectObject(&brush); dc.PatBlt(x,y,w,h,PATCOPY); dc.SelectObject(pOldBrush); } /* Paints the bar of that is in progress : whith some optimizations still needs some work - flickers when there's text within */ void CProgress::PaintBar(CDC &dc,LPCTSTR lpszTitle) { COLORREF clrFrom = clrFG; // the beginning color , COLORREF clrTo = clrBK; // the ending color // Get the intensity values for the ending color int r1 = GetRValue(clrFrom); // red int g1 = GetGValue(clrFrom); // green int b1 = GetBValue(clrFrom); // blue // Get the intensity values for the begining color int r2 = GetRValue(clrTo); // red int g2 = GetGValue(clrTo); // green int b2 = GetBValue(clrTo); // blue static int x1,x2; if (m_nDirection==UP) { x1 = max(rcBar.left,m_nPosition-m_nWidth); x2 = m_nPosition; } else { // DOWN x1 = m_nPosition; x2 = min(rcBar.right,m_nPosition+m_nWidth); } /* static variables are instantiated once so quicker this way (and less fragmentation : since this function is activated many times ) */ static int xDelta= max(m_nWidth/NCOLORSHADES,1); // width of one shade band static int r, g, b; static int pos,rDiff,gDiff,bDiff; rDiff = r1-r2; // caculate once for each (loop uses many times) gDiff = g1-g2; bDiff = b1-b2; if (m_nDirection==UP) { for (int i=x2 ; i>x1 ; i-=xDelta ) { pos= (x2-i); r = (r1>r2) ? (r1 - rDiff*pos/m_nWidth) : (r1 - rDiff*pos/m_nWidth); g = (g1>g2) ? (g1 - gDiff*pos/m_nWidth) : (g1 - gDiff*pos/m_nWidth); b = (b1>b2) ? (b1 - bDiff*pos/m_nWidth) : (b1 - bDiff*pos/m_nWidth); PaintBarArea(dc, i, rcBar.top, xDelta, rcBar.bottom, RGB(r, g, b)); } } else { for (int i=x1 ; i < x2 ; i+=xDelta ) { pos= (i-x1); r = (r1>r2) ? (r1 - rDiff*pos/m_nWidth) : (r1 - rDiff*pos/m_nWidth); g = (g1>g2) ? (g1 - gDiff*pos/m_nWidth) : (g1 - gDiff*pos/m_nWidth); b = (b1>b2) ? (b1 - bDiff*pos/m_nWidth) : (b1 - bDiff*pos/m_nWidth); PaintBarArea(dc, i, rcBar.top, xDelta, rcBar.bottom, RGB(r, g, b)); } } // extra area to paint if (m_nDirection==UP) { // paint area is to the left to the bar if (m_nPosition-m_nWidth>rcBar.left) { int nStartPoint = max(rcBar.left,m_nPosition-m_nWidth-xDelta); if (m_nPosition-m_nWidth-xDelta-MOVEMENT < rcBar.left) nStartPoint--; PaintBarArea(dc, nStartPoint, rcBar.top, xDelta, rcBar.bottom, clrTo);//RGB(r, g, b)); } } else { //DOWN // paint area is to the right of bar if (m_nPosition+m_nWidth< rcBar.right) { int toPaint = min(xDelta,rcBar.right-(m_nPosition+m_nWidth)); PaintBarArea(dc, m_nPosition+m_nWidth, rcBar.top, toPaint, rcBar.bottom, clrTo);//RGB(r, g, b)); } } static int PIXELSALWAYSARE = 2; // pixels that will stay in target color // when bar reaches the end : (stay in dark color) if (!m_bUseFadeEffect) { if (m_nPosition+MOVEMENT>=rcBar.right) { // UP int toPaint = min(m_nWidth-PIXELSALWAYSARE,rcBar.right-m_nPosition-PIXELSALWAYSARE); PaintBarArea(dc, m_nPosition-m_nWidth, rcBar.top, m_nWidth-PIXELSALWAYSARE, rcBar.bottom, clrTo); } else if (m_nPosition-MOVEMENT< rcBar.left) // DOWN PaintBarArea(dc, PIXELSALWAYSARE, rcBar.top, m_nPosition+m_nWidth, rcBar.bottom, clrTo); } }
Move to downloads downloads