Click here to Skip to main content
15,884,702 members
Articles / Desktop Programming / MFC

Professional User Interface Suite

Rate me:
Please Sign up or sign in to vote.
4.99/5 (174 votes)
13 Jan 200423 min read 1.5M   23.5K   641  
MFC extension library enabling software to be provided with a professional UI
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
///                                                                    ///
/// Professional User Interface Suite (TM)                             ///
/// Copyright (C) 2001-2002 by Foss Software Inc.                      ///
///                                                                    ///
/// http://www.fossware.com                                            ///
/// mailto:foss@fossware.com                                           ///
///                                                                    ///
///                                                                    ///
/// This software and accompanying documentation is the copyrighted    ///
/// work of Foss Software Inc.                                         ///
///                                                                    ///
/// Use of this software is governed by the following conditions:      ///
///                                                                    ///
///   a) this software is free for any kind of personal and            ///
///      commercial usage;                                             ///
///                                                                    ///
///   a) you may not reproduce, record, publish, publicly exhibit      ///
///      or distribute this source code without author's express       ///
///      prior written consent (foss@fossware.com);                    ///
///                                                                    ///
///   b) this notice should be remained intact in distributed source   ///
///      files;                                                        ///
///                                                                    ///
///   c) this software is subject to all Warranties and Disclaimers    ///
///      as set forth below;                                           ///
///                                                                    ///
/// Warranties and Disclaimers:                                        ///
///                                                                    ///
/// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND     ///
/// INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,      ///
/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.             ///
/// IN NO EVENT WILL FOSS SOFTWARE INC. BE LIABLE FOR ANY DIRECT,      ///
/// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES, ///
/// INCLUDING DAMAGES FOR LOSS OF PROFITS, LOSS OR INACCURACY OF DATA, ///
/// INCURRED BY ANY PERSON FROM SUCH PERSON'S USAGE OF THIS SOFTWARE   ///
/// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.                ///
///                                                                    ///
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

#if (!defined __EXT_TOOLCONTROLBAR_H)
#define __EXT_TOOLCONTROLBAR_H

#if (!defined __EXT_MFC_DEF_H)
	#include <ExtMfcDef.h>
#endif // __EXT_MFC_DEF_H

#if (!defined __EXT_CONTROLBAR_H)
	#include <ExtControlBar.h>
#endif

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

/////////////////////////////////////////////////////////////////////////////
// CExtBarButton

class __PROF_UIS_API CExtBarButton : public CObject
{
protected:
	UINT _GetTrackPopupFlags();

public:
	DECLARE_DYNAMIC(CExtBarButton)

protected:
	CExtToolControlBar * m_pBar;
	UINT	m_nCmdID; // Command ID or ID_SEPARATOR
	UINT	m_nStyle; // button styles
	
	CSize	m_ActiveSize;
	CRect	m_ActiveRect;
	
	BOOL	m_bWrap,
			m_bVisible,m_bHover,
			m_bCtrlAutoDestroyed,
			m_bVertDocked,
			m_bPopupMenu,
			m_bAutoDestroyMenu,
			m_bAppendMdiWindowsMenu
			;

	CWnd *	m_pCtrl;
	HMENU m_hMenu;

	void _InitMembers()
	{
		m_pBar = NULL;
		m_nCmdID = ID_SEPARATOR;
		m_pCtrl = NULL;
		m_bCtrlAutoDestroyed = FALSE;
		m_nStyle = 0;
		m_ActiveSize.cx = m_ActiveSize.cy = 0;
		m_ActiveRect.SetRectEmpty();
		m_bWrap = m_bHover = FALSE;
		m_bVisible = TRUE;
		m_bVertDocked = FALSE;
		m_hMenu = NULL;
		m_bPopupMenu = FALSE;
		m_bAutoDestroyMenu = FALSE;
		m_bAppendMdiWindowsMenu = FALSE;
	};

	void _UpdateCtrl()
	{
		if( m_pCtrl == NULL )
			return;
		ASSERT_VALID( m_pCtrl );
		m_pCtrl->ShowWindow(
			(m_bVisible && (!m_bVertDocked)) ? SW_SHOW : SW_HIDE
			);
		m_pCtrl->EnableWindow( IsEnabled() );
		if( m_pCtrl->IsKindOf(RUNTIME_CLASS(CButton)) )
		{
			int nCheck = 0;
			if( IsPressed() )
				nCheck = 1;
			else if( IsIndeterminate() )
				nCheck = 2;
			((CButton *)(m_pCtrl))->SetCheck( nCheck );
		}
//		if( m_bVisible && m_bHover )
//			m_pCtrl->SetFocus();
	};
	void _UpdateCmdIdFromStyle()
	{
		if( m_nStyle & TBBS_SEPARATOR )
		{
			m_nStyle &= ~(TBBS_BUTTON);
			m_nCmdID = ID_SEPARATOR;
		}
		else
		{
			m_nStyle |= TBBS_BUTTON;
		}
	};

	void _DestroyMenu()
	{
		if( m_hMenu == NULL )
			return;
		if( m_bAutoDestroyMenu )
		{
			ASSERT( ::IsMenu(m_hMenu) );
			VERIFY( ::DestroyMenu(m_hMenu) );
		}
		m_hMenu = NULL;
	}

public:
	CExtBarButton(
		CExtToolControlBar * pBar,
		UINT nCmdID = ID_SEPARATOR,
		UINT nStyle = 0
		)
	{
		_InitMembers();
		ASSERT( pBar != NULL );
		m_pBar = pBar;
		m_nStyle = nStyle;
		SetCmdID( nCmdID );
	};
	~CExtBarButton()
	{
		_DestroyMenu();
	};

	virtual UINT GetCmdID() const
	{
		return m_nCmdID;
	};
	virtual void SetCmdID( UINT nCmdID )
	{
		m_nCmdID = nCmdID;
		if( m_nCmdID == ID_SEPARATOR )
		{
			m_nStyle |= TBBS_SEPARATOR;
			m_nStyle &= ~(TBBS_BUTTON);
		}
		else
		{
			m_nStyle |= TBBS_BUTTON;
			m_nStyle &= ~(TBBS_SEPARATOR);
		}
	};

	virtual CWnd * CtrlGet()
	{
		return m_pCtrl;
	};
	virtual void CtrlSet(
		CWnd * pCtrl,
		BOOL bCtrlAutoDestroyed
		)
	{
		if( m_pCtrl != NULL )
		{
			if( ::IsWindow(m_pCtrl->GetSafeHwnd()) )
				m_pCtrl->DestroyWindow();
			if( !m_bCtrlAutoDestroyed )
				delete m_pCtrl;
		}
		m_pCtrl = pCtrl;
		m_bCtrlAutoDestroyed = bCtrlAutoDestroyed;
#ifdef _DEBUG
		if( m_pCtrl != NULL )
		{
			ASSERT_VALID( m_pCtrl );
		}
#endif // _DEBUG
	};

	virtual UINT GetStyle() const
	{
		return m_nStyle;
	};
	virtual void SetStyle( UINT nStyle )
	{
		m_nStyle = nStyle;
		_UpdateCmdIdFromStyle();
		_UpdateCtrl();
	};
	virtual void ModifyStyle(
		UINT nAdd,
		UINT nRemove = 0
		)
	{
		m_nStyle |= nAdd;
		m_nStyle &= ~nRemove;
		_UpdateCmdIdFromStyle();
		_UpdateCtrl();
	};

	virtual void SetVertDocked( BOOL bVertDocked )
	{
		m_bVertDocked = bVertDocked;
	}

	virtual BOOL IsWrap() const
	{
		return m_bWrap;
	};
	virtual void SetWrap( BOOL bWrap = TRUE )
	{
		m_bWrap = bWrap;
	};

	virtual BOOL IsSeparator() const
	{
		BOOL bSeparator =
			(GetStyle() & TBBS_SEPARATOR) ?
				TRUE : FALSE;
		return bSeparator;
	};
	virtual BOOL IsDisabled() const
	{
		BOOL bDisabled =
			(GetStyle() & TBBS_DISABLED) ?
				TRUE : FALSE;
		return bDisabled;
	};
	virtual BOOL IsEnabled() const
	{
		return !( IsDisabled() );
	};
	virtual BOOL IsIndeterminate() const
	{
		BOOL bIndeterminate =
			(GetStyle() & TBBS_INDETERMINATE) ?
				TRUE : FALSE;
		return bIndeterminate;
	};
	virtual BOOL IsPressed() const
	{
		BOOL bPressed =
			(GetStyle() & (TBBS_PRESSED|TBBS_CHECKED)) ?
				TRUE : FALSE;
		return bPressed;
	};

	virtual void Show( BOOL bShow = TRUE )
	{
		m_bVisible = bShow;
		_UpdateCtrl();
	};
	virtual BOOL IsVisible() const
	{
		return m_bVisible;
	};

	virtual void SetHover( BOOL bHover = TRUE )
	{
		m_bHover = bHover;
		_UpdateCtrl();
	};
	virtual BOOL IsHover() const
	{
		return m_bHover;
	};

	virtual CString GetText() const;
	
	virtual void SetRect( const RECT & rectButton )
	{
		m_ActiveRect = rectButton;
		if( (m_pCtrl != NULL) && (!m_bVertDocked) )
		{
			ASSERT_VALID( m_pCtrl );
			//m_pCtrl->MoveWindow( &m_ActiveRect,FALSE );
			CRect rcCtrl;
			m_pCtrl->GetWindowRect( &rcCtrl );
			CRect rcMove(
				m_ActiveRect.TopLeft(),
				rcCtrl.Size()
				);
			m_pCtrl->MoveWindow( &rcMove,FALSE );
		} // if( (m_pCtrl != NULL) && (!m_bVertDocked) )
		_UpdateCtrl();
	};
	virtual CRect Rect() const
	{
		return m_ActiveRect;
	};
	operator CRect() const
	{
		return Rect();
	};

	virtual CSize Size() const
	{
		return m_ActiveSize;
	};
	operator CSize() const
	{
		return m_ActiveSize;
	};

	virtual BOOL IsContainerOfPopupLikeMenu()
	{
		ASSERT( m_hMenu != NULL );
		ASSERT( ::IsMenu(m_hMenu) );
		return m_bPopupMenu;
	}
	virtual void SetMenu(
		HMENU hMenu,
		BOOL bPopupMenu,
		BOOL bAutoDestroyMenu
		);
	const HMENU GetMenu() const
	{
		return m_hMenu;
	};
	operator const HMENU() const
	{
		return GetMenu();
	};
	virtual HMENU GetMenu()
	{
		return m_hMenu;
	};
	operator HMENU()
	{
		return GetMenu();
	};
	virtual void SetAppendMdiWindowsMenu(
		BOOL bAppendMdiWindowsMenu
		)
	{
		m_bAppendMdiWindowsMenu = bAppendMdiWindowsMenu;
	};
	virtual BOOL IsAppendMdiWindowsMenu()
	{
		return m_bAppendMdiWindowsMenu;
	};

	virtual bool IsAbleToTrackMenu();

	virtual CSize CalculateLayout(
		CDC & dc,
		CSize sizePreCalc,
		BOOL bHorz
		);

	virtual BOOL PutToPopupMenu(
		CExtPopupMenuWnd * pPopup
		);

	virtual HICON GetHICON();

	virtual CWnd * GetCmdTargetWnd();

	virtual void Paint(
		CDC & dc,
		bool bHorz
		);

	virtual void OnTrackPopup(
		CPoint point
		);
	virtual void OnHover(
		CPoint point,
		bool bOn
		);
	virtual void OnClick(
		CPoint point,
		bool bDown
		);

}; // class CExtBarButton


/////////////////////////////////////////////////////////////////////////////
// CExtBarContentExpandButton

typedef
	CArray < CExtBarButton *, CExtBarButton * >
	_tb_buttons_container_t;

#define __ID_TOOLBAR_RIGHT_BUTTON__ ((UINT)-66)
#define __RIGHT_BUTTON_HORZ_DX__ 14
#define __RIGHT_BUTTON_VERT_DY__ 12

class CExtPopupBaseWnd;
class CExtPopupMenuWnd;

class __PROF_UIS_API CExtBarContentExpandButton : public CExtBarButton
{
public:
	DECLARE_DYNAMIC(CExtBarContentExpandButton)

protected:
	bool m_bClearContent;

	_tb_buttons_container_t m_buttons;

public:
	CExtBarContentExpandButton(
		CExtToolControlBar * pBar
		) :
		CExtBarButton(pBar)
	{
		SetCmdID( __ID_TOOLBAR_RIGHT_BUTTON__ );
	};
	~CExtBarContentExpandButton()
	{
		CExtBarButton::~CExtBarButton();
	}

	bool IsContentClear()
	{
		ASSERT_VALID( this );
		return m_bClearContent;
	};
	void ClearContent( bool bClearContent = true )
	{
		if( this == NULL )
			return;
		ASSERT_VALID( this );
		m_bClearContent = bClearContent;
	};

	const _tb_buttons_container_t & GetButtons() const
	{
		return m_buttons;
	};
	_tb_buttons_container_t & GetButtons()
	{
		return m_buttons;
	};

	virtual CSize CalculateLayout(
		CDC & dc,
		CSize sizePreCalc,
		BOOL bHorz
		);

	virtual BOOL PutToPopupMenu(
		CExtPopupMenuWnd * pPopup
		);

	virtual void Paint(
		CDC & dc,
		bool bHorz
		);

	virtual void OnTrackPopup(
		CPoint point
		);
	virtual void OnHover(
		CPoint point,
		bool bOn
		);
	virtual void OnClick(
		CPoint point,
		bool bDown
		);

}; // class CExtBarContentExpandButton

/////////////////////////////////////////////////////////////////////////////
// CExtToolControlBar

class __PROF_UIS_API CExtToolControlBar : public CExtControlBar
{
public:
	DECLARE_DYNAMIC(CExtToolControlBar)

private:
	friend class CExtBarButton;
	friend class CExtBarContentExpandButton;
	friend class CExtBarMdiDocButton;
	class CExtToolControlBarCmdUI;
	friend class CExtPopupBaseWnd;
	friend class CExtPopupMenuWnd;

public:
	bool IsRightExpandButton(int nBtnIdx);
protected:
	CExtBarContentExpandButton * m_pRightBtn;

	_tb_buttons_container_t m_buttons;
	
	void _RemoveAllButtonsImpl();
	int _GetButtonsCountImpl() const;

// Construction
public:
	CExtToolControlBar();
	void SetSizes(
		SIZE sizeTBB,
		SIZE sizeImage = CSize(0,0) // unsed in this version
		);
				// ORIGINALLY button size should be bigger than image

	BOOL LoadToolBar(
		LPCTSTR lpszResourceName
		);
	BOOL LoadToolBar(
		UINT nIDResource
		)
	{
		return
			LoadToolBar(
				MAKEINTRESOURCE(nIDResource)
				);
	};
	
	BOOL InsertButton(
		int nPos = -1, // append
		UINT nCmdID = ID_SEPARATOR,
		BOOL bDoRecalcLayout = TRUE
		);
	BOOL RemoveButton(
		int nPos,
		BOOL bDoRecalcLayout = TRUE
		);

	BOOL SetButtons(
		const UINT * lpIDArray = NULL,
		int nIDCount = 0
		); // lpIDArray can be NULL to allocate empty buttons

// Attributes
public: // standard control bar things
	int CommandToIndex( UINT nIDFind ) const;
	UINT GetButtonID( int nIndex ) const;
	virtual void GetButtonRect( int nIndex, LPRECT lpRect ) const;
	UINT GetButtonStyle( int nIndex ) const;
	void SetButtonStyle( int nIndex, UINT nStyle );

public:
	// for changing button info
	void GetButtonInfo(
		int nIndex,
		UINT & nID,
		UINT & nStyle
		) const;
	void SetButtonInfo(
		int nIndex,
		UINT nID,
		UINT nStyle
		);

	CWnd * GetButtonCtrl(
		int nIndex
		);
	BOOL SetButtonCtrl(
		int nIndex,
		CWnd * pCtrl = NULL,
		BOOL bCtrlAutoDestroyed = TRUE
		);

	int GetButtonByAccessKey( TCHAR vkTCHAR );

	HMENU GetButtonMenu(
		int nIndex
		);
	BOOL SetButtonMenu(
		int nIndex,
		HMENU hMenu = NULL,
		BOOL bPopupMenu = TRUE,
		BOOL bAutoDestroyMenu = TRUE,
		BOOL bDoRecalcLayout = TRUE
		);
	BOOL MarkButtonAsMdiWindowsMenu(
		int nIndex,
		BOOL bAppendMdiWindowsMenu = TRUE
		);
	virtual BOOL TrackButtonMenu(
		int nIndex
		);
	int GetVisibleButton(
		int nBtnIdx,
		BOOL bNext
		);

	int GetButtonsCount() const
	{
		return _GetButtonsCountImpl();
	};
	int GetMenuTrackingButton() const
	{
		return m_nBtnIdxMenuTracking;
	};

// Implementation
public:
	virtual ~CExtToolControlBar();
	virtual CSize CalcFixedLayout(
		BOOL bStretch,
		BOOL bHorz
		);
    virtual CSize CalcDynamicLayout(
		int nLength,
		DWORD dwMode
		);

#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:
	CExtBarButton* _GetButtonPtr( int nIndex ) const;
	void _InvalidateButton( int nIndex );
	void _UpdateButton( int nIndex );

protected:
	bool _UpdateHoverButton(
		CPoint point = CPoint(-1,-1) // default is use ::GetCursorPos()
		);

	virtual DWORD RecalcDelayShow(
		AFX_SIZEPARENTPARAMS * lpLayout
		);

	virtual void _RecalcPositionsImpl();
	virtual void _RecalcLayoutImpl();

	// input CRect should be client rectangle size
	void _CalcInsideRect(
		CRect & rect,
		BOOL bHorz
		) const;
	
	CSize _CalcLayout(
		DWORD dwMode,
		int nLength = -1
		);
	CSize _CalcSize( BOOL bVerticallyDocked );
	void _SizeToolBar(
		int nLength,
		BOOL bVert = FALSE
		);
	int _WrapToolBar(
		int nWidth,
		int nHeight = 32767
		);
	CSize _GetButtonSize()
	{
		return m_sizeTBB;
	};
	int _GetIndexOf( CExtBarButton * pTBB )
	{
		if( pTBB == NULL )
			return -1;
		int nCountOfButtons = m_buttons.GetSize();
		for( int nBtnIdx=0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		{
			ASSERT( m_buttons[nBtnIdx] != NULL );
			if( m_buttons[nBtnIdx] == pTBB )
				return nBtnIdx;
		}
		return -1;
	};
	void _SwitchMenuTrackingIndex(
		int iNewMenuTrackingIndex = -1
		);
	static CExtToolControlBar * _GetMenuTrackingBar();
	static void _CloseTrackingMenus();

	static void _CbPaintCombinedContent(
		LPVOID pCookie,
		CDC & dc,
		const CWnd & refWndMenu,
		const CRect & rcExcludeArea, // in screen coords
		int eCombineAlign // CExtPopupMenuWnd::e_combine_align_t values
		);

	static bool g_bMenuTracking;
	static bool g_bMenuTrackingExpanded;
	int m_nBtnIdxMenuTracking;
	CSize m_sizeTBB;         // size of button
	int m_nBtnIdxCapture;       // index of button with capture (-1 => none)
	int m_nBtnIdxHover;

	virtual void DoPaint( CDC* pDC );
	virtual void OnUpdateCmdUI(
		CFrameWnd* pTarget,
		BOOL bDisableIfNoHndler
		);
	int _HitTestImpl(
		CPoint point,
		UINT nButtonStyleInclude = 0, // button must have style
		UINT nButtonStyleExclude = 0  // button must have not style
		) const;
	virtual int HitTest( CPoint point ) const;
	virtual int OnToolHitTest(
		CPoint point,
		TOOLINFO * pTI
		) const;

	//{{AFX_MSG(CExtToolControlBar)
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnCancelMode();
	afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos);
	afx_msg void OnTimer(UINT nIDEvent);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

#endif // __EXT_TOOLCONTROLBAR_H

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Foss Software Inc
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions