Click here to Skip to main content
15,886,106 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox - Updates and User Contributions

Rate me:
Please Sign up or sign in to vote.
4.79/5 (26 votes)
12 Feb 2013CPOL8 min read 254.8K   23.7K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
// ==========================================================================
//			Class Implementation: COXCustomizeCommandsPage
// ==========================================================================

// Version: 9.3

// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
                         
// //////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "OXCustomizeCommandsPage.h"
#include "OXCustomizeManager.h"
#include "OXButtonAppearanceDlg.h"
#include "OXDragDropCommands.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

const int ID_OX_IMAGEOFFSET_MENUGROUP=0;
const int ID_OX_IMAGEOFFSET_NEWPOPUPMENU=1;
const int ID_OX_IMAGEOFFSET_SEPARATOR=2;
const int ID_OX_IMAGEOFFSET_NOIMAGE=3;
const int ID_OX_IMAGEOFFSET_CUSTOMBUTTON=4;
const int ID_OX_IMAGEOFFSET_COUNT=5;

/////////////////////////////////////////////////////////////////////////////
// COXCustomizeCommandsPage dialog

IMPLEMENT_DYNCREATE(COXCustomizeCommandsPage, COXCustomizePage)

COXCustomizeCommandsPage::COXCustomizeCommandsPage()
{
	//{{AFX_DATA_INIT(COXCustomizeCommandsPage)
	m_sDescription = _T("");
	m_bShowIconsInMenu = FALSE;
	m_bShowOnlyRecentlyUsedMenuItems = FALSE;
	//}}AFX_DATA_INIT
	m_nDialogID=IDD;
	m_sProfileName.Empty();
	m_arrCommandIds=NULL;

	m_pCustomizedToolbar=NULL;
	m_nCustomizedPopupMenuIndex=-1;

	m_hCustomButtonWnd=NULL;
}


COXCustomizeCommandsPage::~COXCustomizeCommandsPage()
{
	if(m_arrCommandIds!=NULL)
	{
		delete[] m_arrCommandIds;
	}

	ResetPopupMenus(0);
	POSITION pos=m_mapBMPopupWnd.GetStartPosition();
	COXBitmapMenuPopupWnd* pBMPopupWnd=NULL;
	int nLevel=-1;
	while(pos!=NULL)
	{
		m_mapBMPopupWnd.GetNextAssoc(pos,pBMPopupWnd,nLevel);
		ASSERT(pBMPopupWnd!=NULL);
		ASSERT(nLevel>=0);
		delete pBMPopupWnd;
	}
	m_mapBMPopupWnd.RemoveAll();
}


BOOL COXCustomizeCommandsPage::OnCloseManager(BOOL bIsOk) 
{	
	// hide all menus
	ResetPopupMenus(0);
	m_nCustomizedPopupMenuIndex=-1;
	m_pCustomizedToolbar=NULL;
	m_hCustomButtonWnd=NULL;

	SaveWorkspaceState();

	if(bIsOk)
	{
		if(!UpdateData(TRUE))
			return FALSE;

		CWinApp* pApp=AfxGetApp();
		ASSERT(pApp!=NULL);

		if(!m_sProfileName.IsEmpty())
		{
#ifndef _MAC
			// save menu options
			pApp->WriteProfileInt(m_sProfileName,
				_T("ShowIconsInMenu"),m_bShowIconsInMenu);
			pApp->WriteProfileInt(m_sProfileName,
				_T("ShowOnlyRecentlyUsedMenuItems"),m_bShowOnlyRecentlyUsedMenuItems);
#endif
		}

		if(m_bShowIconsInMenu)
		{
			// Let the menu organizer fix our menus
			if(GetBMOrganizer()->IsAttached())
				GetBMOrganizer()->DetachFrameWnd();

			CWnd* pWnd=AfxGetMainWnd();
			ASSERT(pWnd!=NULL);
			CFrameWnd* pFrameWnd=DYNAMIC_DOWNCAST(CFrameWnd,pWnd);
			ASSERT(pFrameWnd!=NULL);

			// Let the menu organizer fix our menus
			GetBMOrganizer()->AttachFrameWnd(pFrameWnd);
			// use button from toolbars with corresponding items in menu
			GetBMOrganizer()->AutoSetMenuImage();

			GetBMOrganizer()->
				ShowOnlyRecentlyUsedItems(m_bShowOnlyRecentlyUsedMenuItems);
		}
		else if(!m_bShowIconsInMenu && GetBMOrganizer()->IsAttached())
		{
			CFrameWnd* pAttachedFrameWnd=GetBMOrganizer()->DetachFrameWnd();
			UNUSED(pAttachedFrameWnd);
#ifdef _DEBUG
			CWnd* pWnd=AfxGetMainWnd();
			ASSERT(pWnd!=NULL);
			CFrameWnd* pFrameWnd=DYNAMIC_DOWNCAST(CFrameWnd,pWnd);
			ASSERT(pFrameWnd!=NULL);
			ASSERT(pFrameWnd==pAttachedFrameWnd);
#endif
		}
	}

	return TRUE;
}


BOOL COXCustomizeCommandsPage::
InitializeCommands(LPCTSTR lpszCustomImagesResource,
				   COLORREF clrMask/*=RGB(192,192,192)*/,
				   BOOL bShowIconsInMenu/*=TRUE*/,
				   BOOL bShowOnlyRecentlyUsedMenuItems/*=TRUE*/,
				   LPCTSTR lpszProfileName/*=_T("CustomizeCommands")*/)
{
	ASSERT(lpszCustomImagesResource!=NULL);

	CWinApp* pApp=AfxGetApp();
	ASSERT(pApp!=NULL);

	CWnd* pWnd=AfxGetMainWnd();
	ASSERT(pWnd!=NULL);
	CFrameWnd* pFrameWnd=DYNAMIC_DOWNCAST(CFrameWnd,pWnd);
	ASSERT(pFrameWnd!=NULL);

	// build array of all commands available in the system
	//
	// document menus
	if(m_pCustomizeManager->IsMDIFramework())
	{
		POSITION pos=pApp->GetFirstDocTemplatePosition();
		while(pos!=NULL)
		{
			CDocTemplate* pDocTemplate=pApp->GetNextDocTemplate(pos);
			ASSERT(pDocTemplate!=NULL);
			CMultiDocTemplate* pMultiDocTemplate=
				DYNAMIC_DOWNCAST(CMultiDocTemplate,pDocTemplate);
			if(pMultiDocTemplate!=NULL)
			{
				if(pMultiDocTemplate->m_hMenuShared!=NULL)
					RetrieveCommandsFromMenu(pMultiDocTemplate->m_hMenuShared);
			}
		}
	}

	// default menu
	HINSTANCE hInstance=AfxFindResourceHandle(MAKEINTRESOURCE(IDR_MAINFRAME),RT_MENU);
	if(hInstance!=NULL)
	{
		HMENU hMenu=::LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MAINFRAME));
		if(hMenu!=NULL)
		{
			RetrieveCommandsFromMenu(hMenu);
			::DestroyMenu(hMenu);
		}
	}

	// toolbars
	//
	// Iterate all the control bars and use only the toolbars
	POSITION pos=pFrameWnd->m_listControlBars.GetHeadPosition();
	while(pos!=NULL)
	{
		CToolBar* pToolbar=DYNAMIC_DOWNCAST(CToolBar, 
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos));
		//If it is a CToolBar
		if(pToolbar!=NULL)
		{
			// Get the original imagelist of the toolbar
			int nButtonCount=pToolbar->GetToolBarCtrl().GetButtonCount();
			// Iterate all buttons on the toolbar
			for(int nButtonIndex=0; nButtonIndex<nButtonCount; nButtonIndex++)
			{
				UINT nID=0;
				UINT nStyle=0;
				int nImageIndex=0;
				pToolbar->GetButtonInfo(nButtonIndex,nID,nStyle,nImageIndex);
				//If the Item is not a button
				if(nStyle&TBBS_SEPARATOR)
					continue;
				m_mapCommands.SetAt(nID,-1);
			}
		}
	}

	//
	////////////////////////////////////////

	// save the flag that specifies if icon will be displayed in menus
	m_bShowIconsInMenu=bShowIconsInMenu;

	// save the flag that specifies if only recently used menu items 
	// should be displayed
	m_bShowOnlyRecentlyUsedMenuItems=bShowOnlyRecentlyUsedMenuItems;


	// populate image list with custom images
	VERIFY(m_ilCustomImages.Create(lpszCustomImagesResource,
		ID_OXCUSTOMIZE_TBIMAGE_WIDTH,0,clrMask));

	// build image list with all images used in the toolbars
	VERIFY(m_ilImages.Create(ID_OXCUSTOMIZE_TBIMAGE_WIDTH,
		ID_OXCUSTOMIZE_TBIMAGE_HEIGHT,ILC_COLOR24|ILC_MASK,0,0));

	// add to the image list images that would be used in tree of all available 
	// commands in order to represent: command groups, command without image,
	// new menu ite and separator item
	//
	HICON hIcon=pApp->LoadIcon(IDI_OX_CUSTOMIZE_COMMANDGROUP);
	ASSERT(hIcon!=NULL);
	VERIFY(m_ilImages.Add(hIcon)==ID_OX_IMAGEOFFSET_MENUGROUP);

	hIcon=pApp->LoadIcon(IDI_OX_CUSTOMIZE_NEWPOPUPMENU);
	ASSERT(hIcon!=NULL);
	VERIFY(m_ilImages.Add(hIcon)==ID_OX_IMAGEOFFSET_NEWPOPUPMENU);

	hIcon=pApp->LoadIcon(IDI_OX_CUSTOMIZE_SEPARATOR);
	ASSERT(hIcon!=NULL);
	VERIFY(m_ilImages.Add(hIcon)==ID_OX_IMAGEOFFSET_SEPARATOR);

	hIcon=pApp->LoadIcon(IDI_OX_CUSTOMIZE_NOIMAGE);
	ASSERT(hIcon!=NULL);
	VERIFY(m_ilImages.Add(hIcon)==ID_OX_IMAGEOFFSET_NOIMAGE);

	hIcon=pApp->LoadIcon(IDI_OX_CUSTOMIZE_CUSTOMBUTTON);
	ASSERT(hIcon!=NULL);
	VERIFY(m_ilImages.Add(hIcon)==ID_OX_IMAGEOFFSET_CUSTOMBUTTON);

	//
	/////////////////////////
	
	// Iterate all the control bars and use only the toolbars
	pos=pFrameWnd->m_listControlBars.GetHeadPosition();
	while(pos!=NULL)
	{
		CToolBar* pToolbar=DYNAMIC_DOWNCAST(CToolBar, 
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos));
		//If it is a CToolBar
		if(pToolbar!=NULL)
		{
			// Get the original imagelist of the toolbar
			HIMAGELIST hOrigImageList=
				(HIMAGELIST)pToolbar->SendMessage(TB_GETIMAGELIST);
			int nFirstImageIndex=0;
			if(hOrigImageList!=NULL)
			{
				CImageList origImageList;
				if(!origImageList.Attach(hOrigImageList))
				{
					TRACE(_T("COXCustomizeCommandsPage::InitializeCommands: failed to retrieve image list from toolbars\n"));
					return FALSE;
				}

				int nOrigImageCount=origImageList.GetImageCount();
				ASSERT(0<nOrigImageCount);

				nFirstImageIndex=m_ilImages.GetImageCount();

				for(int nButtonIndex=0; nButtonIndex<nOrigImageCount; nButtonIndex++)
				{
					HICON hIcon=origImageList.ExtractIcon(nButtonIndex);
					ASSERT(hIcon!=NULL);
					VERIFY(m_ilImages.Add(hIcon)!=-1);
					VERIFY(::DestroyIcon(hIcon));
				}

				// Close everything
				origImageList.Detach();
			}

			int nButtonCount=pToolbar->GetToolBarCtrl().GetButtonCount();
			// Iterate all buttons on the toolbar
			for(int nButtonIndex=0; nButtonIndex<nButtonCount; nButtonIndex++)
			{
				UINT nID=0;
				UINT nStyle=0;
				int nImageIndex=0;
				pToolbar->GetButtonInfo(nButtonIndex,nID,nStyle,nImageIndex);
				//If the Item is not a button
				if(nStyle&TBBS_SEPARATOR || nImageIndex==-1)
					continue;

				int nImageIndexTest=-1;
				// check if this button is in the commands map
				VERIFY(m_mapCommands.Lookup(nID,nImageIndexTest));
				if(nImageIndexTest==-1)
				{
					nImageIndexTest=nImageIndex+nFirstImageIndex;
					m_mapCommands.SetAt(nID,nImageIndexTest);
				}
				pToolbar->SetButtonInfo(nButtonIndex,nID,nStyle,nImageIndexTest);
			}

			pToolbar->
				SendMessage(TB_SETIMAGELIST,NULL,(LPARAM)((HIMAGELIST)m_ilImages));
		}
	}

	// add custom images
	for(int nButtonIndex=0; 
		nButtonIndex<m_ilCustomImages.GetImageCount(); 
		nButtonIndex++)
	{
		HICON hIcon=m_ilCustomImages.ExtractIcon(nButtonIndex);
		ASSERT(hIcon!=NULL);
		VERIFY(m_ilImages.Add(hIcon)!=-1);
		VERIFY(::DestroyIcon(hIcon));
	}

	// build array of all command IDs
	BuildArrayCommandIDs();
	//
	//////////////////////////////

	// Iterate all the control bars and use only the toolbars
	pos=pFrameWnd->m_listControlBars.GetHeadPosition();
	while(pos!=NULL)
	{

		CToolBar* pToolbar=DYNAMIC_DOWNCAST(CToolBar, 
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos));
		//If it is a CToolBar
		if(pToolbar!=NULL)
		{
			COXCoolToolBar* pCoolToolbar=
				DYNAMIC_DOWNCAST(COXCoolToolBar,pToolbar);
			if(pCoolToolbar!=NULL)
			{
				pCoolToolbar->
					SetBitmapIds(m_arrCommandIds,PtrToInt(m_mapCommands.GetCount()));
				// make sure toolbar is in list mode
				pCoolToolbar->SetList(TRUE);
			}
			VERIFY(LoadToolbarState(pToolbar));

			int nButtonCount=pToolbar->GetToolBarCtrl().GetButtonCount();
			// Iterate all buttons on the toolbar
			for(int nButtonIndex=0; nButtonIndex<nButtonCount; nButtonIndex++)
			{
				UINT nID=0;
				UINT nStyle=0;
				int nImageIndex=0;
				pToolbar->GetButtonInfo(nButtonIndex,nID,nStyle,nImageIndex);
				//If the Item is not a button
				if(nStyle&TBBS_SEPARATOR)
					continue;

				// make sure every button has TBSTYLE_AUTOSIZE style set
				pToolbar->SetButtonInfo(
					nButtonIndex,nID,nStyle|TBSTYLE_AUTOSIZE,nImageIndex);
			}

		}
	}

	if(lpszProfileName!=NULL)
	{
		m_sProfileName=lpszProfileName;
	}

#ifndef _MAC
	if(!m_sProfileName.IsEmpty())
	{
		// retrieve menu options
		m_bShowIconsInMenu=(BOOL)pApp->GetProfileInt(m_sProfileName,
			_T("ShowIconsInMenu"),m_bShowIconsInMenu);
		m_bShowOnlyRecentlyUsedMenuItems=(BOOL)pApp->GetProfileInt(m_sProfileName,
			_T("ShowOnlyRecentlyUsedMenuItems"),m_bShowOnlyRecentlyUsedMenuItems);
	}
#endif

	if(m_bShowIconsInMenu)
	{
		// Let the menu organizer fix our menus
		GetBMOrganizer()->AttachFrameWnd(pFrameWnd);
		// use button from toolbars with corresponding items in menu
		GetBMOrganizer()->AutoSetMenuImage();

		GetBMOrganizer()->
			ShowOnlyRecentlyUsedItems(m_bShowOnlyRecentlyUsedMenuItems);
	}
	VERIFY(GetBMOrganizer()->LoadRUCommandsState(_T("RecentlyUsedMenuItems")));

	return TRUE;
}


void COXCustomizeCommandsPage::DoDataExchange(CDataExchange* pDX)
{
	COXCustomizePage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(COXCustomizeCommandsPage)
	DDX_Control(pDX, IDC_OX_SEPARATOR_DESCRIPTION, m_sepDescription);
	DDX_Control(pDX, IDC_OX_SEPARATOR_COMMANDS, m_sepCommands);
	DDX_Control(pDX, IDC_OX_SEPARATOR_OPTIONS, m_sepOptions);
	DDX_Control(pDX, IDC_OX_BUTTON_MODIFY_SELECTION, m_btnModifySelection);
	DDX_Control(pDX, IDC_OX_TREE_COMMANDS, m_treeCommands);
	DDX_Text(pDX, IDC_OX_STATIC_DESCRIPTION, m_sDescription);
	DDX_Check(pDX, IDC_OX_CHECK_ICONS_IN_MENU, m_bShowIconsInMenu);
	DDX_Check(pDX, IDC_OX_CHECK_SHOW_ONLY_RECENTLY_USED, m_bShowOnlyRecentlyUsedMenuItems);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(COXCustomizeCommandsPage, COXCustomizePage)
	//{{AFX_MSG_MAP(COXCustomizeCommandsPage)
	ON_NOTIFY(TVN_BEGINDRAG, IDC_OX_TREE_COMMANDS, OnBegindragTreeCommands)
	ON_NOTIFY(TVN_SELCHANGED, IDC_OX_TREE_COMMANDS, OnSelchangedTreeCommands)
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
	ON_NOTIFY_RANGE(OXCTBN_CUSTOMIZECMD, 0, 0xffff, OnTBCustomizeCommand)
	ON_NOTIFY_RANGE(OXBMN_CUSTOMIZECMD, 0, 0xffff, OnBMCustomizeCommand)
	ON_NOTIFY(OXBBN_DROPDOWN,IDC_OX_BUTTON_MODIFY_SELECTION,OnDropDownModifySelection)
	ON_BN_CLICKED(IDC_OX_CHECK_ICONS_IN_MENU, OnCheckIconsInMenu)
	ON_BN_CLICKED(IDC_OX_CHECK_SHOW_ONLY_RECENTLY_USED, OnCheckShowOnlyRecentlyUsed)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// COXCustomizeCommandsPage message handlers

BOOL COXCustomizeCommandsPage::Load(const COXCustomizeManager* pCustomizeManager)
{
	// Call default implementation. It will load this demo dialog as the first 
	// page and will create About and CodeSample pages if specified.
	if(!COXCustomizePage::Load(pCustomizeManager))
		return FALSE;

	CWnd* pWnd=AfxGetMainWnd();
	ASSERT(pWnd!=NULL);
	CFrameWnd* pFrameWnd=DYNAMIC_DOWNCAST(CFrameWnd,pWnd);
	ASSERT(pFrameWnd!=NULL);

	// set all COXCoolToolBar derived toolbars in advanced customization mode
	// Iterate all control bars and use only the toolbars that are derived from 
	// COXCoolToolBar class
	POSITION pos=pFrameWnd->m_listControlBars.GetHeadPosition();
	while(pos!=NULL)
	{
		COXCoolToolBar* pToolbar=DYNAMIC_DOWNCAST(COXCoolToolBar, 
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos));
		//If its a COXCoolToolBar
		if(pToolbar!=NULL)
		{
			pToolbar->SetAdvancedCustomizationMode(TRUE,GetSafeHwnd());
		}
	}

	GetBMOrganizer()->SetCutomizationMode(TRUE,GetSafeHwnd());

	// set current customized toolbar to NULL
	m_pCustomizedToolbar=NULL;
	m_nCustomizedPopupMenuIndex=-1;

	return TRUE;
}


void COXCustomizeCommandsPage::Unload()
{
	// add here code for cleaning up all objects created by demo
	//
	//
	//////////////////////////////////////////////////////////////////////////
	
	// reset all COXCoolToolBar derived toolbars state ( remove advanced 
	// customization mode flag). Iterate all control bars and use only the 
	// toolbars that are derived from COXCoolToolBar class
	CWnd* pWnd=AfxGetMainWnd();
	ASSERT(pWnd!=NULL);
	CFrameWnd* pFrameWnd=DYNAMIC_DOWNCAST(CFrameWnd,pWnd);
	ASSERT(pFrameWnd!=NULL);

	POSITION pos=pFrameWnd->m_listControlBars.GetHeadPosition();
	while(pos!=NULL)
	{
		COXCoolToolBar* pToolbar=DYNAMIC_DOWNCAST(COXCoolToolBar, 
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos));
		//If its a COXCoolToolBar
		if(pToolbar!=NULL)
		{
			pToolbar->SetAdvancedCustomizationMode(FALSE);
		}
	}

	// hide all menus
	ResetPopupMenus(0);
	// set current customized toolbar to NULL
	m_pCustomizedToolbar=NULL;
	m_nCustomizedPopupMenuIndex=-1;

	GetBMOrganizer()->SetCutomizationMode(FALSE);

	COXCustomizePage::Unload();
}

void COXCustomizeCommandsPage::OnInitDialog()
{
#ifndef _MAC
	if(!m_sProfileName.IsEmpty())
	{
		// retrieve menu options
		m_bShowIconsInMenu=(BOOL)::AfxGetApp()->GetProfileInt(m_sProfileName,
			_T("ShowIconsInMenu"),m_bShowIconsInMenu);
		m_bShowOnlyRecentlyUsedMenuItems=(BOOL)::AfxGetApp()->GetProfileInt(m_sProfileName,
			_T("ShowOnlyRecentlyUsedMenuItems"),m_bShowOnlyRecentlyUsedMenuItems);
	}
#endif

	// must call default implementation
	COXCustomizePage::OnInitDialog();

	// add here initialization code for your demo dialog. Treat it as a
	// normal CDialog::OnInitDialog function

	// separators
	COLORREF clr=::GetSysColor(COLOR_WINDOW);
	m_sepDescription.SetTextColor(clr);
	m_sepCommands.SetTextColor(clr);
	m_sepOptions.SetTextColor(clr);

	// bitmap button
	m_btnModifySelection.SetStyleEx(OXBB_EX_DROPDOWN);
	m_btnModifySelection.SetDrawDropdownSeparator(FALSE);
	// set custom text font to button
	CFont* pFont=m_btnModifySelection.GetTextFont();
	ASSERT(pFont!=NULL);
	LOGFONT lf;
	VERIFY(pFont->GetLogFont(&lf));
	lf.lfWeight=FW_BOLD;
	VERIFY(pFont->DeleteObject());
	VERIFY(pFont->CreateFontIndirect(&lf));
	m_btnModifySelection.SetTextFont(pFont);

	// populate tree
	GetVars();

	// layout
	//
	m_LayoutManager.TieChild(&m_treeCommands,OX_LMS_ANY,OX_LMT_SAME);
	m_LayoutManager.TieChild(&m_sepCommands,OX_LMS_LEFT|OX_LMS_RIGHT,OX_LMT_SAME);
	m_LayoutManager.TieChild(&m_sepDescription,OX_LMS_RIGHT,OX_LMT_SAME);
	m_LayoutManager.TieChild(&m_sepOptions,OX_LMS_RIGHT,OX_LMT_SAME);
	m_LayoutManager.TieChild(IDC_OX_STATIC_DESCRIPTION,OX_LMS_RIGHT,OX_LMT_SAME);
	m_LayoutManager.TieChild(&m_btnModifySelection,OX_LMS_RIGHT,OX_LMT_SAME);
	m_LayoutManager.TieChild(IDC_OX_CHECK_ICONS_IN_MENU,OX_LMS_RIGHT,OX_LMT_SAME);
	m_LayoutManager.TieChild(IDC_OX_CHECK_SHOW_ONLY_RECENTLY_USED,
		OX_LMS_RIGHT,OX_LMT_SAME);
	m_LayoutManager.TieChild(IDC_OX_STATIC_CUSTOM_BUTTON_PREVIEW,
		OX_LMS_LEFT|OX_LMS_RIGHT|OX_LMS_BOTTOM,OX_LMT_SAME);
	//
	///////////////////////////////////////

	m_btnModifySelection.EnableWindow(m_pCustomizedToolbar!=NULL);

	m_bInitialized=TRUE;
}


void COXCustomizeCommandsPage::GetVars()
{
	CWinApp* pApp=AfxGetApp();
	ASSERT(pApp!=NULL);

	// populate tree control
	//
	m_treeCommands.DeleteAllItems();

	// associate image list with tree
	m_treeCommands.SetImageList(&m_ilImages,TVSIL_NORMAL);

	// build tree on the base of all menus available in the system
	//
	HINSTANCE hInstance=AfxFindResourceHandle(MAKEINTRESOURCE(IDR_MAINFRAME),RT_MENU);
	if(hInstance!=NULL)
	{
		HMENU hMenu=::LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MAINFRAME));
		if(hMenu!=NULL)
		{
			AddCommandsFromMenuToTree(hMenu,TVI_ROOT);
			::DestroyMenu(hMenu);
		}
	}

	if(m_pCustomizeManager->IsMDIFramework())
	{
		POSITION pos=pApp->GetFirstDocTemplatePosition();
		while(pos!=NULL)
		{
			CDocTemplate* pDocTemplate=pApp->GetNextDocTemplate(pos);
			ASSERT(pDocTemplate!=NULL);
			CMultiDocTemplate* pMultiDocTemplate=
				DYNAMIC_DOWNCAST(CMultiDocTemplate,pDocTemplate);
			if(pMultiDocTemplate!=NULL)
			{
				if(pMultiDocTemplate->m_hMenuShared!=NULL)
				{
					AddCommandsFromMenuToTree(pMultiDocTemplate->m_hMenuShared,
						TVI_ROOT);
				}
			}
		}
	}

	// add toolbars' custom buttons
	AddCustomButtonsFromToolbars(TVI_ROOT);

	// add custom commands
	AddCustomCommandsToTree();


	// add items for new popup menu and separator
	//
	int nImageIndex=ID_OX_IMAGEOFFSET_NEWPOPUPMENU;
	CString sItem;
	VERIFY(sItem.LoadString(IDS_OX_CSTMZECOMMANDSNEWMENU));//"New Menu"
	HTREEITEM hItem=m_treeCommands.InsertItem(sItem,nImageIndex,
		nImageIndex,TVI_ROOT,TVI_LAST);
	ASSERT(hItem!=NULL);
	m_treeCommands.SetItemState(hItem,TVIS_BOLD,TVIS_BOLD);
	m_treeCommands.SetItemData(hItem,(DWORD)-2);

	nImageIndex=ID_OX_IMAGEOFFSET_SEPARATOR;
	VERIFY(sItem.LoadString(IDS_OX_CSTMZECOMMANDSSEPARATOR));//"Separator"
	hItem=m_treeCommands.InsertItem(sItem,nImageIndex,
		nImageIndex,TVI_ROOT,TVI_LAST);
	ASSERT(hItem!=NULL);
	m_treeCommands.SetItemState(hItem,TVIS_BOLD,TVIS_BOLD);
	m_treeCommands.SetItemData(hItem,0);
	//
	/////////////////////////////////////
}


void COXCustomizeCommandsPage::AddCustomButtonsFromToolbars(HTREEITEM hParentItem)
{
	int nCustomButtonCount=PtrToInt(COXCoolToolBar::m_mapAllCustomButtons.GetCount());
	if(nCustomButtonCount>0)
	{
		CString sItem;
		VERIFY(sItem.LoadString(IDS_OX_CSTMZECOMMANDSCUSTOMBUTTONS));//"Custom Buttons"
		HTREEITEM hCustomButtonsItem=m_treeCommands.InsertItem(sItem,
			ID_OX_IMAGEOFFSET_CUSTOMBUTTON,ID_OX_IMAGEOFFSET_CUSTOMBUTTON,
			hParentItem,TVI_LAST);
		ASSERT(hCustomButtonsItem!=NULL);
		m_treeCommands.SetItemState(hCustomButtonsItem,TVIS_BOLD,TVIS_BOLD);
		m_treeCommands.SetItemData(hCustomButtonsItem,(DWORD)-3);

		POSITION pos=COXCoolToolBar::m_mapAllCustomButtons.GetStartPosition();
		while(pos!=NULL)
		{
			int nCtrlID=-1;
			OXCUSTOMBUTTONDESCRIPTOR descriptor;
			COXCoolToolBar::m_mapAllCustomButtons.GetNextAssoc(pos,nCtrlID,descriptor);
			ASSERT(nCtrlID!=-1);
			if(!::IsWindow(descriptor.m_pCBTemplate->CBGetWindow()->GetSafeHwnd()))
			{
				TRACE(_T("COXCustomizeCommandsPage::AddCustomButtonsFromToolbars: registered custom button with ID %d found that hasn't been inserted in any toolbar. Therefore it is ignored here!\n"),nCtrlID);
				continue;
			}

			CString sText(_T(""));
			HINSTANCE hInstance=
				AfxFindResourceHandle(MAKEINTRESOURCE(nCtrlID),RT_STRING);
			if(hInstance!=NULL)
			{
				sText.LoadString(nCtrlID);
				int nPosition=sText.Find(_T('\n'));
				if(nPosition!=-1)
				{
					sText=sText.Mid(nPosition+1);
				}

				nPosition=sText.Find(_T('\t'));
				if(nPosition!=-1)
					sText=sText.Left(nPosition);
				
				nPosition=sText.Find(_T('&'));
				if(nPosition!=-1)
					sText=sText.Left(nPosition)+sText.Mid(nPosition+1);

			}
			
			if(sText.IsEmpty())
			{
				CString sClassName;
				VERIFY(::GetClassName(
					descriptor.m_pCBTemplate->CBGetWindow()->GetSafeHwnd(),
					sClassName.GetBuffer(MAX_PATH),MAX_PATH)>0);
				sClassName.ReleaseBuffer();
				sText.Format(_T("Window class '%s'"),sClassName);
			}
			ASSERT(!sText.IsEmpty());

			HTREEITEM hItem=m_treeCommands.InsertItem(sText,ID_OX_IMAGEOFFSET_CUSTOMBUTTON,
				ID_OX_IMAGEOFFSET_CUSTOMBUTTON,hCustomButtonsItem,TVI_LAST);
			ASSERT(hItem!=NULL);
			m_treeCommands.SetItemData(hItem,(LPARAM)nCtrlID);
		}
	}
}


void COXCustomizeCommandsPage::RetrieveCommandsFromMenu(HMENU hMenu)
{
	ASSERT(hMenu!=NULL);

	CMenu* pMenu=CMenu::FromHandle(hMenu);
	ASSERT(pMenu!=NULL);
	
	int nItemCount=pMenu->GetMenuItemCount();
	for(int nIndex=0; nIndex<nItemCount; nIndex++)
	{
		if(pMenu->GetMenuItemID(nIndex)==-1)
		{
			// popup menu
			CMenu* pPopupMenu=pMenu->GetSubMenu(nIndex);
			ASSERT(pPopupMenu!=NULL);
			RetrieveCommandsFromMenu((HMENU)*pPopupMenu);
		}
		else
		{
			UINT nCommandID=pMenu->GetMenuItemID(nIndex);
			if(nCommandID!=0)
			{
				// don't add most recent files used 
				if(nCommandID>=ID_FILE_MRU_FILE1 && nCommandID<=ID_FILE_MRU_FILE16)
					continue;

				// don't add MDIChild windows menu items 
				if(m_pCustomizeManager->IsMDIFramework() && 
					nCommandID>=AFX_IDM_FIRST_MDICHILD)
					continue;

				HINSTANCE hInstance=
					AfxFindResourceHandle(MAKEINTRESOURCE(nCommandID),RT_STRING);
				if(hInstance!=NULL)
					m_mapCommands.SetAt(nCommandID,-1);
			}
		}
	}
}


void COXCustomizeCommandsPage::AddCommandsFromMenuToTree(HMENU hMenu, 
														 HTREEITEM hParentItem)
{
	ASSERT(hMenu!=NULL);
	ASSERT(hParentItem!=NULL);

	CMenu* pMenu=CMenu::FromHandle(hMenu);
	ASSERT(pMenu!=NULL);
	BOOL bIsBitmapMenu=pMenu->IsKindOf(RUNTIME_CLASS(COXBitmapMenu));
	
	int nItemCount=pMenu->GetMenuItemCount();
	for(int nIndex=0; nIndex<nItemCount; nIndex++)
	{
		UINT nCommandID=pMenu->GetMenuItemID(nIndex);
		if(nCommandID==0)
			continue;

		if(nCommandID!=-1)
		{
			// don't add most recent files used 
			if(nCommandID>=ID_FILE_MRU_FILE1 && nCommandID<=ID_FILE_MRU_FILE16)
				continue;

			// don't add MDIChild windows menu items 
			if(m_pCustomizeManager->IsMDIFramework() && 
				nCommandID>=AFX_IDM_FIRST_MDICHILD)
				continue;

			HINSTANCE hInstance=
				AfxFindResourceHandle(MAKEINTRESOURCE(nCommandID),RT_STRING);
			if(hInstance==NULL)
				continue;
		}

		CString sText(_T(""));
		if(bIsBitmapMenu)
		{
			MENUITEMINFO mii={ sizeof(mii) };
			mii.fMask=MIIM_TYPE|MIIM_DATA;
			::GetMenuItemInfo(pMenu->GetSafeHmenu(),nIndex,TRUE,&mii);

			if(mii.fType==MFT_OWNERDRAW)
			{
				COXItemInfo* pItemInfo=(COXItemInfo*)(mii.dwItemData);
				ASSERT(pItemInfo!=NULL);
				sText=pItemInfo->GetText();
			}
		}
		if(sText.IsEmpty())
		{
			pMenu->GetMenuString(nIndex,sText,MF_BYPOSITION);
		}
		ASSERT(!sText.IsEmpty());

		int nPosition=sText.Find(_T('\t'));
		if(nPosition!=-1)
			sText=sText.Left(nPosition);
		
		nPosition=sText.Find(_T('&'));
		if(nPosition!=-1)
			sText=sText.Left(nPosition)+sText.Mid(nPosition+1);

		HTREEITEM hItem=FindMenuItemInTree(sText,hParentItem);
		if(hItem==NULL)
		{
			int nImageIndex=-1;
			if(nCommandID!=-1)
			{
				VERIFY(m_mapCommands.Lookup(nCommandID,nImageIndex));
				if(nImageIndex==-1)
					nImageIndex=ID_OX_IMAGEOFFSET_NOIMAGE;
			}
			else
			{
				nImageIndex=ID_OX_IMAGEOFFSET_MENUGROUP;
			}

			hItem=m_treeCommands.InsertItem(sText,nImageIndex,nImageIndex,
				hParentItem,TVI_LAST);
			ASSERT(hItem!=NULL);
			m_treeCommands.SetItemData(hItem,(LPARAM)nCommandID);
		}

		if(nCommandID==-1)
		{
			// popup menu
			m_treeCommands.SetItemState(hItem,TVIS_BOLD,TVIS_BOLD);

			CMenu* pPopupMenu=pMenu->GetSubMenu(nIndex);
			ASSERT(pPopupMenu!=NULL);
			AddCommandsFromMenuToTree((HMENU)*pPopupMenu,hItem);
		}
	}
}


HTREEITEM COXCustomizeCommandsPage::FindMenuItemInTree(CString sText, 
													   HTREEITEM hParentItem) const
{
	ASSERT(!sText.IsEmpty());
	ASSERT(hParentItem!=NULL);

	HTREEITEM hChildItem=m_treeCommands.GetNextItem(hParentItem,TVGN_CHILD);

	HTREEITEM hFoundItem=NULL;
	while(hChildItem!=NULL)
	{
		CString sTextToCompare=m_treeCommands.GetItemText(hChildItem);
		if(sText.CompareNoCase(sTextToCompare)==0)
		{
			hFoundItem=hChildItem;
			break;
		}

		hChildItem=m_treeCommands.GetNextItem(hChildItem,TVGN_NEXT);
	}

	return hFoundItem;
}


void COXCustomizeCommandsPage::OnBegindragTreeCommands(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView=(NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	
	m_treeCommands.SelectItem(pNMTreeView->itemNew.hItem);

	CString sText(_T(""));
	int nImageIndex=-1;
	int nCommandID=0;
	BYTE fsStyle=0;
	HMENU hSubmenu=NULL;
	DWORD_PTR dwData=m_treeCommands.GetItemData(pNMTreeView->itemNew.hItem);
	if(dwData==0)
	{
		// separator
		fsStyle=TBSTYLE_SEP;
	}
	else if(dwData==-1)
	{
		// existing popup menu
		sText=m_treeCommands.GetItemText(pNMTreeView->itemNew.hItem);
		nCommandID=-1;
		fsStyle=TBSTYLE_AUTOSIZE|TBSTYLE_DROPDOWN;
		hSubmenu=BuildMenuFromTree(pNMTreeView->itemNew.hItem);
	}
	else if(dwData==-2)
	{
		// new popup menu
		VERIFY(sText.LoadString(IDS_OX_CSTMZECOMMANDSNEWMENU)); //"New menu"
		nCommandID=-1;
		fsStyle=TBSTYLE_AUTOSIZE|TBSTYLE_DROPDOWN;
	}
	else if(dwData==-3)
	{
		// set of toolbars' custom buttons
		// doesn't support drag'n'drop
		return;
	}
	else 
	{
		nCommandID=(int)dwData;
		int nSelectedImage=0;
		VERIFY(m_treeCommands.GetItemImage(pNMTreeView->itemNew.hItem,
			nImageIndex,nSelectedImage));
		ASSERT(nSelectedImage==nImageIndex);

		HINSTANCE hInstance=
			AfxFindResourceHandle(MAKEINTRESOURCE(nCommandID),RT_STRING);
		if(hInstance!=NULL)
		{
			sText.LoadString(nCommandID);
			int nPosition=sText.Find(_T('\n'));
			if(nPosition!=-1)
				sText=sText.Mid(nPosition+1);
		}
		if(sText.IsEmpty())
		{
			sText=m_treeCommands.GetItemText(pNMTreeView->itemNew.hItem);
		}
		ASSERT(!sText.IsEmpty());
	}

	COleDataSource* pDataSource=
		COXDragDropCommands::PrepareDragDropData(sText,nImageIndex,
		nCommandID,fsStyle,hSubmenu);
	ASSERT(pDataSource!=NULL);
	COleDropSource dropSource;
	COXDragDropCommands::DoDragDrop(pDataSource,&dropSource);

	//delete drag source (we are responsible for doing that)
	delete pDataSource;

	if(hSubmenu!=NULL)
	{
		::DestroyMenu(hSubmenu);
	}

	*pResult=0;
}


void COXCustomizeCommandsPage::OnSelchangedTreeCommands(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView=(NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here

	// destroy currently displayed custom button window
	if(m_hCustomButtonWnd!=NULL)
	{
		VERIFY(::DestroyWindow(m_hCustomButtonWnd));
		m_hCustomButtonWnd=NULL;
	}

	HTREEITEM hSelectedItem=pNMTreeView->itemNew.hItem;
	if(hSelectedItem!=NULL)
	{
		DWORD_PTR dwData=m_treeCommands.GetItemData(hSelectedItem);
		if(dwData==0)
		{
			// separator
			VERIFY(m_sDescription.LoadString(IDS_OX_CSTMZECOMMANDSDESCSEPARATOR)); //"Menu or toolbar separator"
		}
		else if(dwData==-1)
		{
			// existing popup menu
			m_sDescription.Format(IDS_OX_CSTMZECOMMANDSDESCGROUP,//"%s group"
				m_treeCommands.GetItemText(hSelectedItem));
		}
		else if(dwData==-2)
		{
			// new popup menu
			VERIFY(m_sDescription.LoadString(IDS_OX_CSTMZECOMMANDSDESCNEWGROUP)); //"New menu group"
		}
		else if(dwData==-3)
		{
			// set of custom buttons
			VERIFY(m_sDescription.LoadString(IDS_OX_CSTMZECOMMANDSDESCSET)) ;//"Set of toolbars' Custom Buttons"
		}
		else 
		{
			UINT nCommandID=(UINT)dwData;
			HINSTANCE hInstance=
				AfxFindResourceHandle(MAKEINTRESOURCE(nCommandID),RT_STRING);
			if(hInstance==NULL)
			{
				m_sDescription.Empty();
			}
			else
			{
				m_sDescription.LoadString(nCommandID);
				int nPosition=m_sDescription.Find(_T('\n'));
				if(nPosition!=-1)
					m_sDescription=m_sDescription.Left(nPosition);
			}

			// check for toollbar custom button
			OXCUSTOMBUTTONDESCRIPTOR descriptor;
			if(COXCoolToolBar::m_mapAllCustomButtons.Lookup(nCommandID,descriptor))
			{
				if(m_sDescription.IsEmpty())
				{
					VERIFY(m_sDescription.LoadString(IDS_OX_CSTMZECOMMANDSCUSTOMBUTTON)); //"Custom Button"
				}

				// create custom button window and display it
				//
				COXCustomTBButtonTemplate* pCBTemplate=
					descriptor.m_pCBTemplate->CBCreateCopy(this);
				ASSERT(pCBTemplate!=NULL);
				ASSERT(::IsWindow(pCBTemplate->CBGetWindow()->GetSafeHwnd()));
				pCBTemplate->CBSetCustomizationMode(TRUE);
				m_hCustomButtonWnd=pCBTemplate->CBGetWindow()->GetSafeHwnd();
				PreviewCustomButtonWindow();
				//
				//////////////////////////////////////////////
			}
		}
	}
	else
	{
		m_sDescription.Empty();
	}

	UpdateData(FALSE);
	
	*pResult=0;
}


void COXCustomizeCommandsPage::OnSize(UINT nType, int cx, int cy)
{
	COXCustomizePage::OnSize(nType,cx,cy);

	// reposition the custom button preview window if any displayed
	if(::IsWindow(m_hCustomButtonWnd))
	{
		PreviewCustomButtonWindow();
	}
}


void COXCustomizeCommandsPage::PreviewCustomButtonWindow()
{
	if(m_hCustomButtonWnd==NULL)
		return;

	ASSERT(::IsWindow(m_hCustomButtonWnd));

	CWnd* pCBWnd=CWnd::FromHandle(m_hCustomButtonWnd);
	// custom button descriptor
	OXCUSTOMBUTTONDESCRIPTOR descriptor;
	VERIFY(COXCoolToolBar::m_mapAllCustomButtons.
		Lookup(pCBWnd->GetDlgCtrlID(),descriptor));

	CRect rect;
	GetDlgItem(IDC_OX_STATIC_CUSTOM_BUTTON_PREVIEW)->GetClientRect(rect);
	GetDlgItem(IDC_OX_STATIC_CUSTOM_BUTTON_PREVIEW)->ClientToScreen(rect);
	// deflate it by some reasonable margin
	rect.DeflateRect(5,17,5,5);

	// based on descriptor info and wrapping rectangle define 
	// the rectangle for custom button window
	int nCBHeight=descriptor.m_nHeight;
	if(nCBHeight>ID_OXCUSTOMIZE_TBIMAGE_HEIGHT+6)
	{
		nCBHeight=ID_OXCUSTOMIZE_TBIMAGE_HEIGHT+6;
	}
	if(nCBHeight>rect.Height())
	{
		nCBHeight=rect.Height();
	}
	else
	{
		// center the custom button window vertically
		rect.top+=(rect.Height()-nCBHeight)/2;
		rect.bottom=rect.top+nCBHeight;
	}
	int nCBWidth=descriptor.m_nWidth;
	if(nCBWidth>rect.Width())
	{
		nCBWidth=rect.Width();
	}
	else
	{
		// center the custom button window horizontally
		rect.left+=(rect.Width()-nCBWidth)/2;
		rect.right=rect.left+nCBWidth;
	}
	ScreenToClient(rect);

	pCBWnd->MoveWindow(rect);
	pCBWnd->ShowWindow(SW_SHOWNA);
}


BOOL COXCustomizeCommandsPage::SaveToolbarState(CToolBar* pToolbar)
{
	ASSERT(pToolbar!=NULL);

	// save the state into the registry
	BOOL bResult=TRUE;
	CString sRegistryKey;
	sRegistryKey.Format(_T("Toolbar_ID_%d"),pToolbar->GetDlgCtrlID());
	if(pToolbar->IsKindOf(RUNTIME_CLASS(COXCoolToolBar)))
	{
		COXCoolToolBar* pCoolToolbar=
			DYNAMIC_DOWNCAST(COXCoolToolBar,pToolbar);
		ASSERT(pCoolToolbar!=NULL);
		bResult=pCoolToolbar->SaveBarState(_T("Toolbars State"),sRegistryKey,TRUE);
	}
	else
	{
#ifndef _MAC
		CWinApp* pApp=AfxGetApp();
		ASSERT(pApp!=NULL);
		// make sure you called CWinApp::SetRegistryKey() functions before
		if(pApp->m_pszRegistryKey!=NULL && pApp->m_pszProfileName!=NULL)
		{
			// we use default registry key assigned to your application by MFC
			HKEY hSecKey=pApp->GetSectionKey(_T(""));
			if(hSecKey!=NULL)
			{
				pToolbar->GetToolBarCtrl().SaveState(hSecKey,
					_T("Toolbars State"),sRegistryKey);
				::RegCloseKey(hSecKey);
			}
			else
			{
				TRACE(_T("COXCustomizeToolbarsPage::SaveToolbarState: unable to get the section key\n"));
				return FALSE;
			}
		}
		else
		{
			TRACE(_T("COXCustomizeToolbarsPage::SaveToolbarState: failed to save the toolbars state, SetRegistryKey() function hasn't been called\n"));
			return FALSE;
		}
#else
		return FALSE;
#endif
	}

	return bResult;
}

BOOL COXCustomizeCommandsPage::LoadToolbarState(CToolBar* pToolbar)
{
	ASSERT(pToolbar!=NULL);

	BOOL bResult=TRUE;
	CString sRegistryKey;
	sRegistryKey.Format(_T("Toolbar_ID_%d"),pToolbar->GetDlgCtrlID());
	if(pToolbar->IsKindOf(RUNTIME_CLASS(COXCoolToolBar)))
	{
		COXCoolToolBar* pCoolToolbar=DYNAMIC_DOWNCAST(COXCoolToolBar,pToolbar);
		ASSERT(pCoolToolbar!=NULL);
		bResult=pCoolToolbar->LoadBarState(_T("Toolbars State"),sRegistryKey,TRUE);
	}
	else
	{
#ifndef _MAC
		CWinApp* pApp=AfxGetApp();
		ASSERT(pApp!=NULL);
		// make sure you called CWinApp::SetRegistryKey() functions before
		if(pApp->m_pszRegistryKey==NULL || pApp->m_pszProfileName==NULL)
		{
			TRACE(_T("COXCustomizeToolbarsPage::LoadToolbarState: failed to restore the toolbars state, SetRegistryKey() function hasn't been called\n"));
			return FALSE;
		}
		// we use default registry key assigned to your application by MFC
		HKEY hSecKey=pApp->GetSectionKey(_T(""));
		if (hSecKey==NULL)
		{
			TRACE(_T("COXCustomizeToolbarsPage::LoadToolbarState: unable to get the section key\n"));
			return FALSE;
		}
		pToolbar->GetToolBarCtrl().RestoreState(hSecKey,
			_T("Toolbars State"),sRegistryKey);
		::RegCloseKey(hSecKey);
#endif
	}

	return bResult;
}


BOOL COXCustomizeCommandsPage::SaveWorkspaceState()
{
	if(!COXCustomizePage::SaveWorkspaceState())
		return FALSE;

	// save info about recently used menu commands
	VERIFY(GetBMOrganizer()->SaveRUCommandsState(_T("RecentlyUsedMenuItems")));
	GetBMOrganizer()->Empty();


	CWnd* pWnd=AfxGetMainWnd();
	ASSERT(pWnd!=NULL);
	CFrameWnd* pFrameWnd=DYNAMIC_DOWNCAST(CFrameWnd,pWnd);
	ASSERT(pFrameWnd!=NULL);

	// Iterate all the control bars and use only the toolbars
	POSITION pos=pFrameWnd->m_listControlBars.GetHeadPosition();
	while(pos!=NULL)
	{
		CToolBar* pToolbar=DYNAMIC_DOWNCAST(CToolBar, 
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos));
		//If its a CToolBar
		if(pToolbar!=NULL)
		{
			// save the state into the registry
			VERIFY(SaveToolbarState(pToolbar));
		}
	}

	return TRUE;
}


void COXCustomizeCommandsPage::OnTBCustomizeCommand(UINT nID, NMHDR* pNMHDR, 
													LRESULT* pResult)
{
	UNUSED(nID);

	*pResult=0;
	
	NMCTBCUSTOMIZE* pNMCTBCustomize=(NMCTBCUSTOMIZE*)pNMHDR;

	ASSERT(::GetDlgCtrlID(pNMCTBCustomize->nmhdr.hwndFrom)==(int)nID);

	CWnd* pWnd=CWnd::FromHandlePermanent(pNMCTBCustomize->nmhdr.hwndFrom);
	ASSERT(pWnd!=NULL);
	COXCoolToolBar* pCoolToolBar=DYNAMIC_DOWNCAST(COXCoolToolBar,pWnd);
	ASSERT(pCoolToolBar!=NULL);
	ASSERT(pCoolToolBar->IsInAdvancedCustomizationMode());
	int nCustomizedButtonIndex=pCoolToolBar->GetCustomizedButton();

	COXMenuBar* pMenuBar=DYNAMIC_DOWNCAST(COXMenuBar,pCoolToolBar);
	if(pMenuBar!=NULL)
	{
		ResetPopupMenus(0);
	}

	switch(pNMCTBCustomize->nCustomizeEventID)
	{
	case ID_OXCUSTTB_APPEARANCE:
		{
			ASSERT(nCustomizedButtonIndex!=-1);
			UINT nButtonCmdID=pCoolToolBar->GetItemID(nCustomizedButtonIndex);

			COXButtonAppearanceDlg dlgAppearance;
			BOOL bCustomButton=pCoolToolBar->IsCustomButton(nCustomizedButtonIndex);
			dlgAppearance.SetCustomButton(bCustomButton);
			
			OXCUSTOMBUTTONDESCRIPTOR descriptor;
			int nImageIndex=-1;
			TBBUTTON button;
			VERIFY(pCoolToolBar->
				GetToolBarCtrl().GetButton(nCustomizedButtonIndex,&button));
			CImageList imageList;
			if(!pCoolToolBar->IsKindOf(RUNTIME_CLASS(COXMenuBar)))
			{
				if(!bCustomButton)
				{
					nImageIndex=button.iBitmap;
				}
				else
				{
					VERIFY(pCoolToolBar->
						GetCustomButton(nCustomizedButtonIndex,descriptor));
					nImageIndex=descriptor.m_nImageIndex;
				}
				ASSERT(nImageIndex!=-1);
				VERIFY(imageList.Create(ID_OXCUSTOMIZE_TBIMAGE_WIDTH,
					ID_OXCUSTOMIZE_TBIMAGE_HEIGHT,ILC_COLOR24|ILC_MASK,0,0));
				// first of all add the current button image
				HICON hIcon=m_ilImages.ExtractIcon(nImageIndex);
				ASSERT(hIcon!=NULL);
				VERIFY(imageList.Add(hIcon)!=-1);
				VERIFY(::DestroyIcon(hIcon));
				// then add all images
				for(int nButtonIndex=ID_OX_IMAGEOFFSET_COUNT; 
					nButtonIndex<m_ilImages.GetImageCount(); 
					nButtonIndex++)
				{
					HICON hIcon=m_ilImages.ExtractIcon(nButtonIndex);
					ASSERT(hIcon!=NULL);
					VERIFY(imageList.Add(hIcon)!=-1);
					VERIFY(::DestroyIcon(hIcon));
				}
				// set the image list to be displayed in the dialog
				dlgAppearance.SetImageList(&imageList);
				dlgAppearance.m_nCustomImageIndex=0;

				if(!bCustomButton)
				{
					// set dropdown flag
					dlgAppearance.m_bDropDown=
						((button.fsStyle&TBSTYLE_DROPDOWN)==TBSTYLE_DROPDOWN);
					
					// get button text (or recent used text or text assigned to the
					// corresponding command ID)
					CString sText=pCoolToolBar->GetButtonText(nCustomizedButtonIndex);
					dlgAppearance.m_nButtonType=(sText.IsEmpty() ? 0 : 1);
					if(sText.IsEmpty())
					{
						sText=pCoolToolBar->GetRecentButtonText(nButtonCmdID);
						if(sText.IsEmpty())
						{
							HINSTANCE hInstance=
								AfxFindResourceHandle(MAKEINTRESOURCE(nButtonCmdID),
								RT_STRING);
							if(hInstance!=NULL)
							{
								sText.LoadString(nButtonCmdID);
								int nPosition=sText.Find(_T('\n'));
								if(nPosition!=-1)
									sText=sText.Mid(nPosition+1);
							}
						}
					}
					dlgAppearance.m_sText=sText;
				}
				else
				{
					dlgAppearance.m_nHeight=descriptor.m_nHeight;
					dlgAppearance.m_nWidth=descriptor.m_nWidth;
					dlgAppearance.m_bDisplayFloat=
						((descriptor.m_nFlags&OXCBD_SHOWFLOAT)==OXCBD_SHOWFLOAT);
					dlgAppearance.m_bDisplayHorzDock=
						((descriptor.m_nFlags&OXCBD_SHOWHORZ)==OXCBD_SHOWHORZ);
					dlgAppearance.m_bDisplayVertDock=
						((descriptor.m_nFlags&OXCBD_SHOWVERT)==OXCBD_SHOWVERT);
				}
			}
			else
			{
				ASSERT(!bCustomButton);
// v9.3 update 02 - GetMenu in COXMenuBar changed to return CMenu* - use GetHMenu
#if _MFC_VER >= 0x0800 
				HMENU hMenu = pMenuBar->GetHMenu();
#else
				HMENU hMenu = pMenuBar->GetMenu();
#endif
				ASSERT(hMenu!=NULL);
				MENUITEMINFO menuItemInfo={ sizeof(MENUITEMINFO) };
				menuItemInfo.fMask=MIIM_TYPE;
				menuItemInfo.cch=256;
				CString sText;
				menuItemInfo.dwTypeData=sText.GetBuffer(menuItemInfo.cch);
				VERIFY(::GetMenuItemInfo(hMenu,nCustomizedButtonIndex,TRUE,
					&menuItemInfo));
				sText.ReleaseBuffer();
				ASSERT(!sText.IsEmpty());
				dlgAppearance.m_sText=sText;

				dlgAppearance.m_nButtonType=-1;

				dlgAppearance.SetModifyTextOnly(TRUE);
				dlgAppearance.SetStyleReadOnly(TRUE);
			}

			if(dlgAppearance.DoModal()==IDOK)
			{
				if(pMenuBar==NULL)
				{
					if(!bCustomButton)
					{
						BOOL bRedraw=FALSE;

						CString sText=
							pCoolToolBar->GetButtonText(nCustomizedButtonIndex);
						if(dlgAppearance.m_nButtonType==0 && !sText.IsEmpty())
						{
							VERIFY(pCoolToolBar->
								SetButtonText(nCustomizedButtonIndex,_T("")));
							bRedraw=TRUE;
						}
						else if(dlgAppearance.m_nButtonType==1)
						{
							VERIFY(pCoolToolBar->SetButtonText(nCustomizedButtonIndex,
								dlgAppearance.m_sText));
							bRedraw=TRUE;
						}

						BOOL bChangeButtonInfo=FALSE;
						if(((button.fsStyle&TBSTYLE_DROPDOWN)==TBSTYLE_DROPDOWN)!=
							dlgAppearance.m_bDropDown)
						{
							if(dlgAppearance.m_bDropDown)
							{
								button.fsStyle|=TBSTYLE_DROPDOWN;
							}
							else
							{
								button.fsStyle&=~TBSTYLE_DROPDOWN;
							}
							bChangeButtonInfo=TRUE;
						}
						if(dlgAppearance.m_nCustomImageIndex!=0 &&
							dlgAppearance.m_nCustomImageIndex!=nImageIndex+1)
						{
							button.iBitmap=dlgAppearance.m_nCustomImageIndex-1+
								ID_OX_IMAGEOFFSET_COUNT;
							bChangeButtonInfo=TRUE;
						}
						if(bChangeButtonInfo)
						{
							pCoolToolBar->SetButtonInfo(nCustomizedButtonIndex,
								button.idCommand,button.fsStyle,button.iBitmap);
							bRedraw=TRUE;
						}

						if(bRedraw)
						{
							pCoolToolBar->RedrawToolBar(TRUE,TRUE);
						}
					}
					else
					{
						int nFlags=
							(dlgAppearance.m_bDisplayFloat ? OXCBD_SHOWFLOAT : 0) |
							(dlgAppearance.m_bDisplayHorzDock ? OXCBD_SHOWHORZ : 0) |
							(dlgAppearance.m_bDisplayVertDock ? OXCBD_SHOWVERT : 0);
						if(descriptor.m_nFlags!=nFlags || 
							descriptor.m_nHeight!=dlgAppearance.m_nHeight || 
							descriptor.m_nWidth!=dlgAppearance.m_nWidth ||
							(dlgAppearance.m_nCustomImageIndex!=0 &&
							dlgAppearance.m_nCustomImageIndex!=nImageIndex+1))
						{
							descriptor.m_nFlags=nFlags;
							descriptor.m_nHeight=dlgAppearance.m_nHeight;
							descriptor.m_nWidth=dlgAppearance.m_nWidth;
							if(dlgAppearance.m_nCustomImageIndex!=0)
							{
								descriptor.m_nImageIndex=
									dlgAppearance.m_nCustomImageIndex-1;
							}

							int nCustomButtonIndex=
								pCoolToolBar->GetCustomButtonIndex(descriptor.m_nID);
							ASSERT(nCustomButtonIndex!=-1);
							VERIFY(pCoolToolBar->
								SetCustomButton(nCustomButtonIndex,descriptor));
						}
					}
				}
				else
				{
					CString sText=pCoolToolBar->GetButtonText(nCustomizedButtonIndex);
					if(!dlgAppearance.m_sText.IsEmpty() && 
						sText.Compare(dlgAppearance.m_sText)!=0)
					{
// v9.3 update 02 - GetMenu in COXMenuBar changed to return CMenu* - use GetHMenu
#if _MFC_VER >= 0x0800 
						HMENU hMenu= pMenuBar->GetHMenu();
#else
						HMENU hMenu= pMenuBar->GetMenu();
#endif
						ASSERT(hMenu!=NULL);
						MENUITEMINFO menuItemInfo={ sizeof(MENUITEMINFO) };
						menuItemInfo.fMask=MIIM_TYPE;
						menuItemInfo.cch=256;
						CString sText;
						menuItemInfo.dwTypeData=sText.GetBuffer(menuItemInfo.cch);
						VERIFY(::GetMenuItemInfo(hMenu,nCustomizedButtonIndex,TRUE,
							&menuItemInfo));
						sText.ReleaseBuffer();
						sText=dlgAppearance.m_sText;
						menuItemInfo.cch=sText.GetLength();
						menuItemInfo.dwTypeData=sText.GetBuffer(menuItemInfo.cch);
						VERIFY(::SetMenuItemInfo(hMenu,nCustomizedButtonIndex,TRUE,
							&menuItemInfo));
						sText.ReleaseBuffer();
						pMenuBar->DrawMenuBar();
						pMenuBar->MarkAsChanged();
					}
				}
			}
	
			*pResult=1;
			break;
		}

	case ID_OXCUSTTB_SET_CUSTOMIZE_BUTTON:
		{
			if(nCustomizedButtonIndex==-1 && m_pCustomizedToolbar!=NULL)
			{
				if(pCoolToolBar!=m_pCustomizedToolbar)
					m_pCustomizedToolbar->SetCustomizedButton(-1);
				
				m_pCustomizedToolbar=NULL;
			}
			else if(pCoolToolBar!=m_pCustomizedToolbar && 
				nCustomizedButtonIndex!=-1)
			{
				if(m_pCustomizedToolbar!=NULL)
					m_pCustomizedToolbar->SetCustomizedButton(-1);
				m_pCustomizedToolbar=pCoolToolBar;
			}
			m_btnModifySelection.EnableWindow(m_pCustomizedToolbar!=NULL);
			break;
		}

	case ID_OXCUSTMB_CUSTOMIZE_POPUP_MENU:
		{
			if(nCustomizedButtonIndex!=-1 && GetBMOrganizer()->IsAttached())
			{
				ASSERT(pMenuBar!=NULL);

// v9.3 update 02 - GetMenu in COXMenuBar changed to return CMenu* - use GetHMenu
#if _MFC_VER >= 0x0800 
				HMENU hMenu= pMenuBar->GetHMenu();
#else
				HMENU hMenu= pMenuBar->GetMenu();
#endif
				ASSERT(hMenu!=NULL);
				CMenu* pMenu=CMenu::FromHandle(hMenu);
				ASSERT(pMenu!=NULL);
				ASSERT(nCustomizedButtonIndex>=0 && 
					nCustomizedButtonIndex<(int)pMenu->GetMenuItemCount());
				CMenu* pPopupMenu=pMenu->GetSubMenu(nCustomizedButtonIndex);

				OXCUSTOMIZEPOPUPMENUINFO* pCPMI=
					(OXCUSTOMIZEPOPUPMENUINFO*)pNMCTBCustomize->lParam;
				ASSERT(pCPMI!=NULL);
				ASSERT(pPopupMenu->GetSafeHmenu()==pCPMI->hMenu);

				if(m_nCustomizedPopupMenuIndex!=nCustomizedButtonIndex)
				{
					COXBitmapMenuPopupWnd* pBMPopupWnd=GetFirstFreeBMPopupWnd(0);
					ASSERT(pBMPopupWnd!=NULL);
					m_nCustomizedPopupMenuIndex=nCustomizedButtonIndex;

					COXBitmapMenu* pBMSubmenu=
						DYNAMIC_DOWNCAST(COXBitmapMenu,pPopupMenu);
					if(pBMSubmenu==NULL)
					{
						HMENU hMenu=pPopupMenu->GetSafeHmenu();
						GetBMOrganizer()->OnInitMenuPopup(pPopupMenu,0,FALSE);
						pPopupMenu=CMenu::FromHandle(hMenu);
						pBMSubmenu=DYNAMIC_DOWNCAST(COXBitmapMenu,pPopupMenu);
						ASSERT(pBMSubmenu!=NULL);
					}

					pBMPopupWnd->TrackPopupMenu(pBMSubmenu,
						pCPMI->nFlags&(TPM_CENTERALIGN|TPM_LEFTALIGN|TPM_RIGHTALIGN),
						pCPMI->ptStart.x,pCPMI->ptStart.y,this);
				}
				else
				{
					m_nCustomizedPopupMenuIndex=-1;
				}
			}
			break;
		}

	case ID_OXCUSTTB_DELETE:
		{
			if(pMenuBar!=NULL && m_nCustomizedPopupMenuIndex==nCustomizedButtonIndex)
			{
				m_nCustomizedPopupMenuIndex=-1;
			}
			break;
		}
	}
}


void COXCustomizeCommandsPage::OnBMCustomizeCommand(UINT nID, NMHDR* pNMHDR, 
													LRESULT* pResult)
{
	UNUSED(nID);

	*pResult=0;
	
	NMBMCUSTOMIZE* pNMBMCustomize=(NMBMCUSTOMIZE*)pNMHDR;

	ASSERT(::GetDlgCtrlID(pNMBMCustomize->nmhdr.hwndFrom)==(int)nID);

	CWnd* pWnd=CWnd::FromHandlePermanent(pNMBMCustomize->nmhdr.hwndFrom);
	ASSERT(pWnd!=NULL);
	COXBitmapMenuPopupWnd* pPopupWnd=DYNAMIC_DOWNCAST(COXBitmapMenuPopupWnd,pWnd);
	ASSERT(pPopupWnd!=NULL);
	COXBitmapMenu* pBitmapMenu=pPopupWnd->GetBitmapMenu();
	ASSERT(pBitmapMenu!=NULL);
	int nCustomizedItemIndex=pBitmapMenu->GetCustomizedItem();

	if(pNMBMCustomize->nCustomizeEventID!=ID_OXCUSTBM_SET_CUSTOMIZE_ITEM && 
		pNMBMCustomize->nCustomizeEventID!=ID_OXCUSTBM_SET_INSERT_MARK)
	{
		int nLevel=GetBMPopupWndLevel(pPopupWnd);
		ASSERT(nLevel>=0 || nLevel==-1);
		if(nLevel>=0)
		{
			ResetPopupMenus(nLevel+1);
		}
	}

	switch(pNMBMCustomize->nCustomizeEventID)
	{
	case ID_OXCUSTBM_APPEARANCE:
		{
			ASSERT(nCustomizedItemIndex!=-1);

			MENUITEMINFO mii={ sizeof(MENUITEMINFO) };
			mii.fMask=MIIM_DATA|MIIM_TYPE;
			::GetMenuItemInfo(pBitmapMenu->GetSafeHmenu(),
				nCustomizedItemIndex,TRUE,&mii);

			if(mii.fType & MFT_SEPARATOR)
				break;

			COXItemInfo* pItemInfo=(COXItemInfo*)(mii.dwItemData);
			CString sText=pItemInfo->GetText();
			ASSERT(!sText.IsEmpty());
			COXImageInfo* pImageInfo=pItemInfo->GetImageInfo();

			COXButtonAppearanceDlg dlgAppearance;
			
			CImageList imageList;
			VERIFY(imageList.Create(ID_OXCUSTOMIZE_TBIMAGE_WIDTH,
				ID_OXCUSTOMIZE_TBIMAGE_HEIGHT,ILC_COLOR24|ILC_MASK,0,0));
			// first of all add the current button image
			HICON hIcon=pImageInfo->GetImageList()->
				ExtractIcon(pImageInfo->GetIndex());
			ASSERT(hIcon!=NULL);
			VERIFY(imageList.Add(hIcon)!=-1);
			VERIFY(::DestroyIcon(hIcon));
			// then add all images
			for(int nItemIndex=ID_OX_IMAGEOFFSET_COUNT; 
				nItemIndex<m_ilImages.GetImageCount(); 
				nItemIndex++)
			{
				HICON hIcon=m_ilImages.ExtractIcon(nItemIndex);
				ASSERT(hIcon!=NULL);
				VERIFY(imageList.Add(hIcon)!=-1);
				VERIFY(::DestroyIcon(hIcon));
			}
			// set the image list to be displayed in the dialog
			dlgAppearance.SetImageList(&imageList);
			dlgAppearance.m_nCustomImageIndex=0;

			// set dropdown flag
			dlgAppearance.m_bDropDown=FALSE;

			CString sShortkeyText(_T(""));
			// only for commands try to retrieve accelerator key strings
			if((int)pBitmapMenu->GetMenuItemID(nCustomizedItemIndex)>0)
			{
				int nShortkeyTextPos=sText.Find(_T('\t'));
				if(nShortkeyTextPos!=-1)
				{
					sShortkeyText=sText.Mid(nShortkeyTextPos+1);
					sText=sText.Left(nShortkeyTextPos);
				}
				dlgAppearance.SetShortkeyReadOnly(FALSE);
#ifdef OX_CUSTOMIZE_SHORTKEYS
				BOOL bFoundShortkey=FALSE;
				COXShortkeysOrganizer* pShortkeysOrganizer=
					m_pCustomizeManager->GetShortkeysOrganizer();
				if(pShortkeysOrganizer!=NULL)
				{
					CMultiDocTemplate* pDocTemplate=NULL;
					if(m_pCustomizeManager->IsMDIFramework())
					{
						CMDIFrameWnd* pFrameWnd=
							DYNAMIC_DOWNCAST(CMDIFrameWnd,AfxGetMainWnd());
						ASSERT(pFrameWnd!=NULL);
						CMDIChildWnd* pChildWnd=pFrameWnd->MDIGetActive();
						if(pChildWnd!=NULL)
						{
							CDocument* pDocument=pChildWnd->GetActiveDocument();
							if(pDocument!=NULL)
							{
								pDocTemplate=DYNAMIC_DOWNCAST(CMultiDocTemplate,
									pDocument->GetDocTemplate());
							}
						}
					}
					COXArrAccelerators arrAccels;
					pShortkeysOrganizer->FindAllAccelerators(
						(WORD)pBitmapMenu->GetMenuItemID(nCustomizedItemIndex),
						pDocTemplate,arrAccels);
					for(int nIndex=0; nIndex<arrAccels.GetSize(); nIndex++)
					{
						ACCEL accel=arrAccels[nIndex];
						CString sNewShortkeyText=
							COXShortkeysOrganizer::GetAccelKeyString(&accel);
						if(!bFoundShortkey && 
							sShortkeyText.CompareNoCase(sNewShortkeyText)==0)
						{
							bFoundShortkey=TRUE;
							dlgAppearance.m_nShortkeyIndex=
   								PtrToInt(dlgAppearance.m_arrShortkeyEntries.Add(sNewShortkeyText));
						}
						else
						{
							dlgAppearance.m_arrShortkeyEntries.Add(sNewShortkeyText);
						}
					}
				}
				if(!bFoundShortkey)
#endif	//	OX_CUSTOMIZE_SHORTKEYS
				{
					if(!sShortkeyText.IsEmpty())
					{
						dlgAppearance.m_nShortkeyIndex=
							PtrToInt(dlgAppearance.m_arrShortkeyEntries.Add(sShortkeyText));
					}
				}
			}
		
			dlgAppearance.m_sText=sText;
			dlgAppearance.SetStyleReadOnly(TRUE);
			dlgAppearance.SetModifyTextOnly(TRUE);

			if(dlgAppearance.DoModal()==IDOK)
			{
				CString sNewShortkeyText=dlgAppearance.GetShortkeyText();
				if(!dlgAppearance.m_sText.IsEmpty() && 
					(sText.Compare(dlgAppearance.m_sText)!=0 || 
					sShortkeyText.Compare(sNewShortkeyText)!=0))
				{
					if(sNewShortkeyText.IsEmpty())
					{
						pItemInfo->SetText(dlgAppearance.m_sText);
					}
					else
					{
						pItemInfo->SetText(dlgAppearance.m_sText+_T("\t")+
							sNewShortkeyText);
					}
					pPopupWnd->OnMenuChanged();

					COXMenuBar* pMenuBar=COXMenuBar::FindMenuBar();
					if(pMenuBar!=NULL)
					{
						pMenuBar->MarkAsChanged();
					}
				}
			}
	
			*pResult=1;
			break;
		}

	case ID_OXCUSTBM_SET_CUSTOMIZE_ITEM:
		{
			if(nCustomizedItemIndex!=-1 && 
				pBitmapMenu->GetMenuItemID(nCustomizedItemIndex)==-1)
			{
				CMenu* pSubmenu=pBitmapMenu->GetSubMenu(nCustomizedItemIndex);
				COXBitmapMenu* pBMSubmenu=DYNAMIC_DOWNCAST(COXBitmapMenu,pSubmenu);
				BOOL bDisplaySubmenu=(pBMSubmenu==NULL || 
					pBMSubmenu->GetPopupWnd()==NULL ||
					!::IsWindow(pBMSubmenu->GetPopupWnd()->GetSafeHwnd()) ||
					!pBMSubmenu->GetPopupWnd()->IsWindowVisible());
				// hide all existing submenus on this level
				int nLevel=GetBMPopupWndLevel(pPopupWnd);
				ASSERT(nLevel>=0 || nLevel==-1);
				if(nLevel>=0)
				{
					ResetPopupMenus(nLevel+1);
				}
				// display new submenu
				if(bDisplaySubmenu)
				{
					// submenu item has been marked for customization. As a result
					// child popup menu must be displayed
					COXBitmapMenuPopupWnd* pBMPopupWnd=
						(pBMSubmenu==NULL ? NULL : pBMSubmenu->GetPopupWnd());
					if(pBMPopupWnd==NULL)
					{
						pBMPopupWnd=GetFirstFreeBMPopupWnd(nLevel+1);
					}
					ASSERT(pBMPopupWnd!=NULL);
					CRect rect=pPopupWnd->GetItemRect(nCustomizedItemIndex);
					pPopupWnd->ClientToScreen(rect);
					pPopupWnd->CalcWindowRect(rect);
					CRect rectWindow;
					pPopupWnd->GetWindowRect(rectWindow);
					
					if(pBMSubmenu==NULL)
					{
						HMENU hMenu=pSubmenu->GetSafeHmenu();
						GetBMOrganizer()->OnInitMenuPopup(pSubmenu,0,FALSE);
						pSubmenu=CMenu::FromHandle(hMenu);
						pBMSubmenu=DYNAMIC_DOWNCAST(COXBitmapMenu,pSubmenu);
						ASSERT(pBMSubmenu!=NULL);
					}

					pBMPopupWnd->TrackPopupMenu(pBMSubmenu,TPM_LEFTALIGN,
						rectWindow.right,rect.top,this);
				}
			}
			else
			{
				// hide all existing submenus on this level
				int nLevel=GetBMPopupWndLevel(pPopupWnd);
				ASSERT(nLevel>=0 || nLevel==-1);
				if(nLevel>=0)
				{
					ResetPopupMenus(nLevel+1);
				}
			}
			break;
		}

	case ID_OXCUSTBM_SET_INSERT_MARK:
		{
			CPoint ptMouse;
			::GetCursorPos(&ptMouse);
			pPopupWnd->ScreenToClient(&ptMouse);
			BOOL bBefore=TRUE;
			int nInsertMarkIndex=pBitmapMenu->HitTest(&ptMouse,&bBefore);
			if(nInsertMarkIndex!=-1 && 
				pBitmapMenu->GetMenuItemID(nInsertMarkIndex)==-1 &&
				pBitmapMenu->GetDraggedItem()!=nInsertMarkIndex)
			{
				CMenu* pSubmenu=pBitmapMenu->GetSubMenu(nInsertMarkIndex);
				COXBitmapMenu* pBMSubmenu=DYNAMIC_DOWNCAST(COXBitmapMenu,pSubmenu);
				BOOL bDisplaySubmenu=(pBMSubmenu==NULL || 
					pBMSubmenu->GetPopupWnd()==NULL ||
					!::IsWindow(pBMSubmenu->GetPopupWnd()->GetSafeHwnd()) ||
					!pBMSubmenu->GetPopupWnd()->IsWindowVisible());
				// display new submenu
				if(bDisplaySubmenu)
				{
					// hide all existing submenus on this level
					int nLevel=GetBMPopupWndLevel(pPopupWnd);
					ASSERT(nLevel>=0 || nLevel==-1);
					if(nLevel>=0)
					{
						ResetPopupMenus(nLevel+1);
					}

					// child popup menu must be displayed
					COXBitmapMenuPopupWnd* pBMPopupWnd=
						(pBMSubmenu==NULL ? NULL : pBMSubmenu->GetPopupWnd());
					if(pBMPopupWnd==NULL)
					{
						pBMPopupWnd=GetFirstFreeBMPopupWnd(nLevel+1);
					}
					ASSERT(pBMPopupWnd!=NULL);
					CRect rect=pPopupWnd->GetItemRect(nInsertMarkIndex);
					pPopupWnd->ClientToScreen(rect);
					pPopupWnd->CalcWindowRect(rect);
					CRect rectWindow;
					pPopupWnd->GetWindowRect(rectWindow);

					if(pBMSubmenu==NULL)
					{
						HMENU hMenu=pSubmenu->GetSafeHmenu();
						GetBMOrganizer()->OnInitMenuPopup(pSubmenu,0,FALSE);
						pSubmenu=CMenu::FromHandle(hMenu);
						pBMSubmenu=DYNAMIC_DOWNCAST(COXBitmapMenu,pSubmenu);
						ASSERT(pBMSubmenu!=NULL);
					}

					pBMPopupWnd->TrackPopupMenu(pBMSubmenu,TPM_LEFTALIGN,
						rectWindow.right,rect.top,this);
				}
			}
			break;
		}

	case ID_OXCUSTBM_RECENTLY_USED:
	case ID_OXCUSTBM_DELETE:
	case ID_OXCUSTBM_SEPARATOR_BEFORE:
	case ID_OXCUSTBM_SEPARATOR_AFTER:
	case ID_OXCUSTBM_DELETE_ITEM:
	case ID_OXCUSTBM_INSERT_ITEM:
		{
			COXMenuBar* pMenuBar=COXMenuBar::FindMenuBar();
			if(pMenuBar!=NULL)
			{
				pMenuBar->MarkAsChanged();
			}
			break;
		}
	}
}


void COXCustomizeCommandsPage::OnDropDownModifySelection(NMHDR* pNotifyStruct, 
														 LRESULT* result)
{
	UNREFERENCED_PARAMETER(pNotifyStruct);

	ASSERT(m_pCustomizedToolbar!=NULL);
	int nCustomizedButtonIndex=m_pCustomizedToolbar->GetCustomizedButton();
	ASSERT(nCustomizedButtonIndex!=-1);

	CRect rect;
	m_btnModifySelection.GetWindowRect(rect);
	m_pCustomizedToolbar->
		DisplayCustomizeButtonContextMenu(nCustomizedButtonIndex,
		CPoint(rect.left,rect.bottom+1));

	*result=0;
}


COXBitmapMenuPopupWnd* COXCustomizeCommandsPage::
GetFirstFreeBMPopupWnd(int nMenuLevel/*=0*/)
{
	BOOL bFound=FALSE;
	COXBitmapMenuPopupWnd* pBMPopupWnd=NULL;
	POSITION pos=m_mapBMPopupWnd.GetStartPosition();
	int nLevel=-1;
	while(pos!=NULL)
	{
		m_mapBMPopupWnd.GetNextAssoc(pos,pBMPopupWnd,nLevel);
		ASSERT(pBMPopupWnd!=NULL);
		ASSERT(nLevel>=0);
		if(pBMPopupWnd->GetBitmapMenu()==NULL)
		{
			bFound=FALSE;
			break;
		}
	}
	if(!bFound)
	{
		pBMPopupWnd=new COXBitmapMenuPopupWnd;
	}
	ASSERT(pBMPopupWnd!=NULL);

	m_mapBMPopupWnd.SetAt(pBMPopupWnd,nMenuLevel);

	return pBMPopupWnd;
}


void COXCustomizeCommandsPage::ResetPopupMenus(int nMenuLevel/*=0*/)
{
	BOOL bOwnDragAndDrop=FALSE;
	POSITION pos=m_mapBMPopupWnd.GetStartPosition();
	COXBitmapMenuPopupWnd* pBMPopupWnd=NULL;
	int nLevel=-1;
	while(pos!=NULL)
	{
		m_mapBMPopupWnd.GetNextAssoc(pos,pBMPopupWnd,nLevel);
		ASSERT(pBMPopupWnd!=NULL);
		ASSERT(nLevel>=0);

		COXBitmapMenu* pMenu=pBMPopupWnd->GetBitmapMenu();
		if(pMenu!=NULL)
		{
			bOwnDragAndDrop|=pMenu->IsDragDropOwner();
		}

		if(nLevel>=nMenuLevel && ::IsWindowVisible(pBMPopupWnd->GetSafeHwnd()))
		{
			pBMPopupWnd->ResetPopupMenu();
		}
	}
	
	if(!bOwnDragAndDrop && nMenuLevel==0 && GetBMOrganizer()->IsAttached())
	{
		GetBMOrganizer()->Empty();
		GetBMOrganizer()->AutoSetMenuImage();
	}
}


int COXCustomizeCommandsPage::GetBMPopupWndLevel(COXBitmapMenuPopupWnd* pBMPopupWnd)
{
	ASSERT(pBMPopupWnd!=NULL);

	POSITION pos=m_mapBMPopupWnd.GetStartPosition();
	COXBitmapMenuPopupWnd* pTempBMPopupWnd=NULL;
	int nLevel=-1;
	while(pos!=NULL)
	{
		m_mapBMPopupWnd.GetNextAssoc(pos,pTempBMPopupWnd,nLevel);
		ASSERT(pTempBMPopupWnd!=NULL);
		ASSERT(nLevel>=0);
		if(pTempBMPopupWnd==pBMPopupWnd && ::IsWindow(pTempBMPopupWnd->GetSafeHwnd()))
		{
			return nLevel;
		}
	}

	return -1;
}


void COXCustomizeCommandsPage::ConvertToolbar(CToolBar* pToolbar)
{
	ASSERT(pToolbar!=NULL);
	ASSERT(pToolbar->GetToolBarCtrl().GetButtonCount()==0);

	pToolbar->
		SendMessage(TB_SETIMAGELIST,NULL,(LPARAM)((HIMAGELIST)m_ilImages));


	COXCoolToolBar* pCoolToolbar=
		DYNAMIC_DOWNCAST(COXCoolToolBar,pToolbar);
	if(pCoolToolbar!=NULL)
	{
		pCoolToolbar->
			SetBitmapIds(m_arrCommandIds,PtrToInt(m_mapCommands.GetCount()));
		// make sure toolbar is in list mode
		pCoolToolbar->SetList(TRUE);
		pCoolToolbar->IniSizes(CSize(ID_OXCUSTOMIZE_TBIMAGE_WIDTH,
			ID_OXCUSTOMIZE_TBIMAGE_HEIGHT));
	}
}


HMENU COXCustomizeCommandsPage::BuildMenuFromTree(HTREEITEM hParentItem)
{
	ASSERT(hParentItem!=NULL);
	HTREEITEM hChildItem=m_treeCommands.GetNextItem(hParentItem,TVGN_CHILD);
	if(hChildItem==NULL)
	{
		return NULL;
	}

	HMENU hMenu=::CreatePopupMenu();
	ASSERT(hMenu!=NULL);

	while(hChildItem!=NULL)
	{
		CString sText(_T(""));
		int nCommandID=0;
		HMENU hSubmenu=NULL;
		DWORD_PTR dwData=m_treeCommands.GetItemData(hChildItem);
		if(dwData==0 || dwData==-2)
		{
			ASSERT(FALSE);
		}
		else if(dwData==-1)
		{
			// existing popup menu
			sText=m_treeCommands.GetItemText(hChildItem);
			nCommandID=-1;
			hSubmenu=BuildMenuFromTree(hChildItem);
		}
		else 
		{
			nCommandID=(int)dwData;

			HINSTANCE hInstance=
				AfxFindResourceHandle(MAKEINTRESOURCE(nCommandID),RT_STRING);
			ASSERT(hInstance!=NULL);
			sText.LoadString(nCommandID);
			int nPosition=sText.Find(_T('\n'));
			if(nPosition!=-1)
				sText=sText.Mid(nPosition+1);
			if(sText.IsEmpty())
				sText=m_treeCommands.GetItemText(hChildItem);
		}
		ASSERT(!sText.IsEmpty());

		if(hSubmenu==NULL)
		{
			VERIFY(::AppendMenu(hMenu,MF_STRING,nCommandID,sText));
		}
		else
		{
			VERIFY(::AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT_PTR)hSubmenu,sText));
		}

		hChildItem=m_treeCommands.GetNextItem(hChildItem,TVGN_NEXT);
	}

	return hMenu;
}


void COXCustomizeCommandsPage::BuildArrayCommandIDs()
{
	int nCommandCount=PtrToInt(m_mapCommands.GetCount());
	if(nCommandCount!=0)
	{
		if(m_arrCommandIds!=NULL)
		{
			delete[] m_arrCommandIds;
		}

		m_arrCommandIds=new UINT[nCommandCount];
		ASSERT(m_arrCommandIds!=NULL);
		
		int nCommandWithoutImageCount=0;
		POSITION pos=m_mapCommands.GetStartPosition();
		UINT nCommandID=NULL;
		int nImageIndex=-1;
		while(pos!=NULL)
		{
			m_mapCommands.GetNextAssoc(pos,nCommandID,nImageIndex);
			ASSERT(nCommandID>0);
			if(nImageIndex!=-1)
			{
				ASSERT(nImageIndex-ID_OX_IMAGEOFFSET_COUNT<
					nCommandCount-nCommandWithoutImageCount);
				m_arrCommandIds[nImageIndex-ID_OX_IMAGEOFFSET_COUNT]=nCommandID;
			}
			else
			{
				nCommandWithoutImageCount++;
				m_arrCommandIds[nCommandCount-nCommandWithoutImageCount]=nCommandID;
			}
		}
	}
}


BOOL COXCustomizeCommandsPage::IsCustomCommand(UINT nCmdID)
{
	CString sText;
	return (m_mapCustomCommands.Lookup(nCmdID,sText));
}


BOOL COXCustomizeCommandsPage::GetCustomCommand(UINT nCmdID, CString& sText, 
												int& nImageIndex, CString& sHierarchy)
{
	if(!m_mapCustomCommands.Lookup(nCmdID,sText))
	{
		sText.Empty();
		nImageIndex=-1;
		sHierarchy.Empty();
		return FALSE;
	}

	VERIFY(m_mapCommands.Lookup(nCmdID,nImageIndex));
	VERIFY(m_mapCustomCommandsHierarchy.Lookup(nCmdID,sHierarchy));

	return TRUE;
}

BOOL COXCustomizeCommandsPage::AddCustomCommand(UINT nCmdID, int nIDCmd, 
		int nImageIndex, int nIDHierarchy)
{
	CString sCommand, sHierarchy;
	VERIFY(sCommand.LoadString(nIDCmd));
	VERIFY(sHierarchy.LoadString(nIDHierarchy));
	return AddCustomCommand(nCmdID, sCommand,nImageIndex, sHierarchy);
}

BOOL COXCustomizeCommandsPage::AddCustomCommand(UINT nCmdID, 
												LPCTSTR pszCmdText, 
												int nImageIndex/*=-1*/, 
												LPCTSTR pszHierarchy/*=_T("Custom commands")*/)
{
	if(nCmdID==0 || lstrlen(pszCmdText)==0 || lstrlen(pszHierarchy)==0)	
	{
		TRACE(_T("COXCustomizeCommandsPage::AddCustomCommand: invalid parameters\n"));
		return FALSE;
	}

	int nFoundImageIndex=-1;
	if(m_mapCommands.Lookup(nCmdID,nFoundImageIndex))
	{
		TRACE(_T("COXCustomizeCommandsPage::AddCustomCommand: command with specified ID exists already\n"));
		return FALSE;
	}

	m_mapCustomCommands.SetAt(nCmdID,pszCmdText);
	m_mapCustomCommandsHierarchy.SetAt(nCmdID,pszHierarchy);
	m_mapCommands.SetAt(nCmdID,nImageIndex);
	// rebuild array of all command IDs
	BuildArrayCommandIDs();

	// Iterate all the control bars and use only the toolbars
	CWnd* pWnd=AfxGetMainWnd();
	ASSERT(pWnd!=NULL);
	CFrameWnd* pFrameWnd=DYNAMIC_DOWNCAST(CFrameWnd,pWnd);
	ASSERT(pFrameWnd!=NULL);
	POSITION pos=pFrameWnd->m_listControlBars.GetHeadPosition();
	while(pos!=NULL)
	{
		CToolBar* pToolbar=DYNAMIC_DOWNCAST(CToolBar, 
			(CControlBar*)pFrameWnd->m_listControlBars.GetNext(pos));
		//If it is a CToolBar
		if(pToolbar!=NULL)
		{
			COXCoolToolBar* pCoolToolbar=
				DYNAMIC_DOWNCAST(COXCoolToolBar,pToolbar);
			if(pCoolToolbar!=NULL)
			{
				pCoolToolbar->
					SetBitmapIds(m_arrCommandIds,PtrToInt(m_mapCommands.GetCount()));
			}
		}
	}

	return TRUE;
}


BOOL COXCustomizeCommandsPage::AddCustomCommandsToTree()
{
	ASSERT(m_mapCustomCommands.GetCount()==m_mapCustomCommandsHierarchy.GetCount());

	POSITION pos=m_mapCustomCommands.GetStartPosition();
	while(pos!=NULL)
	{
		UINT nCmdID;
		CString sText;
		CString sHierarchy;
		m_mapCustomCommands.GetNextAssoc(pos,nCmdID,sText);
		ASSERT(!sText.IsEmpty());
		ASSERT(nCmdID>0);
		if(!FindCommandInTree(nCmdID,TVI_ROOT))
		{
			VERIFY(m_mapCustomCommandsHierarchy.Lookup(nCmdID,sHierarchy));
			ASSERT(!sHierarchy.IsEmpty());

			// analyze hierarchy (hierarchy items are divided using '\t' character)
			HTREEITEM hParentItem=TVI_ROOT;
			int nPos=sHierarchy.Find(_T('\t'));
			CString sHierarchyItem;
			while(TRUE)
			{
				if(nPos!=-1)
				{
					sHierarchyItem=sHierarchy.Left(nPos);
					sHierarchy=sHierarchy.Mid(nPos+1);
				}
				else
				{
					sHierarchyItem=sHierarchy;
				}

				HTREEITEM hFoundItem=FindMenuItemInTree(sHierarchyItem,hParentItem);
				if(hFoundItem!=NULL)
				{
					hParentItem=hFoundItem;
				}
				else
				{
					hParentItem=m_treeCommands.
						InsertItem(sHierarchyItem,ID_OX_IMAGEOFFSET_MENUGROUP,
						ID_OX_IMAGEOFFSET_MENUGROUP,hParentItem,TVI_LAST);
					ASSERT(hParentItem!=NULL);
					m_treeCommands.SetItemData(hParentItem,(DWORD)-1);
					m_treeCommands.SetItemState(hParentItem,TVIS_BOLD,TVIS_BOLD);
				}

				if(nPos!=-1)
				{
					nPos=sHierarchy.Find(_T('\t'));
				}
				else
				{
					break;
				}
			}

			// insert item in the tree 
			//

			// retrieve image
			int nImageIndex=-1;
			VERIFY(m_mapCommands.Lookup(nCmdID,nImageIndex));
			if(nImageIndex==-1)
			{
				nImageIndex=ID_OX_IMAGEOFFSET_NOIMAGE;
			}

			HTREEITEM hItem=m_treeCommands.
				InsertItem(sText,nImageIndex,nImageIndex,hParentItem,TVI_LAST);
			ASSERT(hItem!=NULL);
			m_treeCommands.SetItemData(hItem,(LPARAM)nCmdID);

			//
			////////////////////////////////
		}
	}

	return TRUE;
}


HTREEITEM COXCustomizeCommandsPage::FindCommandInTree(UINT nCmdID, 
													  HTREEITEM hParentItem) const
{
	ASSERT(nCmdID>0);
	ASSERT(hParentItem!=NULL);

	HTREEITEM hChildItem=m_treeCommands.GetNextItem(hParentItem,TVGN_CHILD);

	HTREEITEM hFoundItem=NULL;
	while(hChildItem!=NULL)
	{
		if(m_treeCommands.ItemHasChildren(hChildItem))
		{
			hFoundItem=FindCommandInTree(nCmdID,hChildItem);
			if(hFoundItem!=NULL)
			{
				break;
			}
		}
		else
		{
			DWORD_PTR dwData=m_treeCommands.GetItemData(hChildItem);
			if((UINT_PTR)dwData==nCmdID)
			{
				hFoundItem=hChildItem;
				break;
			}
		}

		hChildItem=m_treeCommands.GetNextItem(hChildItem,TVGN_NEXT);
	}

	return hFoundItem;
}

void COXCustomizeCommandsPage::OnCheckIconsInMenu() 
{
	UpdateData();	
}

void COXCustomizeCommandsPage::OnCheckShowOnlyRecentlyUsed() 
{
	UpdateData();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions