New Pie Progress Control with 3D Look






3.72/5 (9 votes)
Jul 22, 2002
2 min read

89063

1188
Now you can have a pie control replacement for a progress bar, in 3D look
Introduction
I have been looking for a pie control that would use the skin images instead of simple colors and just could not find that. And I struggled quite a lot to make it but ..:( anyway so found out another solution that is 3D pie control that could satisfy my needs. I got it developed with one of my bright colleagues, Amit Ganguly, who is a fresh engineer and strong with mathematics. So guys, just download it, use it, and let me know your comments.
How to Use It
This is very simple to use. Just add a button to your project and make member variables of the button. Include the following line at the top of the dialog box's header file (if you are making a dialog box based application as my demo project with the article).
#include "PieProgress.h"
Now you have included the class CPieProgress
. It's time to make an object of this class, change the following code in the header file.
CButton m_ctlPieProgress;
to:
CPieProgress m_ctlPieProgress;
Of course, if the member variable of the button earlier created by you, is named m_ctlPieProgress
. All is done, all you have to do now is initialize the pie control. Add the following lines of code in your dialog box's implementation class in the function OnInitDialog()
.
BOOL CPieControlDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_ctlPieProgress.SetRange(0,100);
m_ctlPieProgress.SetProgressColors(RGB(255,0,0),RGB(0,255,0));
SetTimer(1978,500,NULL);
return TRUE; // return TRUE unless you set the focus to a control
}
I have set a timer here to see the progress. So it's all done and you have a 3D-pie control in your project. Enjoy.........
Behind the Scenes
Nothing magical here. It's the magic of subclassing. I derived the pie control's class directly from CWnd
and have the magical drawing function DrawPie()
get called from OnPaint()
after checking that the progress value lies in the range set as follows:
void CPieProgress::DrawPie(CZipDC * pDC,CPoint CntrPt,CRect Rect)
{
CBrush BkgndBrh;
CBrush FrgndBrh;
BkgndBrh.CreateSolidBrush(clrComplete);
FrgndBrh.CreateSolidBrush(clrIncomplete);
iSemi_ht = 0.6 * Rect.Height() /2;
iSemi_lt = Rect.Width()/2;
PieRect.top = CntrPt.y - iSemi_ht;
PieRect.bottom = CntrPt.y + iSemi_ht;
PieRect.left = CntrPt.x - iSemi_lt;
PieRect.right = CntrPt.x + iSemi_lt;
StrtPt.x = CntrPt.x;
StrtPt.y = CntrPt.y + iSemi_ht;
EndPt = StrtPt;
pDC->SelectObject(&BkgndBrh);
pDC->Pie(PieRect.operator LPRECT(),StrtPt,EndPt);
iPer = ((nValue - nLow)* 100/(nHigh - nLow));
EndPt = GetPerPoint(iPer,iSemi_lt,iSemi_ht,CntrPt);
pDC->SelectObject(&FrgndBrh);
pDC->Pie(PieRect.operator LPRECT(),StrtPt,EndPt);
Rect_1.bottom = CntrPt.y;
Rect_1.right = CntrPt.x;
Rect_1.top = CntrPt.y - 10;
Rect_1.left = CntrPt.x - iSemi_lt;
Rect_2.top = CntrPt.y - 10;
Rect_2.left =CntrPt.x;
Rect_2.bottom = CntrPt.y;
Rect_2.right = CntrPt.x + iSemi_lt;
if(iPer >= 25)
{
pDC->FillRect(Rect_1.operator LPRECT(),&BkgndBrh);
if(iPer >= 75)
{
pDC->FillRect(Rect_2.operator LPRECT(),&BkgndBrh);
}
else
{
pDC->FillRect(Rect_2.operator LPRECT(),&FrgndBrh);
}
}
else
{
pDC->FillRect(Rect_1.operator LPRECT(),&FrgndBrh);
pDC->FillRect(Rect_2.operator LPRECT(),&FrgndBrh);
}
if(iPer <= 50)
{
Rect_1.bottom = EndPt.y;
switch(iPer)
{
case 0:
Rect_1.right = EndPt.x ;
break;
case 1:
Rect_1.right = EndPt.x + 2;
break;
case 2:
Rect_1.right = EndPt.x + 4;
break;
case 3:
Rect_1.right = EndPt.x + 6;
break;
case 4:
Rect_1.right = EndPt.x + 8;
break;
default:
Rect_1.right = EndPt.x + 10;
break;
}
Rect_1.top = EndPt.y - 10;
Rect_1.left = EndPt.x;
pDC->FillRect(Rect_1.operator LPRECT(),&BkgndBrh);
}
else
{
Rect_1.bottom = EndPt.y;
switch(iPer)
{
case 96:
Rect_1.left = EndPt.x - 8;
break;
case 97:
Rect_1.left = EndPt.x - 6;
break;
case 98:
Rect_1.left = EndPt.x - 4;
break;
case 99:
Rect_1.left = EndPt.x - 2;
break;
case 100:
Rect_1.left = EndPt.x ;
break;
default:
Rect_1.left = EndPt.x - 10;
break;
}
Rect_1.top = EndPt.y - 10;
Rect_1.right = EndPt.x;
pDC->FillRect(Rect_1.operator LPRECT(),&FrgndBrh);
}
CntrPt.y = CntrPt.y - 10;
PieRect.top = CntrPt.y - iSemi_ht;
PieRect.bottom = CntrPt.y + iSemi_ht ;
PieRect.left = CntrPt.x - iSemi_lt;
PieRect.right = CntrPt.x + iSemi_lt;
StrtPt.x = CntrPt.x;
StrtPt.y = CntrPt.y + iSemi_ht;
EndPt = StrtPt;
pDC->SelectObject(&BkgndBrh);
pDC->Pie(PieRect.operator LPRECT(),StrtPt,EndPt);
EndPt = GetPerPoint(iPer,iSemi_lt,iSemi_ht,CntrPt);
pDC->SelectObject(&FrgndBrh);
pDC->Pie(PieRect.operator LPRECT(),StrtPt,EndPt);
pDC->MoveTo(CntrPt.x - iSemi_lt,CntrPt.y);
pDC->LineTo(CntrPt.x - iSemi_lt,CntrPt.y + 10);
pDC->MoveTo(CntrPt.x + iSemi_lt,CntrPt.y);
pDC->LineTo(CntrPt.x + iSemi_lt,CntrPt.y + 10);
}
Now you must be wondering why so much of code there. Well, this is what shows Mr. Amit Ganguly's mathematical skills. I haven't really checked what all he has written there but I think, this must be the smallest code required to draw the pie (I guess it is called Keplar's law).
Guys Help Me
Please let me know if someone has any idea about the skin based pie control...coool...so just live life ;)
History
- 27th October, 2002: Initial version
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.