Click here to Skip to main content
15,867,330 members
Articles / Programming Languages / C++

New Pie Progress Control with 3D Look

Rate me:
Please Sign up or sign in to vote.
3.72/5 (9 votes)
26 Oct 20022 min read 88.2K   1.2K   24   8
Now you can have a pie control replacement for a progress bar, in 3D look

Sample Image - 3D-Pie_progress_control.gif

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).

C++
#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.

C++
CButton m_ctlPieProgress;

to:

C++
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().

C++
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:

C++
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.


Written By
Web Developer
Hong Kong Hong Kong
innovating, managing and developing next generation media products and services

Comments and Discussions

 
GeneralThis pie chart seems to not show properly at 100% [modified] Pin
hyvee_doughboy25-Jul-07 5:10
hyvee_doughboy25-Jul-07 5:10 
QuestionFlickering Pin
LuPossj2-Jul-07 20:50
LuPossj2-Jul-07 20:50 
Questionclear bkg? Pin
Christopher Stratmann14-Sep-06 9:14
Christopher Stratmann14-Sep-06 9:14 
Generala drawing fix... Pin
Orkblutt17-Aug-06 6:59
Orkblutt17-Aug-06 6:59 
GeneralRe: a drawing fix... Pin
Nynaeve10-May-07 10:11
Nynaeve10-May-07 10:11 
Questionhow to use non dialog box application Pin
shaikesu9-Dec-05 0:36
shaikesu9-Dec-05 0:36 
QuestionHit testing? Pin
fred@yahoo.com22-Jul-02 8:00
fred@yahoo.com22-Jul-02 8:00 
Generalcode in the article Pin
Jason Henderson22-Jul-02 3:20
Jason Henderson22-Jul-02 3:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.