std::string Menu::buildMenuText( ItemPtr item )
{
    return item->shortcutKey().size()						?
           item->displayName() + '\t' + item->shortcutKey()	:
           item->displayName();
}
void Toolbar::updateExpandedChoice( unsigned int& index, ItemPtr item, TBBUTTONINFO& info )
{
	struct PatchDisplayName
	{
		std::string operator()( std::string name )
		{
			std::string::iterator iter = name.begin();
			while( iter != name.end() )
			{
				if( *iter == '&' )
					name.erase( iter );
				else
					++iter;
			}
			return name;
		}
	}
	PatchDisplayName;
	HWND combobox = (HWND)info.lParam;
	if( ( info.fsStyle & BTNS_SEP ) == 0 || // not a place holder
		info.lParam == 0 ) // do not contain a combo box
	{
		int width = item->exist( "width" )	?	atoi( (*item)[ "width" ].c_str() )	:
												150;
		combobox = CreateWindow( "COMBOBOX", "",
			CBS_AUTOHSCROLL | CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE,
			0, 0, width, 1,
			toolbar_, NULL, GetModuleHandle( NULL ), NULL );
		SendMessage( combobox, WM_SETFONT,
			SendMessage( toolbar_, WM_GETFONT, 0, 0 ),
			FALSE );
		TBBUTTON button;
		memset(	&button, 0, sizeof(button) );
		button.iBitmap = width; // width of the combobox, MUST be configurable in future
		button.idCommand = 0;
		button.fsState = 0;
		button.fsStyle = BTNS_SEP;
		button.dwData = (DWORD)combobox;
		button.iString = -1;

		sendMessage( TB_INSERTBUTTON, index, (LPARAM)&button );
	}
	{// set the position & size
		RECT rectButton, rectWin;
		sendMessage( TB_GETITEMRECT, index, (LPARAM)&rectButton );
		GetWindowRect( combobox, &rectWin );
		ScreenToClient( toolbar_, (POINT*)&rectWin );
		MoveWindow( combobox, rectButton.left, rectButton.top,
			rectButton.right - rectButton.left, ( rectButton.bottom - rectButton.top ) * 20, TRUE );
	}
	int comboIndex = 0;
	unsigned int subitemIndex = 0;
	while( comboIndex < SendMessage( combobox, CB_GETCOUNT, 0, 0 ) &&
		subitemIndex < item->num() )
	{
		ItemPtr subitem = (*item)[ subitemIndex ];
		char* buffer = (char*)_alloca( SendMessage( combobox, CB_GETLBTEXTLEN, comboIndex, 0 ) + 1 );
		SendMessage( combobox, CB_GETLBTEXT, comboIndex, (LPARAM)buffer );
		if( SendMessage( combobox, CB_GETITEMDATA, comboIndex, 0 ) != subitem->commandID() ||
			buffer != subitem->displayName() )
		{
			SendMessage( combobox, CB_INSERTSTRING, comboIndex,
				(LPARAM)PatchDisplayName( subitem->displayName() ).c_str() );
			SendMessage( combobox, CB_SETITEMDATA, comboIndex, subitem->commandID() );
		}
		if( subitem->update() && !SendMessage( combobox, CB_GETDROPPEDSTATE, 0, 0 ) )
			SendMessage( combobox, CB_SETCURSEL, comboIndex, 0 );
		++comboIndex;
		++subitemIndex;
	}
	while( comboIndex < SendMessage( combobox, CB_GETCOUNT, 0, 0 ) )
		SendMessage( combobox, CB_DELETESTRING, comboIndex, 0 );
	while( subitemIndex < item->num() )
	{
		ItemPtr subitem = (*item)[ subitemIndex ];
		SendMessage( combobox, CB_INSERTSTRING, comboIndex,
			(LPARAM)PatchDisplayName( subitem->displayName() ).c_str() );
		SendMessage( combobox, CB_SETITEMDATA, comboIndex, subitem->commandID() );
		if( subitem->update()  && !SendMessage( combobox, CB_GETDROPPEDSTATE, 0, 0 ) )
			SendMessage( combobox, CB_SETCURSEL, comboIndex, 0 );
		++comboIndex;
		++subitemIndex;
	}
	EnableWindow( combobox, item->update() && item->num() && isEnabled() );
}