
Introduction
Hi all!! Well 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
quit 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();
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);
}
}
SetIcon(m_hIcon, TRUE); SetIcon(m_hIcon, FALSE);
m_ctlPieProgress.SetRange(0,100);
m_ctlPieProgress.SetProgressColors(RGB(255,0,0),RGB(0,255,0));
SetTimer(1978,500,NULL);
return TRUE; }
I have set a timer here to see the progress. So its 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
Hey guys please let me know if someone has any idea about the skin based pie
control...coool...so just live life ;)