Windows Controls: Progress Bars

 

Overview

A progress bar is a Windows control that displays (small) rectangles that are each filled with a color. These (small) rectangles are separate but adjacent each other so that, as they display, they produce a bar. To have the effect of a progress bar, not all these rectangles display at the same time. Instead, a numeric value specifies how many of these (small) rectangles can display at one time.

There are two types of progress bars and various characteristics they can have. Although most progress bars are horizontal, the control can assume a vertical position. We mentioned that a progress bar is made of small colored rectangles. These rectangles can display distinctively from each other although they are always adjacent. Alternatively, these rectangles can be "glued" to produce a smooth effect, in which case they would not appear distinct.

  1. Start a new Win32 Project and name it ProgressTime
  2. Create it as a Windows Application and Empty Project
  3. Display the Add Resource dialog box and double-click Dialog
  4. Resize it to 320 x 166
  5. Change its ID to IDD_CONTROLS_DLG
  6. Change its Caption to Progress Bar Example
  7. Change its X Pos to 200 and change its Y Pos to 180
  8. Save All
  9. Add a new C++ (Source) File and name it Exercise
  10. Implement it as follows:
     
    #include <windows.h>
    #include "Resource.h"
    
    //---------------------------------------------------------------------------
    HWND hWnd;
    HINSTANCE hInst;
    LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    				   LPSTR lpCmdLine, int nCmdShow)
    {
    	hInst = hInstance;
    
    	DialogBox(hInst, MAKEINTRESOURCE(IDD_CONTROLS_DLG),
    	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg,
    		       WPARAM wParam, LPARAM lParam)
    {
    	switch(Msg)
    	{
    	case WM_INITDIALOG:
    		return TRUE;
    
    	case WM_COMMAND:
    		switch(wParam)
    		{
    		case IDOK:
    			EndDialog(hWndDlg, 0);
    			return TRUE;
    		case IDCANCEL:
    			EndDialog(hWndDlg, 0);
    			return TRUE;
    		}
    		break;
    	}
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
  11. Test the application and return to your programming environment

Progress Bar Creation

Because a progress control belongs to the family of Common Controls, before using it, call the InitCommonControlsEx() function. When initializing the INITCOMMONCONTROLSEX structure, assign the ICC_PROGRESS_CLASS to its dwICC member variable.

To create a progress bar, call the CreateWindowEx() function and specify the class name as PROGRESS_CLASS.

  1. To add a progress to the progress, change the Exercise.cpp source file as follows:
     
    #include <windows.h>
    #include <commctrl.h>
    #include "Resource.h"
    
    //---------------------------------------------------------------------------
    HWND hWnd;
    HINSTANCE hInst;
    LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    				   LPSTR lpCmdLine, int nCmdShow)
    {
    	hInst = hInstance;
    
    	DialogBox(hInst, MAKEINTRESOURCE(IDD_CONTROLS_DLG),
    	          hWnd, reinterpret_cast<DLGPROC>(DlgProc));
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg,
    		       WPARAM wParam, LPARAM lParam)
    {
    	INITCOMMONCONTROLSEX InitCtrlEx;
    
    	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    	InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
    	InitCommonControlsEx(&InitCtrlEx);
    
    	switch(Msg)
    	{
    	case WM_INITDIALOG:
    		CreateWindowEx(0, PROGRESS_CLASS, NULL,
    		               WS_CHILD | WS_VISIBLE,
    			      20, 20, 260, 17,
    			      hWndDlg, NULL, hInst, NULL);
    		return TRUE;
    
    	case WM_COMMAND:
    		switch(wParam)
    		{
    		case IDOK:
    			EndDialog(hWndDlg, 0);
    			return TRUE;
    		case IDCANCEL:
    			EndDialog(hWndDlg, 0);
    			return TRUE;
    		}
    		break;
    	}
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
  2. Add the comctl32.lib to your project
     
  3. Test the application
     
  4. Return to your programming environment

Progress Bar Characteristics

Most progress bars appear horizontally and their default orientation. Here is an example:

If you want the control to be oriented vertically, OR the PBS_VERTICAL style progress:

A progress bar, by default, is presented with small distinct rectangles. Here is an example:

If you prefer not to distinguish the small divisions of the progress bar, OR the PBS_SMOOTH style. It would then appear as follows:

  1. To make the progress bar smooth, change its style as follows:
    //---------------------------------------------------------------------------
    LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg,
    		       WPARAM wParam, LPARAM lParam)
    {
    	INITCOMMONCONTROLSEX InitCtrlEx;
    
    	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
    	InitCtrlEx.dwICC  = ICC_PROGRESS_CLASS;
    	InitCommonControlsEx(&InitCtrlEx);
    
    	switch(Msg)
    	{
    	case WM_INITDIALOG:
    		CreateWindowEx(0, PROGRESS_CLASS, NULL,
    		               WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
    			      20, 20, 260, 17,
    			      hWndDlg, NULL, hInst, NULL);
    		return TRUE;
    
    	case WM_COMMAND:
    		switch(wParam)
    		{
    		case IDOK:
    			EndDialog(hWndDlg, 0);
    			return TRUE;
    		case IDCANCEL:
    			EndDialog(hWndDlg, 0);
    			return TRUE;
    		}
    		break;
    	}
    
    	return FALSE;
    }
    //---------------------------------------------------------------------------
  2. Save All

Progress Bar Messages

A progress bar is usually added to indicate the progression of an activity. To guide with this, it uses a range of values between which it draws its small colored rectangles. After creating the control, the first thing you may want to do is to specify its range of values. This is done by calling the SendMessage() function and passing the PBM_SETRANGE message using the following syntax:

SendMessage(HWND hWnd, PBM_SETRANGE, 0, MAKEPARAM(int Min, int Max);

The wParam argument is not used. Therefore, you can pass it as 0. The lParam argument must be passed as a MAKEPARAM macro which takes two arguments. Here is an example:

SendMessage(hProgress, PBM_SETRANGE, 0, MAKELPARAM(0, 220)); 

If the range of values already exists and you want to find it out, you can call the SendMessage() function with the PBM_GETRANGE as message:

 

SendMessage(hProgress, PBM_GETRANGE, (WPARAM)(MAKELPARAM)(BOOL), (LPARAM)(MAKELPARAM)(PPBRANGE, ppBRange));