
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 crumb-bar in another project, and it had nothing to do with file paths. So I built this CrumbBar controller that is generic. It can show any string with delimiters as a crumb-bar.
Features
- Any string with a delimiter can be shown as a crumbbar:

- Can go into Edit mode if clicked on (configurable on what clicks will turn it to editable).

- Send notification on what item was clicked. Notifications can be sent for both single and double clicks on all three mouse buttons.
- Support 'go back' item if not all crumb items fit in the controller.

- Support left margin and item spacing.
- Support gradient background.
- Can easily be custom drawn to implement your own drawing of the crumb items.

Create the Controller
Adding MZCrumbBar to a dialog:

- Added a custom controller to the layout where you want to have it.
- Set the ID of the properties to something like
IDC_CRUMBBAR.
- Class name in properties must be "
MZCrumbBarCtrl".
- Then set the style flags you want, like 0x50810001. If you do not want any border (
WS_BORDER), remove 0x00800000 from the value.
- Then add a
MZCrumbBar variable to your dialog class.
- 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);
}
- Then configure the controller how you want it in
OnInitDialog().
Configuring
Here are the options on when the controller should turn into Edit mode. Set them as StyleEx flags in Create, or with MZCrumbBar::Style(...).
#define CRU_EDITOUTSIDE 0x00000010 #define CRU_EDITONCLK_L 0x00000100 #define CRU_EDITONDBL_L 0x00000200 #define CRU_EDITONCLK_R 0x00000400 #define CRU_EDITONDBL_R 0x00000800 #define CRU_EDITONCLK_M 0x00001000 #define CRU_EDITONDBL_M 0x00002000 #define CRU_LASTITEMCOLD 0x00010000 #define CRU_LASTITEMNOCLK 0x00020000 #define CRU_LASTITEMNODELIMITER 0x00040000 #define CRU_DONOTSTRIPDELIMITER 0x00080000
Flags for configuring how the delimiter should be shown (set the option via the DelimiterMode(...) function):
#define DM_STRIP 0 #define DM_LEFT 1 #define DM_RIGHT 2
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
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 Complete 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 happened:
#define NMCB_LBCLICK 1000 #define NMCB_RBCLICK 1001 #define NMCB_MBCLICK 1002 #define NMCB_LBDBLCLICK 1003 #define NMCB_RBDBLCLICK 1004 #define NMCB_MBDBLCLICK 1005 #define NMCB_EDITCHANGE 1010
To catch the notification message, you can do this in your dialog:
afx_msg void OnCrumbBarItemClicked(NMHDR *pNotifyStruct, LRESULT* pResult) ;
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;
pnmCrumbBarItem->pCrumbBarItem;
pnmCrumbBarItem->strCrumbPath;
pnmCrumbBarItem->pt;
...
}
Custom Draw the CrumbBar Items


To change the CrumbBar to a custom look, you need to override a couple of functions.
virtual int OnMeasureItem(CDC* pDC, CrumbBarItem* pItem);
virtual int OnMeasurePreItem(CDC* pDC);
virtual void DrawCrumbItem(CrumbBarItem* pItem, CDC* pDC, CRect rc);
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.
Credits
- Borrowed Gradient code from CLabel by Norm.net
History
For full history, check the header in MZCrumbBar.cpp.
- v1.3: 2010-11-13
- Added new flag
CRU_DONOTSTRIPDELIMITER that will keep the double delimiter.
- Double delimiter is used to tell
MZCrumbarCtrl that it should not break a path when it sees a delimiter.
E.g.: "Main-Sub-Sub--Menu" -> last item is normally 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" -> the first item will now be shown as "\\Server" and not as "\Server".
- v1.2: 2010-04-15
- Added improvements/fixes provided by Iain Clarke
- Three more
BuildCrumbbar(...) functions for special situations.
- Refactored how a path is parsed.
- Added
CRU_LASTITEMNODELIMITER. If style is set, the delimiter will not be shown for the last crumb-bar item.
- Style can now be set using
styleEx.
- Changed default hot color to
COLOR_HOTLIGHT.
- Added possibility to store custom data in a crumb-bar item.
- Added
SetItemData/GetItemData of custom data to crumb-bar items.
- Fixed so that double delimiter now works again. Double delimiter should be part of the crumb-path name and not split the path.
- Changed 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-10 - First version.