Icon Progress Bar

Environment: [VC6]

This is a progress bar control that uses icons.

First create a static control of the required size in the dialog editor and set the style you want.

The 'Attach' function sets up the following features:

  • The icon to use in the progress bar.

  • The number of pixels to increment between each icon.

  • The background colour. (Optional, the default is the 3D face colour)

  • The stagger value. (Optional, the default is zero)
    This is the number of pixels that the icons will be offset each time, creating a zigzag pattern.

'Attach' will calculate the number of icons that can be contained within the static control and attempt to centralise the bar within it. It will derive the orientation of the bar by using the aspect ratio of the control.

'SetIconChange' allows you to modify the icon that will be displayed from a certain value.

Example

// ICON1 for the whole bar, increment of 4, pale 
// blue background, stagger of 2
Attach( IDC_ICON_PROGRESS, 
        this, 
      IDI_ICON1, 
      4, 
      RGB(128, 128, 255), 
      2);

SetRange(0, 100);
SetPos(0);

// Use icon 2 from position 10 to 100
SetIconChange(IDI_ICON2, 10);

// Use icon 3 from position 30 to 100
SetIconChange(IDI_ICON3, 30);

// Use icon 4 from position 70 to 100
SetIconChange(IDI_ICON4, 70);

Final result

0 - 9    = ICON1
10 - 29    = ICON2
30 - 69    = ICON3
70 - 100 = ICON4

The acuracy of the changeover position will depend on the number total of icons displayed for the range.

i.e.

If, in the above example, there were only 6 icons in total, the changeover position of 30 should occur at 1.78 icons. This of course can't happen so the changeover icon index will be rounded down to 1. This equates to a position of 17. The more icons you can fit into the bar the more accurate it will be.

CIconProgress supports all of the normal CProgressCtrl member functions.

///////////////////////////////////////////////
// CIconProgress window

class CIconProgress : public CWnd
{
// Construction
public:
   CIconProgress();

   void Attach(UINT control_id,
          CWnd *parent,
          UINT icon_id, 
          int  increment, 
          int  stagger = 0);

   void Attach(UINT     control_id,
          CWnd     *parent,
          UINT     icon_id, 
          int        increment, 
          COLORREF background,
          int        stagger = 0);

   void SetRange(short lower, 
            short upper);
   
   void SetRange32(int lower, 
         int upper);
   
   void GetRange(int &lower,
            int &upper);

   int  SetPos(int position);

   int  GetPos();
   
   int  OffsetPos(int offset);

   int  SetStep(int step);

   int  StepIt();

   void SetIconChange(UINT icon_id, int position);

// Attributes
public:

// Operations
public:

// Overrides
   // ClassWizard generated virtual function overrides
   //{{AFX_VIRTUAL(CIconProgress)
   //}}AFX_VIRTUAL

// Implementation
public:
   virtual      ~CIconProgress();

private:
   int      GetNumberOfIcons(int position); 

   static const int   HORIZONTAL;
   static const int   VERTICAL;

   CBrush      background_brush;
   HICON      hicon;
   COLORREF   background_colour;
   int      icon_increment;
   int      orientation;
   int      total_number_of_icons;
   int      number_of_icons;
   int      icon_major;
   int      icon_minor;
   int      window_major;
   int      window_minor;
   int      start_major;
   int      start_minor;
   int      stagger_distance;
   int      upper;
   int      lower;
   int      position;
   int      step;
   RECT      window_rect;

   CArray hicon_array;

   // Generated message map functions
protected:
   //{{AFX_MSG(CIconProgress)
   afx_msg void OnPaint();
   afx_msg BOOL OnEraseBkgnd(CDC* pDC);
   //}}AFX_MSG
   DECLARE_MESSAGE_MAP()
};

// Constants
const int CIconProgress::HORIZONTAL = 0;
const int CIconProgress::VERTICAL   = 1;

// Message map
BEGIN_MESSAGE_MAP(CIconProgress, CWnd)
   //{{AFX_MSG_MAP(CIconProgress)
   ON_WM_PAINT()
   ON_WM_ERASEBKGND()
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//////////////////////////////////////////
// Constructor

CIconProgress::CIconProgress()
{
	upper    = 100;
	lower    = 0;
	position = 0;
	step     = 10;
}

//////////////////////////////////////////
// Destructor

CIconProgress::~CIconProgress()
{
   background_brush.DeleteObject();
}

//////////////////////////////////////////
// SetInitial - default colour

void CIconProgress::Attach( UINT control_id, 
                            CWnd *parent, 
                            UINT icon_id, 
                            int increment, 
                            int stagger)
{
   Attach( control_id, 
            parent, 
         icon_id, 
         increment, 
         GetSysColor(COLOR_3DFACE), 
         stagger);
}

//////////////////////////////////////////
// SetInitial - specified colour

void CIconProgress::Attach( UINT control_id, 
                            CWnd *parent, 
                            UINT icon_id, 
                            int increment, 
                            COLORREF background, 
                            int stagger)
{
   SubclassDlgItem(control_id, parent);

   // Store the parameters.
   icon_increment    = increment;
   background_colour = background;
   stagger_distance  = stagger;

   // Create the background brush.
   background_brush.CreateSolidBrush(background_colour);

   // Get the icon handle.
   hicon = AfxGetApp()->LoadIcon(icon_id);

   // Find the client window size.
   GetClientRect(&window_rect);

   // Set the orientation and the major and minor axis.
   // Major is in the direction of progress.
   if (window_rect.right > window_rect.bottom)
   {
      orientation = HORIZONTAL;
   }
   else
   {
      orientation = VERTICAL;
   }
   
   switch (orientation)
   {
      case HORIZONTAL:
      {
         icon_major   = GetSystemMetrics(SM_CXICON);
         icon_minor   = GetSystemMetrics(SM_CYICON);
         window_minor = window_rect.bottom;
         window_major = window_rect.right;
         break;
      }
   
      case VERTICAL:
      {
         icon_minor   = GetSystemMetrics(SM_CXICON);
         icon_major   = GetSystemMetrics(SM_CYICON);
         window_major = window_rect.bottom;
         window_minor = window_rect.right;
         break;
      }
   }

   // Adjust for daft icon increment.
   if (icon_increment == 0)
   {
      icon_increment = 1;
   }

   // Find the number of icons that will fit in the window.
   total_number_of_icons = 1;
   while (((total_number_of_icons * icon_increment)
            + icon_major) < window_major)
   {
      total_number_of_icons++;
   }

   // Fill the icon array with the default icon
   hicon_array.SetSize(total_number_of_icons);
   for (int i = 0; i < total_number_of_icons; i++)
   {
      hicon_array[i] = hicon;
   }

   // Find the start points.
   switch (orientation)
   {
      case HORIZONTAL:
      {
        // Left.
        start_major = (window_major - 
            (((total_number_of_icons - 1) 
           * icon_increment) 
           + icon_major)) / 2;
         break;
      }

      case VERTICAL:
      {
        // Bottom.
        start_major = ((window_major 
            + (((total_number_of_icons - 1) 
          * icon_increment) + icon_major)) / 2) 
          - icon_major;
      }
   }

   start_minor = (window_minor - 
                  icon_minor - 
               stagger_distance) / 2;
}

//////////////////////////////////////////
// SetPos

int CIconProgress::SetPos(int new_position)
{
   int old_position;
      
   old_position    = position;
   position        = new_position;
   position        = min(upper, max(lower, position)); 
   number_of_icons = GetNumberOfIcons(position);
   
   Invalidate();

   return old_position;
}

//////////////////////////////////////////
// OffsetPos

int CIconProgress::OffsetPos(int offset)
{
   int old_position;
   
   old_position    = position;
   position       += offset;
   position        = min(upper, max(lower, position)); 
   number_of_icons = GetNumberOfIcons(position);
   
   Invalidate();

   return old_position;
}

//////////////////////////////////////////
// SetRange

void CIconProgress::SetRange(short lower_range, 
                             short upper_range)
{
   SetRange32(lower_range, upper_range);
}

//////////////////////////////////////////
// SetRange32

void CIconProgress::SetRange32( int lower_range, 
                                int upper_range)
{
   lower           = lower_range;
   upper           = upper_range;
   position        = min(upper, max(lower, position)); 
   number_of_icons = GetNumberOfIcons(position);
   
   Invalidate();
}

//////////////////////////////////////////
// SetIconChange

void  CIconProgress::SetIconChange( UINT icon_id, 
                                    int position)
{
   HICON hicon = AfxGetApp()->LoadIcon(icon_id);

   // Where to start from
   int change_icon_index = GetNumberOfIcons(position);

   // Fill part of the array with the new icon
   for ( int i = change_icon_index; 
         i < total_number_of_icons; 
        i++)
   {
      hicon_array[i] = hicon;
   }
}

//////////////////////////////////////////
// SetStep

int CIconProgress::SetStep(int new_step)
{
   int old_step;
   
   old_step = step;
   step     = new_step;

   return old_step;
}

//////////////////////////////////////////
// StepIt

int CIconProgress::StepIt()
{
   int old_position;
   
   old_position    = position;
   position       += step;
   position        = min(upper, max(lower, position)); 
   number_of_icons = GetNumberOfIcons(position);
   
   Invalidate();

   return old_position;
}

//////////////////////////////////////////
// GetPos

int CIconProgress::GetPos()
{
   return position;
}

//////////////////////////////////////////
// GetRange

void CIconProgress::GetRange(int &lower_range, 
                             int &upper_range)
{
   lower_range = lower;
   upper_range = upper;
}

//////////////////////////////////////////
// GetNumberOfIcons

int CIconProgress::GetNumberOfIcons(int position)
{
   int   n_icons;
   float delta = (float)(position - lower);
   float range = (float)(upper - lower + 1);
   
   float range_per_icon = range / total_number_of_icons;

   // Just in case of rounding errors
   if (position == upper)
   {
      n_icons = total_number_of_icons;
   }
   else
   {
      n_icons = (int)(delta / range_per_icon);
   }

   return n_icons;
}

//////////////////////////////////////////
// CIconProgress message handlers

void CIconProgress::OnPaint() 
{
   CPaintDC dc(this);
   CDC      memdc;
   CBitmap    bitmap;
   int      x, y, count;
   BOOL    do_stagger = FALSE;

   // Create a memory copy to draw to.
   memdc.CreateCompatibleDC(&dc);
   bitmap.CreateCompatibleBitmap(&dc, 
                         window_rect.right, 
                       window_rect.bottom);
   memdc.SelectObject(&bitmap);

   // Clear the background.
   memdc.FillRect(&window_rect, &background_brush);
   
   // Draw the icons.
   switch (orientation)
   {
      case HORIZONTAL:
      {
         for ( x = start_major, 
               count = 0; count < number_of_icons; 
               x += icon_increment, count++)
         {
           if (do_stagger)
           {
             memdc.DrawIcon(x, 
                         start_minor + stagger_distance,
                       hicon_array[count]);
           }
           else
           {
             memdc.DrawIcon(x, start_minor, hicon_array[count]);
           }

           do_stagger = !do_stagger;
         }
         break;
      }

      case VERTICAL:
      {
         for ( y = start_major, count = 0; 
              count < number_of_icons;
              y -= icon_increment, count++)
         {
            if (do_stagger)
            {
               memdc.DrawIcon(start_minor + 
                              stagger_distance, 
                           y, 
                           hicon_array[count]);
            }
            else
            {
               memdc.DrawIcon(start_minor, 
                              y, 
                              hicon_array[count]);
            }

            do_stagger = !do_stagger;
         }
         break;
      }
   }

   // Copy it to the screen.
   dc.BitBlt( 0, 0, 
              window_rect.right, 
            window_rect.bottom, 
            &memdc, 
            0, 0, 
            SRCCOPY);

   // Delete the tempory resources.
   memdc.DeleteDC();
   bitmap.DeleteObject();
}

BOOL CIconProgress::OnEraseBkgnd(CDC* pDC) 
{
   // Indicate that it is already erased.
   return TRUE;
}

Downloads

Download demo project - 16Kb
Download source - 3Kb


Comments

  • Det er bedre end at købe Monster Studio hovedtelefoner

    Posted by pelyab596 on 07/17/2013 12:19pm

    Udover alle andre hovedtelefoner par, beats Dre lyd præsentation er temmelig god, ikke som “mudrede” og “uklar” støjende lyde, som ofte er problemer med hver hovedtelefon. Nå, denne genre af hovedtelefon er meget godt for den elektroniske, hård rock, og midt tempo hip-hop musik, som helt sikkert kan rock you ingen tvivl om. billige beats by dre er meget til salg i forskellige musik-butikker og du kan købe dem fra enhver stikkontakt til pluk det til din musik dille. Nå, ingen tvivl om, at du kan have en god musik ved at have det, efter alt dette er ‘beats by Dre «og navnet i sig selv er alt for at angive dets kvalitet. Så ven, så hvis du er en af dem, der søger for at have hovedtelefoner til dit musiksystem eller spekulerer at købe det til din iPhone eller iPod, kan du placere din ordre online. Du kan købe denne genre af hovedtelefoner lige fra sidder fra din hjemmecomputer, logge på hjemmesiden at udforske Dre beats rækkevidde at smage essensen af musikken. [url=http://beatsbydrdredanmark.blinkweb.com/]beats by dre Hovedtelefoner[/url] Den særlige er bedre end headset er ideelle til ipods på markedet, Apple iPhones og bærbare forskellige modeller af iPods. Disse mennesker giver den komplette lyd du rigtig skal lytte til. Opholder drevne øretelefoner derudover du erhverver øget volumen. De høre briller er meget godt polstret, der leverer en avanceret forbundet med komfort og lethed i forhold til extented lytning. Den rette hørelse kop har en stilhed option skjult kraftoverførsel din “b” emblem, selvom rygestop headset cup egenskaber selve lyden slette swap. [url=http://beatsbydretilbud.webspawner.com/]beats by dre[/url] Det kan ikke være potentiel, at du er en total musik-freak, og du måske ikke tænker højtydende trådløse hovedtelefoner! Disse gadgets er de korrekte kammerater specielt inde du lytter til musik bestræbelser. Der er en række organisationer, først og fremmest de velkendte mærker, som Sony, Philips og Samsung osv., der tilfældigvis er i massiv organisering af elektroniske varer og tjenesteydelser og hovedtelefoner med Monstor Diddybeats White trådløse bestemmelser er en af dem. Du vil finde bestemte funktioner og faktorer, som har at blive alvorligt tages i betragtning, når 1 vælger denne fantastiske enhed. Målet er normalt at støde på en sund god kvalitet, der er helt sikkert virkelig vidunderlig og afslappende mod sindet også.

    Reply
  • clarisonic extra reduced issue is elbow in australia

    Posted by iouwanzi on 06/06/2013 01:21pm

    [url=http://www.australiaclarisonic.com/]clarisonic brush[/url] Victoria Secret 2012, la dernière conférence de maillots de bain sur la belle Miranda Kerr trésor et sexy top model Candice Swanepoel lors de la sélection se tailler un style de grands ghd lisseur cheveux de milliers de féminité sexy. Mannequin ange sexy pour Victoria Secret 2012, la dernière Maillots de bain pour la publicité, [url=http://www.australiaclarisonic.com/clarisonic-classic]clarisonic classic[/url] modestes caractéristiques consistent non pas un mais deux défini guides mise en page talents Deco, simultanément disponible ce sont unique. Toute la galerie Scarlet comprend un sac soie cramoisi tolérant à chaleur merveilleuse lesoù aider à stocker le fer à lisser vos plaques ghd IV Styler cheveux pour s’assurer vous rose profond, par le biais de non pas un mais deux trucs cheveux sauvages dont une instance appropriée.Écrit à l’intérieur d’une boîte commune inflammed inanité habilitée par période de Style déco, tous le groupe écarlate fantaisie ghd styler intemporelle métal jaune comprend une alimentation réduite option rouge et en outre une mallette de rangement, un voyage fabuleux crinière sèche-cheveux ghd, couple de crinière de films et en outre un important carton satiné résistant à la chaleur. [url=http://www.australiaclarisonic.com/clarisonic-classic]clarisonic classic[/url] Il existe plusieurs variétés d’instruments conformément à la l’extérieur de votre cuir chevelu. Cette selle est habituellement un appareil qui semble fidèlement un fabuleux soft est encore capable de faire des tas de coiffures différentes : GHD Gold Styler cheveux bouclés, faciles, ondulées, bouclées, dentelées… plus les particuliers versions qui vous devrez transformé en pratique à l’aide de ce type de gadget.

    Reply
  • Nike Draught Max+instagram, at one's desire you hold the color to wear on your feet!

    Posted by madytreathy on 04/21/2013 11:05am

    Recollect in 2008, if not earlier, when Nike launched ahead of the affluent shoe color projects, the war cry "Shoot Your Colours", "Nike PhotoiD" layout, [url=http://markwarren.org.uk/property-waet.cfm]air max 90[/url] response has not been as hearty as expected. About, 2008 Canon IXUS 80 IS Digital greetings card arcade but contrariwise 8 million pixels, Nokia, the facile phone market is the one leadership, NikeiD was boost to color in the photos as a infrastructure quest of sneakers excise color, although exciting, but does provoke some. Instagram which communicate this item fun and modest, Nike PHOTOiD homeopathic upgrade customization services, recently [url=http://markwarren.org.uk/goodbuy.cfm]nike free run uk[/url] released a unique plan. That such iD can you realize pictures as instagram account shoe color, little while volunteer Nike Breeze Max shoes and Nike Refresh Max 1, Nike Show Max 90 953 options. Interested in children's shoes, you [url=http://northernroofing.co.uk/roofins.cfm]nike free run 3[/url] can every conform with each other's proper website photoid.Nike.com, in addition to browse other people's artistic charge, or you can try to upload your own instagram photo, build your own Nike Air Max.

    Reply
  • Application note.

    Posted by Legacy on 02/10/2002 12:00am

    Originally posted by: John Wellbelove

    The icon progress bar could be used for showing the ratios of certain items.

    i.e.
    If you have a study of the number of people with blue and brown eyes, it could be represented as follows.

    Assuming 30% blue and 70% brown.

    SetRange(0, 100) // 0 to 100%
    SetIconChange(IDI_BLUE_EYE, 0);
    SetIconChange(IDI_BROWN_EYE, 30); // Change to brown at 30%
    SetPos(100); // Show the whole bar

    The result will be a bar with 30% blue and 70% brown.

    Reply
  • comment from jim

    Posted by Legacy on 02/05/2002 12:00am

    Originally posted by: jim

    cool!

    if u know how to learn to create a database in c++ ,
    tell me.
    jim from Greece.

    Reply
  • Interesting!

    Posted by Legacy on 02/02/2002 12:00am

    Originally posted by: Sword


    It looks so funny!

    I think it is useful to game design.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • VMware vCloud® Government Service provided by Carpathia® is an enterprise-class hybrid cloud service that delivers the tried and tested VMware capabilities widely used by government organizations today, with the added security and compliance assurance of FedRAMP authorization. The hybrid cloud is becoming more and more prevalent – in fact, nearly three-fourths of large enterprises expect to have hybrid deployments by 2015, according to a recent Gartner analyst report. Learn about the benefits of …

Most Popular Programming Stories

More for Developers

RSS Feeds