Click here to Skip to main content
15,867,704 members
Articles / Desktop Programming / MFC
Article

CSkinProgress

Rate me:
Please Sign up or sign in to vote.
4.97/5 (102 votes)
11 Jul 2003Zlib9 min read 543.9K   14.1K   209   90
A bitmapped progress bar in a status bar with optional completion status message

Introduction

Originally developed based on the work of Chris Maunder on CProgressBar. This CSkinProgress class intend to be used everywhere some calculations are needed. It features :

  • Bitmapped progress bar (default, from resource - which need little code modification - or from external source)
  • Auto-sizing of the progress bar
  • Auto-sizing of the text
  • Paning of the progress bar
  • Optional completion status message (percent or timed)
  • And more...

All features can be changed during run-time :

  • Switch in real-time between different bitmaps according to your mood or needs (normal mode, alert bar, ...)
  • Change the text to show different states of the process being calculated
  • Change the range of the progress bar with resample if more accuracy provided
  • And more...

Now the explanation of the features...

Features

1. Mode

CSkinProgress allows to create a progress bar in a status bar or in a dialog. All depends on the constructor you will use and which parameters you will provide to CSkinProgress.

Status Bar

Status Bar - 02-StatusBar.png - 14868 bytes - 600 x 365

CSkinProgress
(
  LPCTSTR  i_poStrMessage,
  int      i_nUpper       = 100,
  int      i_nProgress    = cSPT_PERCENT,
  int      i_nPane        = 0,
  int      i_nSize        = 200,
  CBitmap* i_poBitmap     = NULL
#ifdef dCSP_SLIDERBAR_METHOD
 ,BOOL     i_bReverse     = false
#endif // dCSP_SLIDERBAR_METHOD
);

With this constructor you can create a progress bar with text, completion status, select the pane, the bitmap and if the progress bar have to be displayed from the end.

Dialog

Dialog - 03-Dialog.png - 14139 bytes - 600 x 367

#ifdef dCSP_DIALOG_PROGRESS
CSkinProgress
(
  CWnd*    i_poWndProgress,
  int      i_nUpper       = 100, 
  CBitmap* i_poBitmap     = NULL,
#ifdef dCSP_SLIDERBAR_METHOD
  BOOL     i_bReverse     = false,
#endif // dCSP_SLIDERBAR_METHOD
  CWnd*    i_poWndMessage = NULL,
  LPCTSTR  i_poStrMessage = NULL,
  int      i_nProgress    = cSPT_NONE
);
#endif // dCSP_DIALOG_PROGRESS

If the dCSP_SLIDERBAR_METHOD define is activated, you can use this constructor to create a progress bar inany CWnd object with a parent (important) in the dialog. You don't have to provide a pane number, but a CWnd anchor used to create the progress bar, and another CWnd in which the text will be displayed.

2. Sizing

You can provide a size for the progress bar. This size is only used when the progress bar is located in the status bar and in pane 0, thus share it with the text. You can select 3 modes of text sharing :

Positive size

If the given size is positive, the size of the progress bar is FIXED. Thus the text is wrapped if there is not enough place.

Zero size

Zero size - 05-ZeroSize.png - 11613 bytes - 600 x 120

If the given size is null, the size of the progress bar fits the remaining place left by the text. Thus the text is never wrapped if there is not enough place. It can only be if there is a completion message that takes too much place.

Negative size

If the given size is negative, the size of the progress bar fits the remaining place left by the text if there is no enough place, otherwise the given size is used.

3. Text

You can provide any text you want (Note: not too long - up to 128 characters).

Text one - 07-TextOne.png - 13150 bytes - 600 x 80

Text two - 08-TextTwo.png - 10867 bytes - 600 x 80

4. The Panes

You can create as many panes as you want in the status bar, just follow these rules...

Add an ID in the string table, in the ID_INDICATORS section, otherwise the text will appears in the pane. The longer the text, the more the width of the pane will be important !

Now add this user pane ID in the 'indicators' array in the beginning of the 'MainFrm.cpp' file. First entry is pane 0.

Main Frm - 10-MainFrm.png - 35606 bytes - 600 x 160

Then, select the pane number you will use to display the progress bar. For instance, the user pane is number 0 where the text is located :

Pane 0 - 11-PaneZero.png - 9964 bytes - 600 x 80

Pane 1 - 12-PaneOne.png - 10062 bytes - 600 x 80

You can even use system panes, such pane 3 where the NUM-LOCK indicator is located:

Pane 3 - 13-PaneThree.png - 9925 bytes - 600 x 80

5. The completion message

You can ask to CSkinProgress to add a message at the end of your text in order to provide the current completion status. The progress bar gives a graphical information, but sometimes it is useful to have more information. An enum list is fitted with increasing value with a different meaning for each of them. Here are the different kinds of messages :

  • cSPT_NONE : Don't add any messages, quite fast.

     

  • cSPT_PERCENT : Add a simple text percent completion report, a bit slower than NONE


  • cSPT_TIMED : Add a full features message that gives the date/time of start, the current percentage of completion, the remaining percentage, the remaining time, and the expected date/time of end - quite slow

     

  • cSPT_AUTOSIZE : Automaticaly select the best message between PERCENT and TIMED according to the remaining place in pane 0 - the slowest.

     

  • NEGATIVE : Suppress the parenthesis (NEW)

    You can now delete the parenthesis by providing a negative progress number, like you can stop the wrapping of the text by providing a negative size for the progress bar in pane 0 !

6. The bitmap

You can select the default and embedded bitmap (which is the same as IDB_BMP_AQUA) or use a resource bitmap (needs to change conditions for the compilation and modify the code in CSkinProgress::SetBitmap(...))

You can also provide a bitmap to the CSkinProgress

User bitmap - 20-BitmapLuna.png - 9698 bytes - 600 x 80

7. Reverse display

When not selected, the progress bar start from the left (or top in a vertical progress bar).

Normal display - 21-Normal.png - 10626 bytes - 600 x 80

For some reasons you can select to display the progress bar from its end. Especially useful for vertical bar in dialog, so that it starts from the bottom, like a thermometer.

The Code

Constructors

Status bar

CSkinProgress::CSkinProgress
( // Default constructor
)

Create a default progress bar in the status bar with "Work in progress" and the default constructor values given below.

CSkinProgress::CSkinProgress
( // Default constructor with parameters for status bar usage
  LPCTSTR     i_poStrMessage, // Text to display
  int         i_nUpper,       // = 100          : Default range from 0 to 
                              //                  i_nUpper
  int         i_nProgress,    // = cSPT_PERCENT : Message type to add to the 
                              // text
  int         i_nPane,        // = 0            : Pane number in which 
                              // display the progress bar
  int         i_nSize,        // = 200          : Size of the progress bar if 
                              //                  in pane 0
  CBitmap*    i_poBitmap      // = NULL         : Pointer to a user bitmap
#ifdef dCSP_SLIDERBAR_METHOD
 ,BOOL        i_bReverse      // = false        : Reverse display of the 
                              // progress bar
#endif // dCSP_SLIDERBAR_METHOD
)

WARNING : This constructor has changed since the original version 1.00/1.12dev !

The most simple status bar constructor is :

CSkinProgress::CSkinProgress
( // Default constructor with parameters for status bar usage
  LPCTSTR     i_poStrMessage, // Text to display
)

Dialog

#ifdef dCSP_DIALOG_PROGRESS
CSkinProgress::CSkinProgress
( // Default constructor with parameters for dialog usage
  CWnd*       i_poWndProgress,  // Pointer to the anchor CWnd to use for the 
                                // progress bar
  int         i_nUpper,         // = 100,      : Default range from 0 to 
                                // i_nUpper
  CBitmap*    i_poBitmap,       // = NULL      : Pointer to a user bitmap
#ifdef dCSP_SLIDERBAR_METHOD
  BOOL        i_bReverse,       // = false,    : Reverse display of the 
                                //               progress bar
#endif // dCSP_SLIDERBAR_METHOD
  CWnd*       i_poWndMessage,   // = NULL,     : Pointer to the anchor CWnd
                                //               to use for the text pane
  LPCTSTR     i_poStrMessage,   // = NULL      : Text to display,
  int         i_nProgress       // = cSPT_NONE : Message type to add to the
                                //               text
)
#endif // dCSP_DIALOG_PROGRESS

To use the dialog constructor, make sure the dCSP_DIALOG_PROGRESS define is set. You can bypass the text pane declaration, as I have put the i_bReverse parameter in the middle of the function parameter list. Beware of your coding, you may use also the dCSP_SLIDERBAR_METHOD define yourself in order to provide conditionnal compilated facilities to your own code.

The most simple status bar constructor is :

CSkinProgress::CSkinProgress
( // Default constructor with parameters for status bar usage
  CWnd*       i_poWndProgress,  // Pointer to the anchor CWnd to use for the 
                                // progress bar
)

Destructor

CSkinProgress::~CSkinProgress
( // Destructor
)

Bitmap Process

BOOL CSkinProgress::SetBitmap
( // Change of progress bar image
  CBitmap* i_poBitmap           // = NULL : Pointer to an existing bitmap
#ifndef dCSP_TIMED_REDRAW
 ,BOOL     i_bDisplay           // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)

The two following addi(c)tive functions are used by CSkinProgress::SetBitmap(...) in order to copy/convert TRUE/COLOR bitmap pictures (don't support mapped color bitmap yet). They can be used for your own purposes :

BOOL CSkinProgress::CopyBitmap
( // Copy a bitmap
  CBitmap* o_poBitmap,          // Pointer to an EXISTING but NOT INITIALIZED 
                                // bitmap
  CBitmap* i_poBitmap           // Pointer to the source bitmap
)
BOOL CSkinProgress::ConvBitmap
( // Convert a bitmap to a specified device context
  CBitmap*    o_poBitmap,       // Pointer to an EXISTING but NOT INITIALIZED 
                                // bitmap
  CBitmap*    i_poBitmap,       // Pointer to the source bitmap
  CDC*        i_poDC            // = NULL : Pointer to the DC to use for the
                                // conversion, if NULL use the current DC
)

Progress Interface

BOOL CSkinProgress::SetRange
( // Set the new range
  int  i_nLower,                // Minimum limit
  int  i_nUpper,                // Maximum limit
  int  i_nStep,                 // = 1     : Step increment
  BOOL i_bResamble              // = false : Resample the current position 
                                // from the new Lower and Upper values
#ifndef dCSP_TIMED_REDRAW
 ,BOOL i_bDisplay               // = true  : Display the changes
#endif // dCSP_TIMED_REDRAW
)
int CSkinProgress::SetPos
( // Set <M_NRIGHT> value
  int  i_nPos                   // Set a new current position
#ifndef dCSP_TIMED_REDRAW
 ,BOOL i_bDisplay               // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)
int CSkinProgress::OffsetPos
( // Forward of <NOFFSET> value
  int  i_nOffset                // Add the offset to the current position 
                                // (can be negative)
#ifndef dCSP_TIMED_REDRAW
 ,BOOL i_bDisplay               // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)
int CSkinProgress::SetStep
( // Set <M_NSTEP> value
  int i_nStep                   // Set the step increment
)             
int CSkinProgress::StepIt
( // Forward of <M_NSTEP> value
#ifndef dCSP_TIMED_REDRAW
  BOOL i_bDisplay               // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
) 

Extended Progress Interface

BOOL CSkinProgress::SetSize
( // Set size of the progress bar in pane 0 
  int  i_nSize                  // Set the size of the progress bar
#ifndef dCSP_TIMED_REDRAW
 ,BOOL i_bDisplay               // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)
int CSkinProgress::GetSize
( // Get width or height of the progress bar in pixel, mostly used in 
  // CSkinSlider
)
int CSkinProgress::GetPos
( // Get <M_NRIGHT> value
  BOOL i_bPercent               // = false
)
int CSkinProgress::GetStep
( // Get <M_NSTEP> value
)
int CSkinProgress::GetLower
( // Get <M_NLOWER> value
)
int CSkinProgress::GetUpper
( // Get <M_NUPPER> value
)
#ifdef dCSP_SLIDERBAR_METHOD
int CSkinProgress::SetStart
( // Set <M_NLEFT> value
  int  i_nStart                 // Set a new start position
#ifndef dCSP_TIMED_REDRAW
 ,BOOL i_bDisplay               // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)
#endif // dCSP_SLIDERBAR_METHOD
#ifdef dCSP_SLIDERBAR_METHOD
int CSkinProgress::GetStart
( // Get <M_NLEFT> value
  BOOL i_bPercent               // = false
)
#endif // dCSP_SLIDERBAR_METHOD
void CSkinProgress::Reset
( // Reset the progress bar
#ifndef dCSP_TIMED_REDRAW
  BOOL i_bDisplay               // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)

Text Interface

BOOL CSkinProgress::SetText
( // Set the new text
  LPCTSTR i_poStrMessage        // New text to display      
#ifndef dCSP_TIMED_REDRAW
 ,BOOL    i_bDisplay            // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)
BOOL CSkinProgress::SetProgress
( // Set <M_NPROGRESSTEXT> value
  int  i_nProgress              // Set progress text
#ifndef dCSP_TIMED_REDRAW
 ,BOOL i_bDisplay               // = true : Display the changes
#endif // dCSP_TIMED_REDRAW
)
int CSkinProgress::GetProgress
( // Get <M_NPROGRESSTEXT> value
)

Update Process

BOOL CSkinProgress::RefreshPanes
( // Resize the text pane and the progress bar
) 

Compiling the Source

Manage the CSkinProgress features with conditionnal compilation ! Here the explanation of each compilation define :

  • dCSP_DIALOG_PROGRESS : Activate the use of
    CSkinProgress 
    in dialogs
  • dCSP_TIMED_REDRAW : When set/uncommented, don't redraw/refresh the text/progress bar at each event but only 50 times a second (enough for accuracy). In some loops, CSkinProgress::StepIt() can be easily called far more than 50 times a second !
  • dCSP_VERTICAL_BAR : Activate the full vertical bar calculation. Not used in the status bar, but can be used when dCSP_DIALOG_PROGRESS is set
  • dCSP_SLIDERBAR_METHOD : Turns the progress bar into a full slider bar. Allows the bar to be reverse displayed, so uncomment this define if you want to use the 'reverse' feature of CSkinProgress

Specific defines are used for very experimental purposes, use them with care :

  • dCSP_RESOURCE_BITMAP : Use a resource bitmap as default bitmap. The current ID name of the resource bitmap is IDB_AQUABAR, but you mey change this by modifying the name of the ressource bitmap in CSkinProgress::SetBitmap(...)
  • dCSP_CREATE_BITMAP_FILE : At the end of CSkinProgress::SetBitmap(...), create a source file in the root of C: ! Used to change the default embedded bitmap : create a
    CSkinProgress 
    and provide a user bitmap, you'll get the converted bitmap into a source file !
  • dCSP_DISPLAY_STRETCH : Display the stretched picture used for the image list creation. There is hardly usage of this feature, beside documentation or verification of the CSkinProgress::SetBitmap(...) function

The Progress Bar Bitmap

Now to finish this little introduction to the

CSkinProgress 
graphic engine, the overview of the method used to create the progress bar picture. A bitmap is provided to CSkinProgress::SetBitmap(...)...

Photon bar - 23-Photon.png - 389 bytes - 180 x 32

This bitmap is divided into 9 parts...

From left to right, here are the meaning and associated ID define :

  • cSPB_START : The start of the progress bar background
  • cSPB_BEFORE : The element before the beginning of the bar, could be an hilight
  • cSPB_LEFT : The left part of the bar, its beginning
  • cSPB_CENTER : The center part of the progress bar, could be interpreted as a grab knot
  • cSPB_BAR : The bar body
  • cSPB_RIGHT : The right part of the bar, its end
  • cSPB_AFTER : The element after of the end of the bar, could be a shadowing
  • cSPB_BACKGROUND : The progress bar background
  • cSPB_END : The end of the progress bar background

To create your own bitmap skin, make any bitmap with 9 parts like above. The height of the bitmap is not really important (BTW not too large - no more than 32 pixels, of course) and the width should be multiple of 9 (important), thus : width % 9 = 0 ! Have a look at the bonus/hidden bitmaps to understand that/how CSkinProgress allows you to make funny things ;)

Relative positions of the keys elements are calculated on the range of the progress bar and its current position. Then, once get these values as percent, calculate the absolute positions of these key elements. There is now just the place them on the progress bar image in a defined order so that some elements could hide some others, like on layers in Paint Shop Pro.

Blue columns are the exact positions of the elements.
Red columns are the base columns based on the width of an element.

The three/four letters are the key of comments into the CSkinProgress::OnPaint() function for you to spot them easily...

Version history

Rev 1.02 : July 12 2003 14:01:53 (Kochise)

Base : CSkinProgress 1.32dev
    extracting files : no error
    parsing files : no error
    diff engine : no error
    modify.public.constructor:CSkinProgress
    touch.protected.function:CreateCommon
    modify.protected.function:ProgressInStatusBar
    modify.protected.function:ProgressInDialog
    modify.public.function:SetRange
    touch.public.function:SetPos
    modify.public.function:GetPos
    touch.public.function:SetStart
    modify.public.function:GetStart
    modify.public.function:Reset
    add.public.function:SetProgress
    add.public.function:GetProgress
    modify.public.function:RefreshPanes
    touch.protected.function:CompactText
    modify.protected.function:GetTimed
    modify.protected.function:UpdateProgress
    modify.protected.function:OnPaint
    compiling project files : no error
    packing files : no error

Rev 1.01 : July 06 2003 22:08:37 (Kochise)

Base : CSkinProgress 1.28 Devel
    extracting files : no error
    parsing files : no error
    diff engine : no error
    modify.public.constructor:CSkinProgress
    add.public.constructor:CSkinProgress
    modify.public.function:SetBitmap
    modify.public.function:ConvBitmap
    modify.public.function:SetRange
    modify.public.function:SetPos
    modify.public.function:OffsetPos
    modify.public.function:StepIt
    modify.public.function:SetSize
    add.public.function:GetSize
    add.public.function:GetPos
    add.public.function:GetStep
    add.public.function:GetLower
    add.public.function:GetUpper
    add.public.function:SetStart
    add.public.function:GetStart
    add.public.function:Reset
    modify.public.function:SetText
    mutate.function:protected.ResizeTextPane->public.RefreshPanes
    modify.public.function:RefreshPanes
    mutate.function:public.Clear->protected.Clear
    add.protected.function:GetTargetRect
    mutate.protected.function:Create->CreateCommon
    modify.protected.function:CreateCommon
    add.protected.function:ProgressInStatusBar
    add.protected.function:ProgressInDialog
    modify.protected.function:CompactText
    add.protected.function:UpdateProgress
    modify.protected.function:OnPaint
    compiling project files : no error
    packing files : no error

Rev 1.00 : May 25 2003 13:25:12 (Kochise)

First archived version and released onto CodeProject.
Base : CSkinProgress 1.12 Devel
    add.public.constructor:CSkinProgress
    add.public.constructor:CSkinProgress
    add.public.function:SetRange
    add.public.function:SetText
    add.public.function:SetSize
    add.public.function:SetBitmap
    add.public.function:CopyBitmap
    add.public.function:ConvBitmap
    add.public.function:SetPos
    add.public.function:OffsetPos
    add.public.function:SetStep
    add.public.function:StepIt
    add.public.function:Clear
    add.public.destructor:~CSkinProgress
    add.protected.function:Create
    add.protected.function:GetStatusBar
    add.protected.function:ResizeTextPane
    add.protected.function:CompactText
    add.protected.function:GetTimed
    add.protected.function:OnEraseBkgnd
    add.protected.function:OnPaint
    add.protected.function:OnSizing
    add.protected.function:OnSize
    add.protected.function:OnTimer
    compiling project files : no error
    packing files : no error

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License


Written By
Software Developer
France France
KOCH David, 41 years old
Coder (embedded, C/C++, ASM, Erlang)

Comments and Discussions

 
GeneralHi everybody ;) Some hints... Pin
Kochise12-Mar-04 7:56
Kochise12-Mar-04 7:56 
GeneralRe: Hi everybody ;) Some hints... Pin
ChauJohnthan12-May-04 7:31
ChauJohnthan12-May-04 7:31 
GeneralHtmlDialog ? Whatzdat ? Pin
Kochise17-May-04 22:53
Kochise17-May-04 22:53 
QuestionCSkinProgress in a Thread??? Pin
adeisageenious@yahoo.co.uk4-Feb-04 2:23
sussadeisageenious@yahoo.co.uk4-Feb-04 2:23 
AnswerWell, yes, that's the idea ;) Pin
Kochise17-Feb-04 7:03
Kochise17-Feb-04 7:03 
GeneralKewl thing But .. Pin
Armoghan Asif4-Nov-03 18:42
Armoghan Asif4-Nov-03 18:42 
GeneralRe: Kewl thing But .. Pin
Kochise4-Nov-03 20:19
Kochise4-Nov-03 20:19 
QuestionHow about a tooltip? Pin
mbartosik4-Nov-03 3:56
mbartosik4-Nov-03 3:56 
AnswerRe: How about a tooltip? Pin
Kochise4-Nov-03 20:31
Kochise4-Nov-03 20:31 
GeneralArgh! Can't get it to work in a View Pin
ame1210-Oct-03 7:56
ame1210-Oct-03 7:56 
GeneralYou found another Windows bug ;) Pin
Kochise12-Oct-03 4:26
Kochise12-Oct-03 4:26 
GeneralCClientDC not yet initialized in OnInitialUpdate() ! Pin
Kochise14-Oct-03 4:05
Kochise14-Oct-03 4:05 
GeneralIncoming 1.02/1.32dev soon ;) Pin
Kochise12-Jul-03 4:01
Kochise12-Jul-03 4:01 
GeneralRe: Incoming 1.02/1.32dev soon ;) Pin
Member 5267212-Jul-03 16:10
Member 5267212-Jul-03 16:10 
GeneralText in progress bar Pin
Kochise12-Jul-03 22:49
Kochise12-Jul-03 22:49 
GeneralOK, the update is on the track... Pin
Kochise6-Jul-03 21:02
Kochise6-Jul-03 21:02 
GeneralA 'little' bug remains... Pin
Kochise8-Jul-03 2:14
Kochise8-Jul-03 2:14 
GeneralRe: OK, the update is on the track... Pin
otuotu8-Jul-03 17:35
sussotuotu8-Jul-03 17:35 
GeneralPosition and size on dialogs ! Pin
Kochise8-Jul-03 19:42
Kochise8-Jul-03 19:42 
GeneralUpdate delayed to this week-end : 03/07/13 Pin
Kochise9-Jul-03 21:06
Kochise9-Jul-03 21:06 
GeneralThe update will be slightly delayed, sorry... Pin
Kochise8-Jun-03 3:44
Kochise8-Jun-03 3:44 
GeneralRe: The update will be slightly delayed, sorry... Pin
Guy Lecomte19-Jun-03 4:10
Guy Lecomte19-Jun-03 4:10 
GeneralRe: The update will be slightly delayed, sorry... Pin
Kochise19-Jun-03 5:49
Kochise19-Jun-03 5:49 
GeneralAlmost finished, not yet ready... Pin
Kochise22-Jun-03 23:37
Kochise22-Jun-03 23:37 
GeneralGreat but... Pin
Guy Lecomte30-May-03 8:18
Guy Lecomte30-May-03 8:18 

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.