Status Progress Feedback






4.68/5 (9 votes)
Jul 7, 2004
7 min read

69820

2732
A status control that can provide feedback to a user on the progress of one or many operations
Description
There are often times when an application needs to perform a lengthy operation-or series of operations; if the operation takes long enough, the programmer will likely want to display the status of the operation as-well-as provide the user with a means of discontinuing the operation. This submission contains a number of MFC classes to provide the programmer with a means by which the status of an operation can be feedback-to and cancelled-from a waiting user.
Design
We will use two primary classes to track the status of an operation. One class will be the actual status control. The status control class will be responsible for displaying the current status to the user. The status control class will allow a user to cancel any operation(s) that are updating the status control. The second class will be the status progress class. The status progress class will be the means by which an operation will communicate with the status control. The status progress class will be configured with a number of steps to perform and each step can, in turn, be broken-up into a number of substeps. When a step is completed the status progress object should increment its current step and check for a cancellation request.
The status control object will initially need to be divided into an initial number of operations or steps. This initial division of the status control's progressbar will be stored in a status progress object. As the steps are performed, the status progress object should increment its current step and check for a cancellation request. If a step has any substeps, the status progress object handling the step can divide its current step into a number of substeps.
Each status progress object will keep track of its current step and its piece of the status control's progressbar, or range. A progress object's range will be set by its parent progress object or the status control-depending on whether it is an initial step or a substep. When a progress object's step is incremented, it will also update the status control's progressbar.
We will make the status control appear to be running independent of the operations that are updating it by processing all the application messages each time the progressbar's position is updated.
Classes
NOTE: The following classes are contained in statusctrl.cpp and statusctrl.h, and they will require the referencecount.h and smartptr.h header files.
CStatusControl
CStatusControl
is the primary class that displays an operation's status to the user and accepts cancellation requests. You can create the control
using one of the create methods provided in the class. Once created, use configuration methods-provided in the class-for custom configuration of
the control. Once configured and displayed, use the progress related methods to break the status control's progressbar into an initial number
of steps-each of which can be further subdivided into substeps using the
CStatusProgress
class. Once the status control is setup and providing
feedback to the user, use the status methods to query the cancellation status or manually cancel the operation.
Creation Methods:
BOOL CreateInPlaceOf(CWnd* pWnd, DWORD dwStyle = NULL)
This method creates the control, and places it in the position of the window indicated by thepWnd
argumentBOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL)
This method creates the control using theCWnd::Create
method.BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam = NULL)
This method creates the control using theCWnd::CreateEx
method.
Configuration Methods:
void SetProgressCtrlText(LPCSTR lpszText)
This method allows the user to configure the text that should appear in the progressbar controlvoid SetProgressCtrlStyle(DWORD dwStyle);
This method allows the user to configure the style that should be used in the progressbar controlSP_USE_PBS_STYLE
- Use defaultCProgressCtrl
painting routineSP_BLOCK_STYLE
- Use the class's paint routine to display status blocksSP_SMOOTH_STYLE
- Use the class's paint routing to display smooth statusSP_SHOWPERCENT
- ORed withSP_SMOOTH_STYLE
orSP_BLOCK_STYLE
to indicate the percent completed showed be displayedSP_SHOWMSG
- ORed withSP_SMOOTH_STYLE
orSP_BLOCK_STYLE
to indicate the user will provide text to be displayed
void SetProgressCtrlNumBlocks(UINT nNumBlocks);
This method allows the user to configure the number of blocks that should be displayed in the progressbar controlBOOL MoveProgressCtrl(RECT& rect)
This method allows the user to resize/reposition the progressbar controlBOOL MoveCancelButton(RECT& rect);
This method allows the user to resize/reposition the cancel button
Progress Methods:
void SetSteps(int nNumSteps, CStatusProgress& retSubProgress)
This method is used to break the initial status control's progressbar into a number of steps. The retSubProgress argument is used to return the configured status control's step information. TheretSubProgress
can be used to further subdivide the current step into a number of substeps.void SetProgressPos(int nPos, BOOL bDispatchAllPendingMessages = TRUE);
This method is used to set the progressbar position. You should never need to call this, as theCStatusProgress
object's call it when their current step is incremented.
Status Methods:
void Reset(void)
This method is used to reset the cancel status and the progressbar positionvoid Cancel(void)
This method is used for manual cancellations from outside of the controlBOOL IsCancelled()
This method is used to query the cancellation status
CStatusProgress
CStatusProgress
is the means by which a CStatusControl
can have its status updated and queried for a cancellation
request. After the initial CStatusControl
object is created, it is initially broken-up into a number of steps; these
steps are returned in a CStatusProgress
object. A CStatusProgress
object can be broken-up into smaller steps, and
these steps are returned in another CStatusProgress
object.
void Init(void)
Initializes the objectvoid Attach(CStatusControlPtr pStatusCtrl)
Attaches theCStatusControl
to the objectvoid Cancel(void)
Cancels the status controlBOOL IsCancelled(void)
Queries for a status control cancellationvoid SetSteps(int nNumSteps, CStatusProgress& retSubProgress)
Breaks the object's current step into a number of substepsvoid StepIt(BOOL bDispatchAllPendingMessages = TRUE)
Increments the objects current stepvoid SetText(LPCSTR lpszText)
Sets the text that should appear in the status control's progressbar
CStatusControlPtr
CStatusControlPtr
is a smartpointer class that wraps a CStatusControl
object. Its is used in the
CStatusProgress
class to
ensure that the CStatusControl
pointed to by the class is not destroyed until all
CStatusProgess
objects using the control
are destroyed.
CStatusProgressControl
CStatusProgressControl
is a subclass of the CProgressCtrl
MFC class. It was written in order to provide an option for displaying
the percent completed in the progressbar. It also provides the ability to
specify how many blocks should appear if the progressbar
is configured to display blocks. The class adds three methods to the CProgressCtrl
class.
void SetStyle(DWORD dwStyle)
This method allows the user to specify how the control should be painted.SP_USE_PBS_STYLE
- Use defaultCProgressCtrl
painting routineSP_BLOCK_STYLE
- Use the class's paint routine to display status blocksSP_SMOOTH_STYLE
- Use the class's paint routing to display smooth statusSP_SHOWPERCENT
- Used withSP_SMOOTH_STYLE
orSP_BLOCK_STYLE
to indicate the percent completed showed be displayedSP_SHOWMSG
- Used withSP_SMOOTH_STYLE
orSP_BLOCK_STYLE
to indicate the user will provide text to be displayed
void SetNumBlocks(UINT nNumBlocks)
This method allows the user to specify the number of blocks that should be displayed when the style isSP_BLOCK_STYLE
void SetMessage(LPCSTR lpszMsg)
This method allows the user to specify the text to display in the progressbar
CStatusDlg
CStatusDlg
is a class that provides a modeless dialog container for a
CStatusControl
. It is provided as a means to place the
CStatusControl
into a separate window.
void DoModeless(CWnd* pParent = NULL, LPCSTR lpszTitle = "", DWORD dwProgressStyle = SP_USE_PBS_STYLE, UINT nNumBlocks = 0, LPCSTR lpszText = "")
This method creates a modeless dialog box containing a status control.CStatusControlPtr GetStatusControlPtr();
This method returns the status control contained in the dialog.void SetSteps(int nNumSteps, CStatusProgress& retSubProgress);
This method simply forwards the request to the contained status control.void Reset(void);
This method simply forwards the request to the contained status control.void Cancel(void);
This method simply forwards the request to the contained status control.BOOL IsCancelled();
This method simply forwards the request to the contained status control.
Example of usage
... ... int nNumberOfSteps = 100; // Create and display the status control... CStatusControlPtr pStatusCtrl = new CStatusControl; pStatusCtrl->Create("STATUS", WS_CHILD | WS_VISIBLE, CRect(10, 10, 210, 32), this, NULL, NULL); // Allocate the initial steps from the status control... CStatusProgress progress; pStatusCtrl->SetSteps(nNumberOfSteps, progress); // Perform the operations... for (int nStep = 0; nStep < nNumberOfSteps; nStep++) { // Perform the current operation... Sleep(100); // Update the current step... progress.StepIt(); // Check for cancellation... // If we're received a cancellation request... if (progress.IsCancelled()) // Discontinue operation... break; } ... ...
See the sourcecode provided for more examples of how the status control can be used.
Caveats
If a long operation is not broken into small enough steps, a cancellation might not get processed within an acceptable time limit. The status progress is recursively broken-up into steps to represent the division of operations, and hence does not reflect the actual time of each operation.
Contact Information
- Roland Trainor - rolandtrainor@frontiernet.net