MZCrumbBar Ctrl

Winner of the competition "Best C++/MFC article of March 2010" at CodeProject.com

Examples of how MZCrumbBar can look

Downloads

Introduction

I needed a breadcrumb bar like the one in Windows Vista so I could show a path and have the path to be clickable, But I also needed a crumbbar in another project, and it had nothing to do with file paths. So I build this CrumbBar controller that are generic. It can shown any string with delimiters as a crumb-bar.

Features

  • Any string with delimiter can be shown as a crumbbar
    CrumbBar showing a none file path
  • Can go into edit mode if clicked on
    (configurable on what clicks will trun it to editable).
    Go into edit mode if clicked on
  • Send notification on what item was clicked. notifications can be sent for both Single and Double clicks on all 3 mouse buttons.
  • Support 'go back' item if not all crumb items fits in the controller
    Go into edit mode if clicked on
  • Support a left margin and item spacing.
  • Support Gradient background.
  • Can easly be custom drawn to implement your own drawing of the crumb items.
    Custom draw of crumbbar items

Create the controller

Adding MZCrumbBar to a dialog.

Custom Control Properties

  1. Add a custom controller to the layout where you want to have it.
  2. Set the ID of the properties to something like IDC_CRUMBBAR.
  3. Class name in properties must be "MZCrumbBarCtrl".
  4. Then set the style flags you want. like 0x50810001. if you do not want any border (WS_BORDER) remove 0x00800000 from the value.
  5. Then Add a MZCrumbBar variable to you dialog class
  6. To connect the custom controller in the dialog layout with the m_CrumbBar variable you need to add some code into DoDataExchange.
    void CCrumbBarDemoDlg::DoDataExchange(CDataExchange* pDX)
    {
            CDialog::DoDataExchange(pDX);
            DDX_Control(pDX, IDC_CRUMBBAR, m_CrumbBar);
    }
    
  7. Then configure the controller how you want it in OnInitDialog().

Configuring

Option on when the controller should turn into Edit Mode.
Set them as StyleEx flags in Create or with MZCrumbBar::Style(...)

#define CRU_EDITOUTSIDE   0x00000010 // Click must be outside of crumb items. 
#define CRU_EDITONCLK_L   0x00000100 // Enter Edit mode on Left Click
#define CRU_EDITONDBL_L   0x00000200 // Enter edit mode on Left DblClick 
#define CRU_EDITONCLK_R   0x00000400 // Enter Edit mode on Right Click 
#define CRU_EDITONDBL_R   0x00000800 // Enter edit mode on Right DblClick 
#define CRU_EDITONCLK_M   0x00001000 // Enter Edit mode on Middle Click 
#define CRU_EDITONDBL_M   0x00002000 // Enter edit mode on Middle DblClick 
#define CRU_LASTITEMCOLD  0x00010000 // Show no hover action for the last item.
#define CRU_LASTITEMNOCLK 0x00020000 // Do not generate click action for the last item.
#define CRU_LASTITEMNODELIMITER 0x00040000  // Do not draw a delimiter for the last item.
#define CRU_DONOTSTRIPDELIMITER 0x00080000  // Do not strip double delimiter.

Flags for configuring how the delimiter show be shown. Set the option via the DelimiterMode(...) function.

#define DM_STRIP 0 // Strip the delimiter char 
#define DM_LEFT  1 // Show Delimiter in the Left part 
#define DM_RIGHT 2 // Show Delimiter in the right part 

Set Colors and Margins

 m_CrumbBar.ColorDefault( RGB(255, 0, 0));
 m_CrumbBar.ColorHot( RGB(255, 0, 0));
 m_CrumbBar.BackgroundColor( RGB(255, 0, 0), RGB(0,0,0), true);
 m_CrumbBar.Margin(10);
 m_CrumbBar.ItemSpacing(6);

Using the Crumbbar

// Initilizing the CrumbBar.
m_CrumbBar.Path(_T("C:\\MyFolder\\SubFiles1\\SubFolder2\\")); 
m_CrumbBar.Delimiter(_T("\\"));
m_CrumbBar.DelimiterMode(DM_RIGHT);

// Create a PreItem and set the preitem to "..\\"
MZCrumbBar::CrumbBarItem PreItem(_T(""), _T("..\\")); 
m_CrumbBar.PreItem(PreItem); 

// Rebuild/Update the CrumbBar.
m_CrumbBar.BuildCrumbbar();

// Get The Complate path.
CString path = m_crumbBar.Path();

// Get the path up to and including a specific CrumbBar item.
CString path = m_crumbBar.GetPath( pCrumbBarItem );

Notifications

There are a few notification messages that are used to notify the owner window when things have happend.

#define NMCB_LBCLICK    1000 // User clicked with Left Mouse Button 
#define NMCB_RBCLICK    1001 // User clicked with Right Mouse Button 
#define NMCB_MBCLICK    1002 // User clicked with Middle Mouse Button 
#define NMCB_LBDBLCLICK 1003 // User double clicked with Left Mouse Button 
#define NMCB_RBDBLCLICK 1004 // User double clicked with Right Mouse Button 
#define NMCB_MBDBLCLICK 1005 // User double clicked with Middle Mouse Button 
#define NMCB_EDITCHANGE 1010 // User changed path by editing it

To catch the notification message you need can do this in you dialog.

 // in .h file
 afx_msg void OnCrumbBarItemClicked(NMHDR *pNotifyStruct, LRESULT* pResult) ;

 // in .cpp file
 BEGIN_MESSAGE_MAP(CCrumbBarDemoDlg, CDialog)
        ON_NOTIFY( NMCB_LBCLICK, IDC_CRUMBBAR , OnCrumbBarItemClicked) 
 END_MESSAGE_MAP()

 void CCrumbBarDemoDlg::OnCrumbBarItemClicked(NMHDR* pNotifyStruct, LRESULT* pResult) 
 {
        NM_CRUMBBARITEM* pnmCrumbBarItem = (NM_CRUMBBARITEM*)pNotifyStruct;

        // CrumbBar Item that was clicked
        pnmCrumbBarItem->pCrumbBarItem;

        // CrumbBar Path for clicked item
        pnmCrumbBarItem->strCrumbPath;

        // Mouse position when click happen.
        // use for example to show a context menu with sub folder, like Explorer in Windows Vista
        pnmCrumbBarItem->pt;

        ...
 }

Custom Draw the CrumbBar Items

Custom draw of crumbbar items
Custom draw of crumbbar items

To change the CrumbBar to a custom look you need to override a couple of functions.

  // Return the width of the crumbbar item.
  virtual int OnMeasureItem(CDC* pDC, CrumbBarItem* pItem);
  
  // Return width if the PreItem (item that is shown at the beginning, if not all crumbbar items can be drawn)
  virtual int OnMeasurePreItem(CDC* pDC);

  // Draw CrumbBar Item
  virtual void DrawCrumbItem(CrumbBarItem* pItem, CDC* pDC, CRect rc);
  
  // Draw PreItem
  virtual void DrawPreItem(CrumbBarItem* pItem, CDC* pDC, CRect rc);

Take a look at CBlockCrumbBar.h/.cpp in the source for the Demo App to see how it can be done.

History

For full history check the header in MZCrumbBar.cpp

 

  • v1.5 - 2012-05-03
    The in-place edit controller caused a crash if it lost focus before it was completely created.
    Also Added VS2010, VS2012 project files to demo
  • v1.4 - 2011-02-25
    Added CRect MZCrumbBar::GetItemRect (CrumbBarItem* pItemChosen) - Provided by Iain Clarke
  • v1.3 - 2010-11-13  
    Added flag CRU_DONOTSTRIPDELIMITER that will keep double delimiter. Double delimiter are use to tell MZCrumbarCtrl that it should not break a path when it sees a delimiter. eg "Main-Sub-Sub--Menu" -> last item is normal shown as "Sub-Menu" but with this flag it is shown as "Sub--Menu" since the double delimiter is not stripped, For example "\\Server\Share\Folder" -> first item will now be shown as "\\Server" and not as "\Server"
  • v1.2 - 2010-04-15  
    • Added improvments/fixes provided by Iain Clarke
      - 3 more BuildCrumbbar(...) function for special situations.
      - Refactored how a path is parsed.
      - Added CRU_LASTITEMNODELIMITER. If style is set the Delimiter will not be shown for last crumbbar item.
      - Style can now be set using styleEx.
      - Change Default hot color to COLOR_HOTLIGHT.
      - Added possibility to store custom data in a Crumbar item.
      - Added SetItemData/GetItemData of custom data to crumbbar items
    - Fixed so that double delimiter now works again. Double delimiter should be part of the crumbpath name and not split the path.
    - Change so that items are added to m_vCrumbItems via the virtual function AddCrumbItem(...)
    - Fixed so that empty path parts are not added to the path.
  • v1.1 - 2010-03-17 - First public version. Fixed minor draw issue.
  • v1.0 - 2009-10-17 - First public version

Credits

  • Borrowed Gradient code from CLabel by Norm.net
Tagged:  

( Try Multi Commander, A file manager for professionals )

Copyright (c) 2015 - Mathias Svensson