Click here to Skip to main content
15,892,927 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 255.8K   23.7K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
// ==========================================================================
// 					Class Specification : COXAppBar
// ==========================================================================
//
// OXAppBar.h
// 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.
                          
// //////////////////////////////////////////////////////////////////////////

// Desciption :         
//
// Class COXAppBar provides functionality of Windows shell application bar  
// It is a template class and use CWnd derived class as a parent.
// COXAppBar has two constructors - one for generic CWnd derived class
// and another one for CDialog derived class. It is easy to use.
// To start use it call Register(TRUE). To Load prevous state call LoadState(),
// that returns TRUE on success, otherwise you can suply your own parameters.
// If you want to dock window on certain edge you can use function SetEdge().
// The two important state are Autohidden and AlwaysOnTop. To  set or remove these
// features call SetAutoHide() or SetAlwaysOnTop() with appropriate value - TRUE or FALSE
// Any edge can be excluded from docking state by function SetBarStyle()
// To see appbar styles use GetBarStyle(). You can also exclude ABE_FLOAT state,
// so your appbar always will be docked to some edge. Additional functionality is
// provided by  OX_APPBARS_DIFFERENT_DIMS. This flag (set on by default) indicate
// the appbar will provide different width and height for every state.
// Addidtional customization: set the width of the appbar in hidden state,
// time the autohidden appbar will wait while inactive until begin slide to hidden state,
// dimensions in any state and others .
// 
// To unregister appbar call Register(FALSE).
// Note: you must provide default constructor for your class will be used by COXAppBar


//Dependences:

//Header files
//#include "OXRegistryValFile.h"
//#include "OXAppBar.h"

//Cpp files:
//"OXRegistryValFile.cpp"

#if !defined(_OXAPPBAR_H__)
#define _OXAPPBAR_H__

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

#include "OXDllExt.h"
#include "OXRegistryValFile.h"
#include "OXMainRes.h"
#include "UTB64Bit.h"


///////////////////////////////////////////////////////////////////////////////
//definitions

const int OX_APPBAR_VERSION=0x0011;

//two additional styles
#define ABE_UNKNOWN 0x101
#define ABE_FLOAT 0x102


//default definitions
#define SLIDING_TIME 10		//time to slide window in autohide state
#define MIN_DIMENSION 2		//width of the appbar in hidden state
#define IDT_AUTOHIDE 1		//timer id for autohide state
#define DEFAULT_DIMENSION 28//default dimension of the appbar (width for right-left,
							//height for top-bottom)
#define DIM_TO_FLOAT 10		//how many pixels should be mouse away from docked
							//appbar to switch to float state
#define DIM_TO_DOCK 40		//how many pixels should be mouse near to an edge 
							//to switch from float state to docking state
#define DIM_CAPTION 6		//pixels from top of the window in float state to the cursor
#define TIMER_INTERVAL 100	//milliseconds - how much time will wait inactive autohidden
							//bar to start to move to hide

/////////////////////////////////////////////////////////////////////////////
//the styles can be set 

#define OX_APPBARS_LEFT 0x01 //can dock on the left
#define OX_APPBARS_TOP  0x02 //can dock on the top
#define OX_APPBARS_RIGHT 0x04 //can dock on the right
#define OX_APPBARS_BOTTOM 0x08 //can dock on the bottom
#define OX_APPBARS_ALL_EDGES (OX_APPBARS_LEFT | OX_APPBARS_TOP | OX_APPBARS_RIGHT | OX_APPBARS_BOTTOM)
#define OX_APPBARS_FLOAT 0x10 //can float
#define OX_APPBARS_DIFFERENT_DIMS 0x020 //remember different dimensions 
										//for every edge 
#define  OX_APPBARS_ALLS (OX_APPBARS_ALL_EDGES | OX_APPBARS_FLOAT | OX_APPBARS_DIFFERENT_DIMS)


typedef struct sMouse
{
	CPoint pt;//current mouse position
	BOOL bButtonDown;//TRUE on button down

	sMouse::sMouse():
	pt(0,0), bButtonDown(FALSE){}

}tMouse;

typedef struct sBarData 
{

	BOOL bRegistered;//TRUE when registered
	BOOL bOnTop;//TRUE when the bar has WS_EX_TOPMOST style
	BOOL bAutoHideDesired;//TRUE, if SHOULD BE in autohide state (may be in not
				   //the state due to error to set autohide state, but this
				   //variable means desired state that will be set on the edge)	
	BOOL bHiding;//TRUE while sliding the bar
	BOOL bHidden;//TRUE if hidden in autohide style, FALSE otherwise
	UINT nWidth;//default width of the bar
	UINT nHeight;//default height of the bar
	UINT nLeft;//width of the bar on the left edge
	UINT nTop;//height of the bar on the top edge
	UINT nRight;//width of the bar on the right edge
	UINT nBottom;//height of the bar on the bottom edge
	UINT nEdge;//edge the bar will be docked on or ABE_FLOAT, ABE_UNKNOWN
	UINT nDockEdge;//edge the bar is docked on, no ABE_FLOAT or ABE_UNKNOWN is allowed
	DWORD dwStyle;//styles applicable to the bar

	sBarData():
	bRegistered(FALSE), bOnTop(FALSE),
	bAutoHideDesired(FALSE), bHiding(FALSE), bHidden(FALSE),
	nWidth(DEFAULT_DIMENSION),
		nHeight(DEFAULT_DIMENSION), nLeft(DEFAULT_DIMENSION),
		nTop(DEFAULT_DIMENSION), nRight(DEFAULT_DIMENSION),
		nBottom(DEFAULT_DIMENSION), nEdge(ABE_UNKNOWN), nDockEdge(NULL),
		dwStyle(OX_APPBARS_ALLS)
	{}

}tBarData;


/////////////////////////////////////////////////////////////////////////////
// COXAppBar window

template <class PARENTWND>
class OX_CLASS_DECL COXAppBar : public PARENTWND
{
// public functions
public:

	// --- In  : 
	// --- Out : 
	// --- Returns :
	// --- Effect : Constructs the object
	COXAppBar();

	// --- In  : nId - resource ID of the dialog
	//			 pParent - pointer to the parent window
	// --- Out : 
	// --- Returns :
	// --- Effect : Constructs the object (for CDialog derived class)
	COXAppBar(UINT nId, CWnd* pParent=NULL);

	// --- In  : 
	// --- Out : 
	// --- Returns :
	// --- Effect : Destructor
	virtual ~COXAppBar();

	// --- In  : 
	// --- Out : 
	// --- Returns : pointer to structure tBarData
	// --- Effect : returns pointer to tBarData
	inline const tBarData* GetBarData() const {return &m_BarData;}

	// --- In  :	nWidth - new default width
	// --- Out : 
	// --- Returns :
	// --- Effect : sets new default width for the appbar
	inline void SetDefaultWidth(UINT nWidth) {m_BarData.nWidth=nWidth;}

	// --- In  :	nHeight - new default height
	// --- Out : 
	// --- Returns :
	// --- Effect : sets new default height for the appbar
	inline void SetDefaultHeight(UINT nHeight){m_BarData.nHeight=nHeight;}

	// --- In  : 
	// --- Out : 
	// --- Returns : a count of timer ticks the window slides on 1 pixel
	// --- Effect : call this function to retrieve the sliding time
	inline UINT GetSlidingTime() const {return m_nSlidingTime;} 

	// --- In  : nSlidingTime - a count of timer ticks the window slides on 1 pixel
	// --- Out : 
	// --- Returns :
	// --- Effect : call this function to change the sliding time
	inline void SetSlidingTime(UINT nSlidingTime) {m_nSlidingTime=nSlidingTime;}

	// --- In  : 
	// --- Out : 
	// --- Returns : width of the appbar while hidden
	// --- Effect : call this function to get width of the appbar in hidden state
	inline UINT GetHiddenWidth() const { return m_nHiddenWidth;}

	// --- In  : nHiddenWidth - new width of the appbar in hidden state
	// --- Out : 
	// --- Returns :
	// --- Effect : call this function to set new width of the appbar in hidden state
	inline void SetHiddenWidth(UINT nHiddenWidth) {m_nHiddenWidth=nHiddenWidth;}

	// --- In  : nToFloat - difference (pixels) between cursor and edge
	//						of the appbar when appbar will switch to the float state
	// --- Out : 
	// --- Returns :
	// --- Effect : call this function to set new value to switch to float state
	inline void SetPointToFloat(UINT nToFloat) {m_nToFloat=nToFloat;}

	// --- In  : 
	// --- Out : 
	// --- Returns : current difference (pixels) between cursor and edge
	//						of the appbar when appbar will switch to the float state
	// --- Effect : call this function to get current value to switch to float state
	inline UINT GetPointToFloat() const {return m_nToFloat;}

	// --- In  : nToDock - difference (pixels) between cursor and screen edge
	//						when appbar will switch to the docking state
	// --- Out : 
	// --- Returns :
	// --- Effect : call this function to set new value to switch to docking state
	inline void SetPointToDock(UINT nToDock) {m_nToDock=nToDock;}

	// --- In  : 
	// --- Out : 
	// --- Returns : difference (pixels) between cursor and screen edge
	//						when appbar will switch to the docking state
	// --- Effect : call this function to get the value the appbar 
	//				will switch to docking state
	inline UINT GetPointToDock() const {return m_nToDock;}

	// --- In  : nTimerInterval - time the appbar will remain unhidden 
	//								while inactive untill start to sliding
	// --- Out : 
	// --- Returns :
	// --- Effect : sets new timer interval value
	inline void SetTimerInterval(UINT nTimerInterval) {m_nTimerInterval=nTimerInterval;}

	// --- In  : 
	// --- Out : 
	// --- Returns : - time the appbar will remain unhidden 
	//					while inactive untill start to sliding
	// --- Effect : call this function to retrieve the value of timer interval
	inline UINT GetTimerInterval() const {return m_nTimerInterval;}

	// --- In  : dwStyle - new styles of the appbar
	//				The valid styles are:
	//					OX_APPBARS_LEFT - the appbar can dock 
	//						on the left edge of the screen
	//					OX_APPBARS_TOP - the appbar can dock
	//						on the top edge of the screen
	//					OX_APPBARS_RIGHT - the appbar can dock 
	//						on the right edge of the screen
	//					OX_APPBARS_BOTTOM - the appbar can dock
	//						on the bottom
	//					OX_APPBARS_ALL_EDGES - the appbar can dock
	//						on all edges of the screen 
	//					OX_APPBARS_FLOAT - the appbar can float
	//					OX_APPBARS_DIFFERENT_DIMS - the appbar has
	//						different dimensions for every edge 
	//					OX_APPBARS_ALLS - all posible styles
	// --- Out : 
	// --- Returns :
	// --- Effect : sets new styles for the appbar
	inline void SetBarStyle(DWORD dwStyle) 
	{
		m_BarData.dwStyle=(dwStyle & OX_APPBARS_ALLS);
	}

	// --- In  : 
	// --- Out : 
	// --- Returns : the appbar styles (See description function SetBarStyle())
	// --- Effect : returns the appbar styles
	inline DWORD GetBarStyle () const {return m_BarData.dwStyle;}

	// --- In  : 
	// --- Out : 
	// --- Returns : TRUE if autobar is in autohidden state. The appbar
	//				  may actually be hidden or unhidden at this moment (if is in
	//				  autohidden state).
	//				  To check actual state see variable 
	//				  bHidden in bar data (GetBarData()). There is a difference
	//				  between autohide state and desired autohide state.
	//				  Once you call SetAutoHide(TRUE), the desired state
	//				  (bAutoHideDesired in bar data - call GetBarData()) will
	//				  remain TRUE untill next call SetAutoHide(FALSE). This is
	//				  because the system can has only one autohidden bar per edge.
	//				  So, if there was not posibility to set autohidden state on
	//				  this edge, this function will return FALSE, while bAutoHideDesired 
	//				  will be TRUE. Next time the edge has been changed bAutoHideDesired
	//				  will forced to set autohide state on the new edge.
	// --- Effect : returns TRUE if the appbar is in autohidden state on this edge
	BOOL IsAutoHidden();

	// --- In  : 
	// --- Out : 
	// --- Returns : TRUE, if the appbar is floating, FALSE othewise.
	// --- Effect : call this function to check floating state of the appabar
	inline BOOL IsFloating() const {return (BOOL) (m_BarData.nEdge==ABE_FLOAT);}

	// --- In  : 
	// --- Out : 
	// --- Returns : TRUE, if the appbar is in topmost state
	// --- Effect : call this function to define if the appbar is
	//				in topmost state
	inline BOOL IsAlwaysOnTop() const {return m_BarData.bOnTop;}

	// --- In  : 
	// --- Out : 
	// --- Returns : TRUE, if appbar is registered, FALSE otherwise
	// --- Effect : call this function to define if the appbar is registered
    inline BOOL IsRegistered () const {return m_BarData.bRegistered;}

	// --- In  : 
	// --- Out : 
	// --- Returns : the edge appbar is docking on or ABE_FLOAT, if floating
	// --- Effect : call this function to get the edge 
	//				appbar is docking on, if any
	inline UINT GetEdge() const { return m_BarData.nEdge;}

	// --- In  : bOnTop - TRUE to set as topmost window, FALSE to remove
	// --- Out : 
	// --- Returns : 
	// --- Effect : call this function to change topmost style of the appbar
	void SetAlwaysOnTop(BOOL bOnTop);

	// --- In  : nEdge - the edge appbar should be docked on or float
	// --- Out : 
	// --- Returns :
	// --- Effect : call this function to change the edge of the appbar
	BOOL SetEdge(UINT nEdge);

	// --- In  : bHide - TRUE to set autohide style, FALSE to remove
	// --- Out : 
	// --- Returns : TRUE on success, FALSE otherwise.
	// --- Effect : Sets or removes autohidden state. The variable
	//				bHide will determine the autohidden state on all edges
	//				(See description of IsAutoHidden() function)
	BOOL SetAutoHide(BOOL bHide);

	// --- In  : bRegister - TRUE to register the appbar, FALSE to remove  
	// --- Out : 
	// --- Returns : TRUE on success, FALSE if the system 
	//				 could not register or the appbar has been registered
	//				 so far
	// --- Effect : Call this function to register or unregister appbar.
	//				The best way is before call this function
	//				call function IsRegistered() to check out the status 
	//				of the appbar
	BOOL Register(BOOL bRegister=TRUE);


	void SetDockDimension(UINT nEdge, UINT nWidth)
	{
		switch (nEdge)
		{
		case ABE_TOP:
			m_BarData.nTop=nWidth;
			break;
		case ABE_LEFT:
			m_BarData.nLeft=nWidth;
			break;
		case ABE_BOTTOM:
			m_BarData.nBottom=nWidth;
			break;
		case ABE_RIGHT:
			m_BarData.nRight=nWidth;
			break;
		default:
			ASSERT(FALSE);
		}
	}
//protected functions
protected:

	// --- In  : nEdge
	// --- Out : 
	// --- Returns :
	// --- Effect : Do nothing. Override this function 
	//				if you need to handle changes of the edges
	//				the appbar switching to
	virtual void OnSetEdge(UINT nEdge) { UNREFERENCED_PARAMETER(nEdge);}

	// --- In  : 
	// --- Out : 
	// --- Returns : TRUE on succes, FALSE otherwise
	// --- Effect : Call this function to restore last 
	//				saved state of the appbar
	virtual BOOL LoadState();

	// --- In  : 
	// --- Out : 
	// --- Returns :
	// --- Effect : Call this function to save appbar to the registry
	//				before call Register(FALSE);
	virtual void SaveState();

	// --- In  : 
	// --- Out : 
	// --- Returns :
	// --- Effect : override this function if you want provide 
	//				popup menu on mouse right-click
	virtual void DoPopupMenu(){/* do nothing - override to provide your own menu*/}

	virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam );
	
	void Float(APPBARDATA* pData);
	void UnFloat(APPBARDATA* pData);
	void AppBarCallback(UINT uMsg, WPARAM wParam, LPARAM lParam);
	void PosChanged();
	void SetPosition(APPBARDATA* pBarData,	BOOL bMove);
	void QueryPosition(RECT* pRect);
	void UnHide();
	void Hide();
	UINT GetProposedEdge();
	void GetEndRect(CRect& rect);
	void GetProposedRect(CRect& rect);
	BOOL CanContinue(CRect& rctCurrent, CRect& rctEnd);
	void SlideWindow();
	
	void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
	int  OnCreate(LPCREATESTRUCT lpCreateStruct);
	void OnDestroy();
	void OnLButtonDown(UINT nFlags, CPoint point);
	void OnLButtonUp(UINT nFlags, CPoint point);
	void OnMouseMove(UINT nFlags, CPoint point);
	void OnMove(int x, int y);
	LRESULT OnNcHitTest(CPoint point);
	void OnRButtonDown(UINT nFlags, CPoint point);
	// v9.3 - update 03 - 64-bit - using OXTPARAM here - see UTB64Bit.h
	void OnTimer(OXTPARAM nIDEvent);
	void OnWindowPosChanged(WINDOWPOS FAR* lpwndpos);
	void OnExitSizeMoveLoop();

//protected members
protected:
	CRect m_rctFloat; //coordinates of the window in the float state
	int m_nOffset;//switches between -1 and 1 indicating in what side slide
	tMouse m_stMouse;//position and state of the cursor
	tBarData m_BarData;//data related to the bar
	BOOL m_bSizeable;//to remember WS_THICKFRAME style while the bar is hidden 
	UINT m_nSlidingTime;//defines speed to slide
	UINT m_nHiddenWidth;//defines width of the window in the hidden state
	UINT m_nTimerInterval;//time to wait to start sliding bar while the bar is inactive
	UINT m_nToDock;//offset cursor from an edge that will be treated as switch to docking state
	UINT m_nToFloat;//offset cursor from the docking frame to switch to float
	BOOL m_bFloating;//TRUE while floating
};

/*
=========================================================================
======================IMPLEMENTATION=====================================
=========================================================================
*/

/////////////////////////////////////////////////////////////////////////////
// COXAppBar

////////////////////////////////////////////
//constructor for generic CWnd derived class

template <class PARENTWND>
COXAppBar<PARENTWND>::COXAppBar()
{
	ASSERT(PARENTWND::IsKindOf(RUNTIME_CLASS(CWnd)));
	m_nOffset=0;
	m_bSizeable=FALSE;
	m_nSlidingTime=SLIDING_TIME;
	m_nHiddenWidth=MIN_DIMENSION;
	m_nTimerInterval=TIMER_INTERVAL;
	m_nToDock=DIM_TO_DOCK;
	m_nToFloat=DIM_TO_FLOAT;
	m_bFloating=FALSE;
}

////////////////////////////////////////////
//constructor for CDialog derived classes

template <class PARENTWND>
COXAppBar<PARENTWND>::COXAppBar(UINT nId, CWnd* pParent):
PARENTWND(nId, pParent)
{
	m_nOffset=0;
	m_bSizeable=FALSE;
	m_nSlidingTime=TIMER_INTERVAL;
	m_nHiddenWidth=MIN_DIMENSION;
	m_nTimerInterval=TIMER_INTERVAL;
	m_nToDock=DIM_TO_DOCK;
	m_nToFloat=DIM_TO_FLOAT;
	m_bFloating=FALSE;
}



///////////////////////////////////////
//destructor

template <class PARENTWND>
COXAppBar<PARENTWND>::~COXAppBar()
{
}

/////////////////////////////////////////////////////////////////////////////
// COXAppBar message handlers

/////////////////////////////////////
//cannot define message handler in 
//template class - working with 
//WindowProc()

template <class PARENTWND>
LRESULT COXAppBar<PARENTWND>::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
#if defined (_WINDLL)
#if defined (_AFXDLL)
	AFX_MANAGE_STATE(AfxGetAppModuleState());
#else
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
#endif
#endif

	switch (message)
	{
	case WM_ACTIVATE:
		{
			OnActivate(LOWORD(wParam),
				(CWnd*) CWnd::FromHandle((HWND) lParam),
				(BOOL) HIWORD(wParam));
			return NULL;
		}
	case WM_CREATE:
		{
			return OnCreate((LPCREATESTRUCT) lParam);
		}
	case WM_DESTROY:
		{
			OnDestroy();
			return NULL;
		}
	case WM_LBUTTONDOWN:
		{
			CPoint point(LOWORD(lParam), HIWORD(lParam));
			OnLButtonDown((UINT) wParam, point);
			return NULL;
		}
	case WM_LBUTTONUP:
		{
			CPoint point(LOWORD(lParam), HIWORD(lParam));
			OnLButtonUp((UINT) wParam, point);
			return NULL;
		}
	case WM_MOUSEMOVE:
		{
			CPoint point(LOWORD(lParam), HIWORD(lParam));
			OnMouseMove((UINT) wParam, point);
			return NULL;
		}
	case WM_MOVE:
		{
			OnMove(LOWORD(lParam), HIWORD(lParam));
			return NULL;
		}
	case WM_NCHITTEST:
		{
			CPoint point(LOWORD(lParam), HIWORD(lParam));
			return OnNcHitTest(point);
		}
	case WM_RBUTTONDOWN:
		{
			CPoint point(LOWORD(lParam), HIWORD(lParam));
			OnRButtonDown((UINT) wParam, point);
			return NULL;
		}
	case WM_EXITSIZEMOVE:
		{
			OnExitSizeMoveLoop();
			return NULL;
		}
		break;
	case WM_TIMER:
		{
			OnTimer((UINT) wParam);
			return NULL;
		}
	case WM_WINDOWPOSCHANGED:
		{
			OnWindowPosChanged((WINDOWPOS*) lParam);
			return NULL;
		}
	
	default:
		{
			return PARENTWND::WindowProc(message, wParam, lParam);
		}
	}
}


//////////////////////////////////////////////////
//handlers for WindowProc()

//////////////////////////////////////////////////
//OnActivate(): if the bar is autohidden, Hide()
//or UnHide() it depends on the message

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
{
	PARENTWND::OnActivate(nState, pWndOther, bMinimized);
	
	ASSERT(PARENTWND::m_hWnd);
	
	APPBARDATA data;
	ZeroMemory((void*) &data, sizeof(data));
	data.cbSize=sizeof(APPBARDATA);
	data.hWnd=PARENTWND::m_hWnd;

	SHAppBarMessage(ABM_ACTIVATE, &data);

	if (!IsAutoHidden())
		return;

	switch (nState)
	{
		case WA_ACTIVE:
		case WA_CLICKACTIVE:
			if (m_BarData.bHidden)
				UnHide();
			break;

		case WA_INACTIVE:
			if (!m_BarData.bHidden)
				Hide();
			break;
	}
}

//////////////////////////////////////////
//OnCreate(): load default bar rect for
//floating state and SetTimer() for autohidden state

template <class PARENTWND>
int COXAppBar<PARENTWND>::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (PARENTWND::OnCreate(lpCreateStruct) == -1)
		return -1;

	PARENTWND::GetWindowRect(&m_rctFloat);

	PARENTWND::SetTimer(IDT_AUTOHIDE,m_nTimerInterval,NULL);
	return 0;
}

/////////////////////////////////////////
//ONDestroy(): Unregister and KillTimer()

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnDestroy() 
{
	Register(FALSE);
	PARENTWND::KillTimer(IDT_AUTOHIDE);
	PARENTWND::OnDestroy();
}

//////////////////////////////////////////
//OnLButtonDown(): start capture if registered

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if (IsRegistered())
	{
		m_stMouse.bButtonDown=TRUE;
		::GetCursorPos(&m_stMouse.pt);
		SetCapture();	
	}
	PARENTWND::OnLButtonDown(nFlags, point);
}

///////////////////////////////////////////////////
//OnLButtonUp(): ReleaseCapture() if was registared

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if (IsRegistered())
	{
		m_stMouse.bButtonDown=FALSE;
		::GetCursorPos(&m_stMouse.pt);
		ReleaseCapture();
	}
	PARENTWND::OnLButtonUp(nFlags, point);
}

////////////////////////////////////////////////////
//OnMouseMove() if registered:
//move window if is in float state,
//UnHide() if in hidden state.
//Check for new appropriate edge.

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (!IsRegistered())
	{
		PARENTWND::OnMouseMove(nFlags, point);
		return;
	}

	if (IsAutoHidden() && m_BarData.bHidden)
	{
		UnHide();
		return;
	}
 	if (!m_stMouse.bButtonDown || m_BarData.nEdge==ABE_UNKNOWN)
		return;

	//get current position 
	CPoint pt;
	::GetCursorPos(&pt);

	if (m_BarData.nEdge==ABE_FLOAT)
	{
		APPBARDATA data;
		ZeroMemory((void*) &data, sizeof(data));
		data.cbSize=sizeof(data);
		data.hWnd=PARENTWND::m_hWnd;
		data.uEdge=m_BarData.nEdge;
		CRect rect;
		PARENTWND::GetWindowRect(&rect);
		CSize size;
		size=pt-m_stMouse.pt;
		rect.OffsetRect(size);
		m_stMouse.pt=pt;
		data.rc=rect;
		SetPosition(&data,TRUE);
		return;
	}

	m_stMouse.pt=pt;

	UINT nNewEdge=GetProposedEdge();

	if (nNewEdge!=m_BarData.nEdge)
		SetEdge(nNewEdge);

	PARENTWND::OnMouseMove(nFlags, point);
}

//////////////////////////////////////////////
//OnMove(): update cursor position

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnMove(int x, int y) 
{

	CWnd::OnMove(x, y);

	CPoint pt;
	::GetCursorPos(&pt);

	m_stMouse.pt=pt;

}

//////////////////////////////////////////////
//OnNcHitTest(): handling to allow move window
//by mouse not only with caption, but all client area

template <class PARENTWND>
LRESULT COXAppBar<PARENTWND>::OnNcHitTest(CPoint point) 
{
	UINT  nHitTest;

	nHitTest = PtrToUint(CWnd::OnNcHitTest(point));
	
	if (!IsRegistered())
		return nHitTest;

	if (m_BarData.nEdge==ABE_FLOAT)
	{
		if (nHitTest==HTCLIENT || nHitTest==HTCAPTION)
			return HTCLIENT;
		else
			return nHitTest;
	}
	if ((m_BarData.nEdge == ABE_TOP) && (nHitTest == HTBOTTOM))
		return HTBOTTOM;
	if ((m_BarData.nEdge == ABE_BOTTOM) && (nHitTest == HTTOP))
		return HTTOP;
	if ((m_BarData.nEdge == ABE_LEFT) && (nHitTest == HTRIGHT))
		return HTRIGHT;
	if ((m_BarData.nEdge == ABE_RIGHT) && (nHitTest == HTLEFT))
		return HTLEFT;

	return HTCLIENT;							
}

/////////////////////////////////////////////////
//OnRButtonDown() Popup menu if cursor is in client area

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnRButtonDown(UINT nFlags, CPoint point) 
{

	CRect rct;
	PARENTWND::GetClientRect(&rct);

	if (rct.PtInRect(point))
	{
		DoPopupMenu();
		PARENTWND::OnRButtonDown(nFlags, point);
	}
}

///////////////////////////////////////////////
//OnExitSizeMoveLoop(): Update current position

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnExitSizeMoveLoop()
{
	if (!m_BarData.bHiding && !m_BarData.bHidden)
	{
		CRect rect;
		PARENTWND::GetWindowRect(&rect);
		
		switch (m_BarData.nEdge)
		{
			case ABE_LEFT:
				m_BarData.nWidth=rect.Width();
				if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
					m_BarData.nLeft=rect.Width();
				break;
			case ABE_TOP:
				m_BarData.nHeight=rect.Height();
				if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
					m_BarData.nTop=rect.Height();
				break;
			case ABE_RIGHT:
				m_BarData.nWidth=rect.Width();
				if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
					m_BarData.nRight=rect.Width();
				break;
			case ABE_BOTTOM:
				m_BarData.nHeight=rect.Height();
				if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
					m_BarData.nBottom=rect.Height();
				break;
		}
		if (!IsAutoHidden())
		{
			APPBARDATA data;
			ZeroMemory((void*) &data,sizeof(data));
			data.cbSize=sizeof(data);
			data.hWnd=PARENTWND::m_hWnd;
			data.uEdge=m_BarData.nEdge;
			data.rc=rect;
			SetPosition(&data, TRUE);
		}
	}

}


/////////////////////////////////////////////////
//OnTimer(): In autohidden state hide window, if 
//is inactive

template <class PARENTWND>
// v9.3 - update 03 - 64-bit - using OXTPARAM here - see UTB64Bit.h
void COXAppBar<PARENTWND>::OnTimer(OXTPARAM nIDEvent) 
{
	if (IsAutoHidden() && !m_BarData.bHidden && !m_BarData.bHiding)
	{
		if (::GetActiveWindow()!=PARENTWND::m_hWnd)
		{
			CPoint pt;
			::GetCursorPos(&pt);
			CRect rct;
			PARENTWND::GetWindowRect(&rct);
			rct.InflateRect(MIN_DIMENSION,MIN_DIMENSION);
			if (!rct.PtInRect(pt))
				Hide();
		}
	}
	PARENTWND::OnTimer(nIDEvent);
}

///////////////////////////////////////////
//OnWindowPosChanged() - update current position

template <class PARENTWND>
void COXAppBar<PARENTWND>::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) 
{
	PARENTWND::OnWindowPosChanged(lpwndpos);
	
	if (!IsRegistered() || m_BarData.bHiding)
		return;
	
	APPBARDATA data;

	CRect rect;
	PARENTWND::GetWindowRect(&rect);

	ZeroMemory(&data, sizeof(data));
	data.cbSize = sizeof(APPBARDATA);
	data.rc=rect;
	data.uEdge = m_BarData.nEdge;
	data.hWnd=PARENTWND::m_hWnd;

	SHAppBarMessage (ABM_WINDOWPOSCHANGED, &data);

	switch(m_BarData.nEdge)
	{
	case ABE_FLOAT:
		{
			m_rctFloat=rect;
			UINT nNewEdge=GetProposedEdge();
			if (nNewEdge!=m_BarData.nEdge)
				SetEdge(nNewEdge);
		}
		break;
	case ABE_LEFT:
		if (!m_BarData.bHidden)
		{
		m_BarData.nWidth=rect.Width();
		if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
			m_BarData.nLeft=m_BarData.nWidth;
		}
		break;
	case ABE_TOP:
		if (!m_BarData.bHidden)
		{
			m_BarData.nHeight=rect.Height();
		if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
			m_BarData.nTop=m_BarData.nHeight;
		}
		break;
	case ABE_RIGHT:
		if (!m_BarData.bHidden)
		{
			m_BarData.nWidth=rect.Width();
		if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
			m_BarData.nRight=m_BarData.nWidth;
		}
		break;
	case ABE_BOTTOM:
		if (!m_BarData.bHidden)
		{
			m_BarData.nHeight=rect.Height();
		if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
			m_BarData.nBottom=m_BarData.nHeight;
		}
		break;
	}

	
}

////////////////////////////////////////
//IsAutoHidden(): defines is bar in autohidden state
//There is a difference between autohidden state and
//variable m_BarData.bAutoHideDesired - the variable
//is always TRUE if last call was SetAutoHide(TRUE)
//and FALSE if last call was SetAutoHide(FALSE) regardless
//of actual autohidden state that returns IsAutoHidden().
//Every time the docked edge is changed the program will try
//to make the bar autohidden if the variable is TRUE 

template <class PARENTWND>
BOOL COXAppBar<PARENTWND>::IsAutoHidden() 
{
	ASSERT(::IsWindow(PARENTWND::m_hWnd));

	if (!IsRegistered())
		return FALSE;

	APPBARDATA data;

	ZeroMemory(&data, sizeof(data));
	data.cbSize = sizeof(APPBARDATA);
	data.uEdge = m_BarData.nEdge;
	data.hWnd=PARENTWND::m_hWnd;

	HWND hWnd=(HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAR, &data);
	
	return (BOOL) (hWnd==data.hWnd); 
}


/////////////////////////////////////////////
//QueryPosition(): query position for appbar

template <class PARENTWND>
void COXAppBar<PARENTWND>::QueryPosition(RECT* pRect)
{
	ASSERT(::IsWindow(PARENTWND::m_hWnd));

	APPBARDATA data;

	ZeroMemory(&data, sizeof(data));
	data.cbSize = sizeof(APPBARDATA);
	data.rc=*pRect;
	data.uEdge = m_BarData.nEdge;
	data.hWnd=PARENTWND::m_hWnd;

	SHAppBarMessage(ABM_QUERYPOS, &data);

	switch (data.uEdge)
	{
		case ABE_LEFT:
			data.rc.right = data.rc.left+pRect->right-pRect->left;
			break;

		case ABE_RIGHT:
			data.rc.left = data.rc.right-pRect->right+pRect->left;
			break;

		case ABE_TOP:
			data.rc.bottom = data.rc.top + pRect->bottom-pRect->top;
			break;

		case ABE_BOTTOM:
			data.rc.top = data.rc.bottom - pRect->bottom+pRect->top;
			break;
	}
	*pRect = data.rc;	
}

/////////////////////////////////////////////////////
//SetPosition(): sets the appbar in specified position 
//regarding with result of query position

template <class PARENTWND>
void COXAppBar<PARENTWND>::SetPosition(APPBARDATA* pBarData,	BOOL bMove)
{

	ASSERT(::IsWindow(PARENTWND::m_hWnd));

	APPBARDATA data;

	ZeroMemory(&data, sizeof(data));
	data.cbSize = sizeof(APPBARDATA);
	data.rc=pBarData->rc;
	data.uEdge = pBarData->uEdge;
	data.hWnd=PARENTWND::m_hWnd;
	
	QueryPosition(&data.rc);

	if (data.uEdge !=ABE_FLOAT && data.uEdge!=ABE_UNKNOWN)
		SHAppBarMessage(ABM_SETPOS, &data);
	if (bMove)
	{
    	
		PARENTWND::MoveWindow(pBarData->rc.left, pBarData->rc.top, 
			   	   pBarData->rc.right - pBarData->rc.left,
			   	   pBarData->rc.bottom - pBarData->rc.top, TRUE);
	}


}

//////////////////////////////////////////////////
//PosChanged(): handler for notification message -
//windows tell us move the appbar

template <class PARENTWND>
void COXAppBar<PARENTWND>::PosChanged()
{
	SetEdge(m_BarData.nEdge);
}

//////////////////////////////////////////////////
//AppBarCallback(): handler for notification messages

template <class PARENTWND>
void COXAppBar<PARENTWND>::AppBarCallback (UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 	static HWND hwndZOrder = NULL;
    
	APPBARDATA data;
	ZeroMemory((void*) &data,sizeof(data));
	data.cbSize=sizeof(data);
	data.hWnd=PARENTWND::m_hWnd;

    
    switch (wParam) 
    {
        case ABN_STATECHANGE:
	        break;

	    case ABN_FULLSCREENAPP:
	        if (lParam) 
	        {
                //Move the appbar to the bottom of the z-order.  

				hwndZOrder = GetWindow (m_data.hWnd, GW_HWNDPREV);
				SetWindowPos(data.hWnd, HWND_BOTTOM, 0, 0, 0, 0, 
	            	 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);            
	        } 
	        else 
	        {
                //Restore the Z-order			   
                SetWindowPos(m_data.hWnd, IsAlwaysOnTop() ? HWND_TOPMOST : hwndZOrder,
	                         0, 0, 0, 0, 
	                         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
				
				hwndZOrder = NULL;
	        }
			break;
        
    	case ABN_POSCHANGED:
        	PosChanged ();
        	break;
    }
}

////////////////////////////////////////////////////////////
//Register(): this function registers/unregisters the appbar. 

template <class PARENTWND>
BOOL COXAppBar<PARENTWND>::Register(BOOL bRegister)
{

	ASSERT(PARENTWND::m_hWnd);
	
	APPBARDATA data;
	ZeroMemory((void*) &data, sizeof(data));
	data.cbSize=sizeof(APPBARDATA);
	data.hWnd=PARENTWND::m_hWnd;

	if (bRegister)
	{
		data.uCallbackMessage = OX_APPBAR;
		m_BarData.bRegistered = PtrToInt(SHAppBarMessage (ABM_NEW, &data));
		if (m_BarData.bRegistered)
		{
			m_bFloating=FALSE;
			if (m_BarData.nEdge==ABE_UNKNOWN )
				SetEdge(ABE_FLOAT);
			else
			{
				int nEdge=m_BarData.nEdge;
				m_BarData.nEdge=ABE_UNKNOWN;
				SetEdge(nEdge);
			}
		}
		return m_BarData.bRegistered;
	}
	else
	{
		SaveState();
		m_BarData.bRegistered = !SHAppBarMessage(ABM_REMOVE, &data);
		m_bFloating=FALSE;
		return !m_BarData.bRegistered;
	}
}

///////////////////////////////////////////////////
//SetAutoHide(): sets or remove autohide mode

template <class PARENTWND>
BOOL COXAppBar<PARENTWND>::SetAutoHide(BOOL bHide)
{

	ASSERT(PARENTWND::m_hWnd);
	
	CRect rect;
	APPBARDATA data;
	ZeroMemory((void*) &data, sizeof(data));
	data.cbSize=sizeof(APPBARDATA);
	data.hWnd=PARENTWND::m_hWnd;
	data.uEdge = m_BarData.nEdge;
	
	m_BarData.bAutoHideDesired=bHide;

	HWND hwndAutoHide = (HWND) SHAppBarMessage(ABM_GETAUTOHIDEBAR, &data);
	
	if (bHide)
    {
		if (hwndAutoHide != NULL)
		{
			TRACE0("The system has autohidden appbar on this edge so far\r\n");
			return FALSE;
		}

		data.lParam = TRUE;			
		if (!SHAppBarMessage(ABM_SETAUTOHIDEBAR, &data))
		{
			TRACE0("Error to set autohidden bar\r\n");
			return FALSE;
		}
		if (m_BarData.nEdge!=ABE_FLOAT)
		{
			PARENTWND::GetWindowRect(&rect);
			GetEndRect(rect);
			data.rc=rect;
			SetPosition(&data, FALSE);
		}
	}
	else
    {
		if (hwndAutoHide != data.hWnd)
		{
			TRACE0 ("The window is not hidden\r\n");
			return FALSE;
		}

		data.lParam = FALSE;			

		if (!SHAppBarMessage(ABM_SETAUTOHIDEBAR, &data))
		{
			TRACE0 ("Error to unhide appbar\r\n");
			return FALSE;
		}
		PARENTWND::GetWindowRect(&rect);
		switch (m_BarData.nEdge)
		{
		case ABE_LEFT:
			rect.right=rect.left+m_BarData.nWidth;
			break;
		case ABE_TOP:
			rect.bottom=rect.top+m_BarData.nHeight;
			break;
		case ABE_RIGHT:
			rect.left=rect.right-m_BarData.nWidth;
			break;
		case ABE_BOTTOM:
			rect.top=rect.bottom-m_BarData.nHeight;
			break;
		default:
			return TRUE;
		}
		data.rc=rect;
		SetPosition(&data,TRUE);
    }
	return TRUE;
}

///////////////////////////////////////////////
//SetEdge(): call this function to set desired edge

template <class PARENTWND>
BOOL COXAppBar<PARENTWND>::SetEdge(UINT nEdge)
{
	//only for changing edge
	if (nEdge==m_BarData.nEdge || !IsRegistered())
		return FALSE;

	switch (nEdge)
	{
	case ABE_UNKNOWN:
		ASSERT(FALSE);
		return FALSE;
	case ABE_FLOAT:
		if (!(m_BarData.dwStyle & OX_APPBARS_FLOAT))
			return FALSE;
		break;
	case ABE_TOP:
		if (!(m_BarData.dwStyle & OX_APPBARS_TOP))
			return FALSE;
		m_BarData.nDockEdge=ABE_TOP;
		break;
	case ABE_LEFT:
		if (!(m_BarData.dwStyle & OX_APPBARS_LEFT))
			return FALSE;
		m_BarData.nDockEdge=ABE_LEFT;
		break;
	case ABE_RIGHT:
		if (!(m_BarData.dwStyle & OX_APPBARS_RIGHT))
			return FALSE;
		m_BarData.nDockEdge=ABE_RIGHT;
		break;
	case ABE_BOTTOM:
		if (!(m_BarData.dwStyle & OX_APPBARS_BOTTOM))
			return FALSE;
		m_BarData.nDockEdge=ABE_BOTTOM;
		break;
	}

	if (IsAutoHidden())
	{
		SetAutoHide(FALSE);
		m_BarData.bAutoHideDesired=TRUE;
	}
	
	m_BarData.nEdge=nEdge;

	CRect rect;

	ASSERT(PARENTWND::m_hWnd);
	PARENTWND::GetWindowRect(&rect);

	APPBARDATA data;
	ZeroMemory((void*) &data, sizeof(data));
	data.cbSize=sizeof(APPBARDATA);
	data.hWnd=PARENTWND::m_hWnd;
	data.uEdge=m_BarData.nEdge;
	

	if ( nEdge==ABE_FLOAT)
		Float(&data);
	else 
		UnFloat(&data);


	GetProposedRect(rect);
	data.rc=rect;

	if (nEdge!=ABE_FLOAT)
	{
		SetPosition(&data, TRUE);
		if (m_BarData.bAutoHideDesired)
			SetAutoHide(TRUE);
	}
	else
		PARENTWND::MoveWindow(rect.left, rect.top, 
	   	   rect.right - rect.left,
	   	   rect.bottom - rect.top, TRUE);

	OnSetEdge(m_BarData.nEdge);
	return TRUE;
}

//////////////////////////////////////////////////////
//SetAlwaysOnTop(): sets or remove always_on_top style

template <class PARENTWND>
void COXAppBar<PARENTWND>::SetAlwaysOnTop(BOOL bOnTop)
{

	::SetWindowPos(PARENTWND::m_hWnd, (bOnTop) ? HWND_TOPMOST : HWND_NOTOPMOST,
	             0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

	m_BarData.bOnTop = bOnTop;
}

///////////////////////////////////////////////////
//Hide(): hides the window in autohidden state

template <class PARENTWND>
void COXAppBar<PARENTWND>::Hide()
{
	if (!IsAutoHidden())
		return;

	CRect rect;
	PARENTWND::GetWindowRect(&rect);
	GetEndRect(rect);

	m_nOffset=-1;
	m_BarData.nEdge=m_BarData.nEdge;
	m_BarData.bHiding=TRUE;
	SlideWindow();
	m_BarData.bHidden=TRUE;
	m_BarData.bHiding=FALSE;
	DWORD dwStyle=PARENTWND::GetStyle();
	if (dwStyle  & WS_THICKFRAME)
	{
		m_bSizeable=TRUE;
		PARENTWND::ModifyStyle(WS_THICKFRAME,0);
	}
	if (IsAutoHidden())
	{
		APPBARDATA data;
		ZeroMemory((void*) &data, sizeof(data));
		data.cbSize=sizeof(data);
		data.hWnd=PARENTWND::m_hWnd;
		data.rc=rect;
		data.uEdge=m_BarData.nEdge;
		SetPosition(&data, TRUE);
	}
}

////////////////////////////////////
//UnHide(): unhidethe window in autohidden state

template <class PARENTWND>
void COXAppBar<PARENTWND>::UnHide()
{

	if (!IsAutoHidden())
		return;
	m_nOffset=1;
	m_BarData.nEdge=m_BarData.nEdge;
	m_BarData.bHiding=TRUE;
	SlideWindow();
    m_BarData.bHiding = FALSE;
	m_BarData.bHidden=FALSE;
	if (m_bSizeable)
		PARENTWND::ModifyStyle(0,WS_THICKFRAME);

}

///////////////////////////////////////////////////////
//LoadState(): loads last saved state from the registry

template <class PARENTWND>
BOOL COXAppBar<PARENTWND>::LoadState()
{

	COXRegistryValFile regfile(
		HKEY_CURRENT_USER, AfxGetAppName(), _T("AppBar"));
	CArchive ar(&regfile, CArchive::load);

	BOOL bRet=FALSE;

	
	if (regfile.GetLength()>0)
	{
		int nVersion;
		ar >> nVersion;
		if (nVersion!=OX_APPBAR_VERSION)
			return FALSE;

		BOOL bRegistered;
		ar >> bRegistered;

		if (bRegistered)
		{
			if(!IsRegistered())
				Register(TRUE);
		}
		else
		{
			if (IsRegistered())
				Register(FALSE);
		}

		BOOL bOnTop;
		BOOL bAutoHide;
		
		ar >> bOnTop;
		ar >> bAutoHide;
		ar >> m_BarData.nWidth;
		ar >> m_BarData.nHeight;
		ar >> m_BarData.nLeft;
		ar >> m_BarData.nTop;
		ar >> m_BarData.nRight;
		ar >> m_BarData.nBottom;

		UINT nEdge;
		//UINT nDockEdge;

		ar >> nEdge;//m_BarData.nEdge;
		ar >> m_BarData.nDockEdge;
		ar >> m_BarData.dwStyle;
		ar >> m_nSlidingTime;
		ar >> m_nHiddenWidth;
		ar >> m_nTimerInterval;

		ar >> m_nToDock;
		ar >> m_nToFloat;
		ar >> m_rctFloat.left;
		ar >> m_rctFloat.top;
		ar >> m_rctFloat.right;
		ar >> m_rctFloat.bottom;

		if (IsRegistered())
		{
			SetEdge(nEdge);
			SetAutoHide(bAutoHide);
			SetAlwaysOnTop(bOnTop);
		}
		bRet=TRUE;
	}

	ar.Close();
	return bRet;
}

///////////////////////////////////////////////////
//SaveState(): save the state to the registry

template <class PARENTWND>
void COXAppBar<PARENTWND>::SaveState()
{
	COXRegistryValFile regfile(
		HKEY_CURRENT_USER, AfxGetAppName(), _T("AppBar"));
	CArchive ar(&regfile, CArchive::store);
	ar << OX_APPBAR_VERSION;
	ar << m_BarData.bRegistered;
	ar << m_BarData.bOnTop;
	ar << m_BarData.bAutoHideDesired;
	ar << m_BarData.nWidth;
	ar << m_BarData.nHeight;
	ar << m_BarData.nLeft;
	ar << m_BarData.nTop;
	ar << m_BarData.nRight;
	ar << m_BarData.nBottom;
	ar << m_BarData.nEdge;
	ar << m_BarData.nDockEdge;
	ar << m_BarData.dwStyle;
	ar << m_nSlidingTime;
	ar << m_nHiddenWidth;
	ar << m_nTimerInterval;
	ar << m_nToDock;
	ar << m_nToFloat;
	ar << m_rctFloat.left;
	ar << m_rctFloat.top;
	ar << m_rctFloat.right;
	ar << m_rctFloat.bottom;

	ar.Close();
}

////////////////////////////////////////////////////
//SlideWindow(): slides the window in autohidden state 
//hiding/unhiding

template <class PARENTWND>
void COXAppBar<PARENTWND>::SlideWindow()
{
	CRect rctCurrent;
	PARENTWND::GetWindowRect(&rctCurrent);
	CRect rctEnd=rctCurrent;

	GetEndRect(rctEnd);


	DWORD dwCount=::GetTickCount();

	while(CanContinue(rctCurrent,rctEnd))
	{
		if ((dwCount-::GetTickCount())>m_nSlidingTime)
		{
			dwCount=::GetTickCount();
			switch (m_BarData.nEdge)
			{
			case ABE_TOP:
				rctCurrent.bottom+=m_nOffset;
				break;
			case ABE_BOTTOM:
				rctCurrent.top-=m_nOffset;	
				break;
			case ABE_LEFT:
				rctCurrent.right+=m_nOffset;
				break;
			case ABE_RIGHT:
				rctCurrent.left-=m_nOffset;
				break;
			}
			PARENTWND::MoveWindow(&rctCurrent);
		}
	}

	PARENTWND::MoveWindow(&rctEnd);
	
}

////////////////////////////////////////////////////
//CanContinue(): helper function for SlideWindow()
//returns FALSE when appbar rect reached final position 

template <class PARENTWND>
BOOL COXAppBar<PARENTWND>::CanContinue(CRect& rctCurrent, CRect& rctEnd)
{
	switch (m_BarData.nEdge)
	{
	case ABE_TOP:
	case ABE_BOTTOM:
		if (m_BarData.bHidden)
			return (BOOL) (rctCurrent.Height()<rctEnd.Height());
		else
			return (BOOL) (rctCurrent.Height()>rctEnd.Height());
	case ABE_LEFT:
	case ABE_RIGHT:
		if (m_BarData.bHidden)
			return (BOOL) (rctCurrent.Width()<rctEnd.Width());
		else
			return (BOOL) (rctCurrent.Width()>rctEnd.Width());
	default:
		ASSERT(FALSE);
	}
	return FALSE;
}

////////////////////////////////////////////////////
//GetEndRect(): helper function returns rectangle
//appbar should reach while hiding/unhiding depends
//on docking edge

template <class PARENTWND>
void COXAppBar<PARENTWND>::GetEndRect(CRect& rect)
{
	switch (m_BarData.nEdge)
	{
	case ABE_TOP:
		if (m_BarData.bHidden)
			rect.bottom=rect.top+m_BarData.nHeight;
		else
			rect.bottom=rect.top+GetHiddenWidth();
	break;
	case ABE_BOTTOM:
		if (m_BarData.bHidden)
			rect.top=rect.bottom-m_BarData.nHeight;
		else
			rect.top=rect.bottom-GetHiddenWidth();
	break;
	case ABE_LEFT:
		if (m_BarData.bHidden)
			rect.right=rect.left+m_BarData.nWidth;
		else
			rect.right=rect.left+GetHiddenWidth();
	break;
	case ABE_RIGHT:
		if (m_BarData.bHidden)
			rect.left=rect.right-m_BarData.nWidth;
		else
			rect.left=rect.right-GetHiddenWidth();
		
	break;
	}
}

//////////////////////////////////////////////////////
//GetProposedRect(): returns proposed rect for the edge
//the appbar will switch to 

template <class PARENTWND>
void COXAppBar<PARENTWND>::GetProposedRect(CRect& rect)
{
	rect.left=0;
	rect.top=0;
	rect.right=::GetSystemMetrics(SM_CXSCREEN);
	rect.bottom=::GetSystemMetrics(SM_CYSCREEN);

	if (m_BarData.dwStyle & OX_APPBARS_DIFFERENT_DIMS)
	{
		switch (m_BarData.nEdge)
		{
		case ABE_UNKNOWN:
			ASSERT(FALSE);
			break;
		case ABE_FLOAT:
			{
				CPoint pt;
				::GetCursorPos(&pt);
				rect.left=pt.x-(m_rctFloat.right-m_rctFloat.left)/2;
				rect.right=rect.left+m_rctFloat.right-m_rctFloat.left;
				rect.top=pt.y-DIM_CAPTION;
				rect.bottom=rect.top+m_rctFloat.bottom-m_rctFloat.top;
			}
			break;
		case ABE_LEFT:
			rect.right=m_BarData.nLeft;
			break;
		case ABE_TOP:
			rect.bottom=m_BarData.nTop;
			break;
		case ABE_RIGHT:
			rect.left=rect.right-m_BarData.nRight;
			break;
		case ABE_BOTTOM:
			rect.top=rect.bottom-m_BarData.nBottom;
			break;
		}
		return;
	}

	switch (m_BarData.nEdge)
	{
	case ABE_UNKNOWN:
		ASSERT(FALSE);
		break;
	case ABE_FLOAT:
		PARENTWND::GetWindowRect(&rect);
		break;
	case ABE_LEFT:
		rect.right=m_BarData.nWidth;
		break;
	case ABE_TOP:
		rect.bottom=m_BarData.nHeight;
		break;
	case ABE_RIGHT:
		rect.left=rect.right-m_BarData.nWidth;
		break;
	case ABE_BOTTOM:
		rect.top=rect.bottom-m_BarData.nHeight;
		break;
	}
}

////////////////////////////////////////////////////
//GetProposedEdge(): propose the edge depends on current
//placement of the appbar and position of the mouse,
//while button pressed

template <class PARENTWND>
UINT COXAppBar<PARENTWND>::GetProposedEdge()
{

	POINT pt;
	CRect rectScreen;
	rectScreen.top=0;
	rectScreen.left=0;
	rectScreen.right = GetSystemMetrics(SM_CXSCREEN);
	rectScreen.bottom = GetSystemMetrics(SM_CYSCREEN);

	VERIFY(GetCursorPos(&pt));
	CRect  rectCurrent;
	PARENTWND::GetWindowRect(&rectCurrent);

	UINT nNewEdge=m_BarData.nEdge;
	UINT nLeftRight;
	UINT nTopBottom;
	UINT nDiffr=rectScreen.right;

	switch (m_BarData.nEdge)
	{
	case ABE_UNKNOWN:
		return ABE_UNKNOWN;
	case ABE_TOP:
	case ABE_LEFT:
	case ABE_RIGHT:
	case ABE_BOTTOM:
		if (!(m_BarData.dwStyle & OX_APPBARS_FLOAT))
		{
			if (m_BarData.dwStyle & (OX_APPBARS_LEFT | OX_APPBARS_RIGHT)) 
				nLeftRight=(pt.x>(rectScreen.right/2))?ABE_RIGHT:ABE_LEFT;
			else
				if (m_BarData.dwStyle & OX_APPBARS_LEFT)
					nLeftRight=ABE_LEFT;
				else
					if (m_BarData.dwStyle & OX_APPBARS_RIGHT)
						nLeftRight=ABE_RIGHT;
					else
						nLeftRight=ABE_UNKNOWN;
			if (m_BarData.dwStyle & (OX_APPBARS_TOP | OX_APPBARS_RIGHT))
				nTopBottom=(pt.y>(rectScreen.bottom/2))?ABE_BOTTOM:ABE_TOP;
			else
				if (m_BarData.dwStyle & OX_APPBARS_TOP)
					nTopBottom=ABE_TOP;
				else
					if (m_BarData.dwStyle & OX_APPBARS_BOTTOM)
						nTopBottom=ABE_BOTTOM;
					else
						nTopBottom=ABE_UNKNOWN;
			switch( nLeftRight)
			{
			case ABE_UNKNOWN:
				if (nTopBottom==ABE_UNKNOWN)
				{
					ASSERT(FALSE);
					return m_BarData.nEdge;
				}
				return nTopBottom;
			case ABE_LEFT:
				if (nTopBottom==ABE_UNKNOWN)
					return ABE_LEFT;
				if (nTopBottom==ABE_TOP)
				{
					return (pt.x*rectScreen.Height()<pt.y*rectScreen.Width())?ABE_LEFT:ABE_TOP;
				}
				else
					return (pt.x*rectScreen.Height()<(rectScreen.Height()-pt.y)*rectScreen.Width())?ABE_LEFT:ABE_BOTTOM;
			case ABE_RIGHT:
				if (nTopBottom==ABE_UNKNOWN)
					return ABE_RIGHT;
				if (nTopBottom==ABE_TOP)
				{
					return ((rectScreen.Width()-pt.x)*rectScreen.Height()<pt.y*rectScreen.Width())?ABE_RIGHT:ABE_TOP;
				}
				else
					return ((rectScreen.Width()-pt.x)*rectScreen.Height()<(rectScreen.Height()-pt.y)*rectScreen.Width())?ABE_RIGHT:ABE_BOTTOM;
			}

		}
		rectCurrent.InflateRect(m_nToFloat,m_nToFloat);
		if (rectCurrent.PtInRect(pt))
			return m_BarData.nEdge;
		nNewEdge=ABE_FLOAT;
		//no break here!
	case ABE_FLOAT:
		if (pt.x<(int) m_nToDock && (m_BarData.dwStyle & OX_APPBARS_LEFT))
		{
			nNewEdge=ABE_LEFT;
			nDiffr=pt.x;
		}
		if (pt.y<(int) m_nToDock && ((UINT) abs(pt.y)<nDiffr) && (m_BarData.dwStyle & OX_APPBARS_TOP))
		{
			nNewEdge=ABE_TOP;
			nDiffr=pt.y;
		}
		if ((UINT) abs(rectScreen.right-pt.x)<nDiffr && rectScreen.right-pt.x<(int) m_nToDock &&
			(m_BarData.dwStyle & OX_APPBARS_RIGHT))
		{
			nNewEdge=ABE_RIGHT;
			nDiffr=rectScreen.right-pt.x;
		}
		if ((UINT) abs(rectScreen.bottom-pt.y)<nDiffr && rectScreen.bottom-pt.y<(int) m_nToDock &&
			(m_BarData.dwStyle & OX_APPBARS_BOTTOM))
		{
			nNewEdge=ABE_BOTTOM;
		}
		return nNewEdge;

	}

	return m_BarData.nEdge;
}

///////////////////////////////////////////////////
//Float() unregisters appbar temporary for floating

template <class PARENTWND>
void COXAppBar<PARENTWND>::Float(APPBARDATA* pData)
{
	SHAppBarMessage(ABM_REMOVE, pData);
	m_bFloating=TRUE;
}

//////////////////////////////////////////////////
//UnFloat() registers the appbar after floating

template <class PARENTWND>
void COXAppBar<PARENTWND>::UnFloat(APPBARDATA* pData)
{
	ASSERT(IsRegistered());

	if (m_bFloating)
		m_bFloating=!SHAppBarMessage(ABM_NEW,pData);

}


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

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(_OXAPPBAR_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, 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