Home

Windows Controls: Progress Bars

 

Introduction to Progress Bars

 

Description

Besides the progress control, Microsoft Visual C++/MFC provides two other progress-oriented controls: the Microsoft Progress Control Version 5.0 and the Microsoft Progress Control Version 6.0 with the main difference on their ability to assume one or two orientations.

 

Practical LearningPractical Learning: Introducing Progress Bar

  1. To start a new application, on the main menu, click File -> New Project...
  2. In the middle list, click MFC Application.
    Set the name to PledgeDistribution2
  3. Click OK
  4. In the first page of the wizard, click Next
  5. In the second page of the wizard, click Dialog-Based and click Next
  6. In the third page, set the Dialog Title to Pledge Distribution
  7. Click Finish
  8. Click TODO and press Delete
  9. Click OK and press Delete
  10. Change the Caption of the Cancel button to Close

Creating a Progress Bar

To add a progress bar to your application, from the Insert ActiveX Control dialog box, select the desired one:

Insert ActiveX Control

After selecting the option, click OK.

Practical LearningPractical Learning: Creating Progress Bars

  1. Right-click the dialog box and click Insert ActiveX Control
  2. In the Insert ActiveX Control dialog box, click Microsoft ProgressBar Control, Version 6.0
  3. Click OK
  4. Right-click the progress bar and click Copy
  5. Press Ctrl + V twice to paste it twice
  6. In the Class View, expand the name of the project
  7. In the top section (of the Class View), click CPledgeDistributionApp
  8. In the bottom section of the Class View, double-click InitInstance
  9. Create a message box as follows:
    BOOL CPledgeDistributionApp::InitInstance()
    {
    	// InitCommonControlsEx() is required on Windows XP if an application
    	// manifest specifies use of ComCtl32.dll version 6 or later to enable
    	// visual styles.  Otherwise, any window creation will fail.
    	INITCOMMONCONTROLSEX InitCtrls;
    	InitCtrls.dwSize = sizeof(InitCtrls);
    	// Set this to include all the common control classes you want to use
    	// in your application.
    	InitCtrls.dwICC = ICC_WIN95_CLASSES;
    	InitCommonControlsEx(&InitCtrls);
    
    	CWinApp::InitInstance();
    
    
    	AfxEnableControlContainer();
    
    	// Create the shell manager, in case the dialog contains
    	// any shell tree view or shell list view controls.
    	CShellManager *pShellManager = new CShellManager;
    
    	// Standard initialization
    	// If you are not using these features and wish to reduce the size
    	// of your final executable, you should remove from the following
    	// the specific initialization routines you do not need
    	// Change the registry key under which our settings are stored
    	// TODO: You should modify this string to be something appropriate
    	// such as the name of your company or organization
    	SetRegistryKey(_T("Local AppWizard-Generated Applications"));
    
    	CPledgeDistributionDlg dlg;
    	m_pMainWnd = &dlg;
    
        MessageBox(NULL,
    	_T("This application is used by a fictitious company or agency ")
    	_T("that raises money for edutional institutions.")
    	_T("The employees of the company call people and organizations. ")
    	_T("They ask the called person for a pledge (an amount).")
    	_T("After setting the amount, they ask the called person how he ")
    	_T("wants to distribute that money for (how much money) each of ")
    	_T("the three schools should from that amount."),
    	_T("Pledge Distribution"), MB_OK);
    
    	INT_PTR nResponse = dlg.DoModal();
    
    	if (nResponse == IDOK)
    	{
    		// TODO: Place code here to handle when the dialog is
    		//  dismissed with OK
    	}
    	else if (nResponse == IDCANCEL)
    	{
    		// TODO: Place code here to handle when the dialog is
    		//  dismissed with Cancel
    	}
    
    	// Delete the shell manager created above.
    	if (pShellManager != NULL)
    	{
    		delete pShellManager;
    	}
    
    	// Since the dialog has been closed, return FALSE so that we exit the
    	//  application, rather than start the application's message pump.
    	return FALSE;
    }
  10. Design the dialog box as follows:
     
    Pledge Distribution
     
    Control ID Caption Additional Properties
    Static Text Static Text   Amount Pledged:  
    Edit Box Edit Control IDC_AMOUNT_PLEDGED   Align Text: Right
    Static Text Static Text   Scholl Name  
    Static Text Static Text   Proportion of funds received  
    Static Text Static Text   Amount Received  
    Static Text Static Text   1:  
    Edit Box Edit Control IDC_SCHOOL1    
    Edit Box Edit Control IDC_RATE_VALUE1   Align Text: Center
    Disabled: True
    Spin Spin IDC_SPIN_RATE1   Auto Buddy: True
    Set Buddy Integer: True
    Static Text Static Text   %  
    Progress Bar   IDC_PROPORTION1    
    Edit Text Edit Control IDC_AMOUNT1   Align Text: Right
    Static Text Static Text   2.  
    Edit Box Edit Control IDC_SCHOOL2    
    Edit Box Edit Control IDC_RATE_VALUE2   Align Text: Center
    Disabled: True
    Spin Spin IDC_SPIN_RATE2   Auto Buddy: True
    Set Buddy Integer: True
    Static Text Static Text   %  
    Progress Bar   IDC_PROPORTION2    
    Edit Box Edit Control IDC_AMOUNT2   Align Text: Right
    Static Text Static Text   3.  
    Edit Box Edit Control IDC_SCHOOL3    
    Edit Box Edit Control IDC_RATE_VALUE3   Align Text: Center
    Disabled: True
    Spin Spin Control IDC_SPIN_RATE3   Auto Buddy: True
    Set Buddy Integer: True
    Static Text Static Text   %  
    Progress Bar   IDC_PROPORTION3    
    Edit Box Edit Control IDC_AMOUNT3   Align Text: Right
    Static Text Static Text IDC_MESSAGE    
    Button Button IDCANCEL Close  
  11. Right-click each of the following controls (based on their IDs) and click Add Variable...
  12. Add the Member Variables as follows:
     
    ID
    Category Type Name
    IDC_AMOUNT_PLEDGED Value double m_AmountPledged
    IDC_SCHOOL1 Value CString m_School1
    IDC_RATE_VALUE1 Control Edit m_Value1Control
    IDC_RATE_VALUE1 Value double m_RateValue1
    IDC_SPIN_RATE1 Control CSpinButtonCtrl m_SpinRate1
    IDC_PROPORTION1 Control CProportion1 m_Proportion1
    IDC_AMOUNT1 Value double m_Amount1
    IDC_SCHOOL2 Value CString m_School2
    IDC_RATE_VALUE2 Control Edit m_Value2Control
    IDC_RATE_VALUE2 Value double m_RateValue2
    IDC_SPIN_RATE2 Control CSpinButtonCtrl m_SpinRate2
    IDC_PROPORTION2 Control CProportion1 m_Proportion2
    IDC_AMOUNT2 Value double m_Amount2
    IDC_SCHOOL3 Value CString m_School3
    IDC_RATE_VALUE3 Control Edit m_Value3Control
    IDC_RATE_VALUE3 Value double m_RateValue3
    IDC_SPIN_RATE3 Control CSpinButtonCtrl m_SpinRate3
    IDC_PROPORTION3 Control CProportion1 m_Proportion3
    IDC_AMOUNT3 Value double m_Amount3
    IDC_MESSAGE Value CString m_Message
  13. In the Class View, click CPledgeDistributionDlg and double-click OnInitDialog
  14. Initialize the spin controls as follows:
    BOOL CPledgeDistributionDlg::OnInitDialog()
    {
    	CDialogEx::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)
    	{
    		BOOL bNameValid;
    		CString strAboutMenu;
    		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    		ASSERT(bNameValid);
    		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_SpinRate1.SetRange(0, 100);
    	m_SpinRate1.SetPos(50);
    	m_SpinRate2.SetRange(0, 100);
    	m_SpinRate2.SetPos(25);
    	m_SpinRate3.SetRange(0, 100);
    	m_SpinRate3.SetPos(25);
    	
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
  15. Return to the dialog box and click the Amount Pledged edit control
  16. In the Properties window, click the Control Events button Control Events
  17. Click EN_CHANGE, then click the arrow and select <Add> OnEnChangeAmountPledge
  18. Implement the event as follows:
    void CPledgeDistributionDlg::OnEnChangeAmountPledged()
    {
        // TODO:  If this is a RICHEDIT control, the control will not
        // send this notification unless you override the CDialogEx::OnInitDialog()
        // function and call CRichEditCtrl().SetEventMask()
        // with the ENM_CHANGE flag ORed into the mask.
    
        // TODO:  Add your control notification handler code here
        UpdateData();
    
    	if( m_AmountPledged == 0.00 )
    	{
    		m_Rate1Control.EnableWindow(FALSE);
    		m_Rate2Control.EnableWindow(FALSE);
    		m_Rate3Control.EnableWindow(FALSE);
    	}
    	else
    	{
    		m_Rate1Control.EnableWindow(TRUE);
    		m_Rate2Control.EnableWindow(TRUE);
    		m_Rate3Control.EnableWindow(TRUE);
    	}
    
    	UpdateData(FALSE);
    }
 
 
 

Characteristics of a Progress Bar

 

The Orientation of a Progress Bar

After adding a progress bar to a parent window, it assumes a horizontal position. This is controlled by the Orientation property (not available in Version 5.0) whose default value is 0 - ccOrientationHorizontal. If you want the progress bar to be vertical, change this property to a 1 - ccOrientationVertical value.

The Minimum and Maximum Values of a Progress Bar

The range of values that a progress bar can assume is set using the Min property for the minimum value and the Max field for the highest value. This can be done in the Properties window.

The values of a progress bar are float, unlike the progress control that mostly uses integers. To programmatically set the minimum value for the progress bar, call its put_Min() member function:

void put_Min(float newValue);

To set the maximum value, call the put_Max() member function:

void put_Max(float newValue);

These two member functions expect a float number as argument. If these values have already been set, you can retrieve them by calling the get_Min() or the get_Max() member functions respectively.

Practical LearningPractical Learning: Setting the Minimum and Maximum Values

  1. Change the OnInitDialog event as follows:
    BOOL CPledgeDistributionDlg::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    
    	// 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_SpinRate1.SetRange(0, 100);
    	m_SpinRate1.SetPos(50);
    	m_SpinRate2.SetRange(0, 100);
    	m_SpinRate2.SetPos(25);
    	m_SpinRate3.SetRange(0, 100);
    	m_SpinRate3.SetPos(25);
    
    	m_Proportion1.put_Min(0);
    	m_Proportion1.put_Max(100);
    	m_Proportion2.put_Min(0);
    	m_Proportion2.put_Max(100);
    	m_Proportion3.put_Min(0);
    	m_Proportion3.put_Max(100);
    
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }

The Value of a Progress Bar

To set the initial value of the progress bar or to change its value any time, you can call the put_Value() member function. Also, at anytime, you can retrieve the position of the control by calling the get_Value() member function.

Practical LearningPractical Learning: Setting the Value of a Progress Bar

  1. On the main menu, click Project -> Class Wizard...
  2. In the MFC Class Wizard, in the Class Name, select CPledgeDistributionDlg, and click Commands.
    In the list of Commands, click IDC_SPIN_RATE1
  3. In the Messages list, click UDN_DELTAPOS
  4. Click Add Handler...
  5. Set the name to OnProportion1
  6. Click OK
  7. In the Commands list, click IDC_SPIN_RATE2
  8. In the Messages list, double-click UDN_DELTAPOS
  9. Set the name to OnProportion2
  10. Click OK
  11. In the Commands list, click IDC_SPIN_RATE3
  12. In the Messages list, double-click UDN_DELTAPOS
  13. Set the name to OnProportion3
  14. Click OK
  15. Click Edit Code
  16. Implement the events as follows:
    void CPledgeDistributionDlg::OnProportion1(NMHDR *pNMHDR, LRESULT *pResult)
    {
        LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
        // TODO: Add your control notification handler code here
        UpdateData();
    
        double Rest;
        int   Value1, Value2, Value3;
        int   Rate1, Rate2, Rate3;
    
        // Get the current value of each spin control
        Value1 = m_SpinRate1.GetPos();
        Value2 = m_SpinRate2.GetPos();
        Value3 = m_SpinRate3.GetPos();
    	
        // Calculate the percentage of each value based on the amount pledged
        m_Amount1 = m_AmountPledged * Value1 / 100;
        m_Proportion1.put_Value(m_SpinRate1.GetPos());
        m_Amount2 = m_AmountPledged * Value2 / 100;
        m_Proportion2.put_Value(m_SpinRate2.GetPos());
        m_Amount3 = m_AmountPledged * Value3 / 100;
        m_Proportion3.put_Value(m_SpinRate3.GetPos());
    
        // Calculate the amount left
        Rest = m_AmountPledged - m_Amount1 - m_Amount2 - m_Amount3;
        
        // If the whole amount has not yet been distributed, display a message
        if( Rest > 0 )
    	m_Message.Format(_T("$%.2f still to be used"), Rest);
        else // If the whole amount has been distributed, don't display a message
    	m_Message = _T("");
    
        UpdateData(FALSE);
        *pResult = 0;
    }
    
    void CPledgeDistributionDlg::OnProportion2(NMHDR *pNMHDR, LRESULT *pResult)
    {
    	LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    	// TODO: Add your control notification handler code here
    	OnProportion1(pNMHDR, pResult);
    
    	*pResult = 0;
    }
    
    
    void CPledgeDistributionDlg::OnProportion3(NMHDR *pNMHDR, LRESULT *pResult)
    {
    	LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
    	// TODO: Add your control notification handler code here
    	OnProportion1(pNMHDR, pResult);
    
    	*pResult = 0;
    }
  17. To test the application, press F5
     
    Pledge Distribution
     
    Pledge Distribution
  18. Close it and return to your programming environment

Using a Progress Bar

Because the user cannot change the value of a progress bar, it does not fire value-related events. On the other hand, it provides you with the ability to do something when the user clicks or positions the mouse over the control. If your user simply positions the mouse or moves it on top of the progress bar, it fires the MouseMove event. At the same time, if the user presses a mouse button on the progress bar, it fires the MouseDown event. When the user releases the mouse, the MouseUp event is sent. Clicking the progress bar causes it to fire the Click event.

 
 
   
 

Home Copyright © 2010-2011 FunctionX, Inc.