Back to Amir Israeli Homepage

[CProgress :Netscape style busy(downloading) bar ]

This article was contributed by Amir Israeli Amir Israeli.
Amir Israeli Web Site

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.
I defined sseveral nice colors for animation so I won't need to remember these colors. (The example project uses 2 of them)
Some other interesting functions are those who get/set fade effect. When animation turns from side to side : left to right and the opposite) the window should repaint with its background color. When m_bUseFadeEffect=TRUE the window wont paint, and it causes a nice visual effect.
	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

History

Date Posted: February 3, 2001

Home  |  Links  |  About