Creating a Progress Bar

To create a progress bar, you can use the CreateWindow or CreateWindowEx function and specify the PROGRESS_CLASS window class, or you can create a CProgressCtrl object and use the MFC Create member function. Be sure that you include the COMMCTRL.H header file in your application and the COMCTL32.LIB file in your list of libraries. The following C code (which differs from the PROGRESS sample on the companion disc) produces a simple progress bar in the parent window's procedure. A timer sends messages to advance the bar's current position.

// Function that creates a progress bar
// Parameters:
// HWND hWndParent - Parent window of the progress bar
// RECT rclPos - Size and position of the progress bar
// WORD wID - ID of the progress bar
// HINSTANCE hInst - Current instance
// LONG lRange - Sets the range
// LONG lStep - Sets the stepping
HWND MyCreateProgressBar (HWND hWndParent, RECT rclPos, WORD wID,
HINSTANCE hInst, LONG lRange, LONG lStep)
{
HWND hWndProgress;

hWndProgress = CreateWindowEx (
OL,
PROGRESS_CLASS,
"",
WS_CHILD | WS_VISIBLE,
rclPos.x, rclPos.y, rclPos.cx, rclPos.cy,
hWndParent,
(HMENU)wID,
hInst,
NULL);

// Set the range for the progress bar.
SendMessage (hWndProgress, PBM_SETRANGE, 0L, lRange);

// Set the step.
SendMessage (hWndProgress, PBM_SETSTEP, lStep, 0L);

return (hWndProgress);
}

§

RECT rcl; // holds the size of the progress bar

switch (message)
{
case WM_CREATE:
rcl.x = 10; rcl.y = 100; rcl.cx = 500; rcl.cy = 20;
hWndProgress = MyCreateProgressBar (hWnd, rcl, ID_PROGRESS,
hInst, MAKELONG (0, 20), 1);
break;

case WM_TIMER:
if (uCurrent < uMax)
{
// Increment (step) the progress bar.
SendMessage (hWndProgress, PBM_STEPIT, 0L, 0L);
uCurrent++;
}
else
{
// We are at the end of the range - kill the timer.
KillTimer (hWnd, ID_TIMER);
uCurrent = 0;
}
break;

case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_STOP:
// Stop the progress bar.
SendMessage (hWndProgress, PBM_SETPOS, 0L, 0L);
KillTimer (hWnd, ID_TIMER);
break;

case IDM_START:
uCurrent = uMin;
SetTimer (hWnd, ID_TIMER, 500, NULL);
break;
§
}

Pretty simple stuff, you say? Think how simple it must have been to port to MFC! Well, take a look at the same work done in the MFCPROG sample. Don't forget to include AFXCMN.H in your STDAFX.H file before you try this. I created a member variable, m_Current, to keep track of the current position of the progress bar and added this variable to my view class. As you can see, it's pretty easy here, too:

// CMfcprogView message handlers

void CMfcprogView::OnTimer (UINT nIDEvent)
{
if (m_Current < m_Max)
{
m_Progress.StepIt ();
m_Current++;
}
else
{
KillTimer (1000);
m_Current = 0;
}

CView::OnTimer (nIDEvent);
}

void CMfcprogView::OnStart ()
{
m_Current = m_Min;
SetTimer (ID_TIMER, 500, NULL);
}

void CMfcprogView::OnStop ()
{
m_Progress.SetPos (0);
KillTimer (ID_TIMER);
}

int CMfcprogView::OnCreate (LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate (lpCreateStruct) == -1)
return -1;

m_Progress.Create (WS_CHILD | WS_VISIBLE,
CRect (10, 100, 500, 120),
this,
ID_PROGRESS);
m_Min = 0;
m_Max = 20;
m_Progress.SetRange (m_Min, m_Max);
m_Progress.SetStep (1);

return 0;
}