// ========================================================================================
// 							Class Implementation : 
//		COXFrameWndSizeDock & COXMDIFrameWndSizeDock & COXMDIChildWndSizeDock
// ========================================================================================

// Source file : OXFrameWndDock.cpp

// 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.
// Some portions Copyright (C)1994-5	Micro Focus Inc, 2465 East Bayshore Rd, Palo Alto, CA 94303.
                          
// //////////////////////////////////////////////////////////////////////////

#include "stdafx.h"				// standard MFC include
#include "OXFrameWndDock.h"		// this class specification

#include "OXSzMiniDockFrmWnd.h"	// used class specification
#include "OXSizeDockBar.h"		// used class specification
#include "OXMDIFloatWnd.h"		// used class specification

#include "UTBStrOp.h"
#include "UTB64Bit.h"

#ifndef __OXMFCIMPL_H__
#if _MFC_VER >= 0x0700
#if _MFC_VER >= 1400
#include <afxtempl.h>
#endif
#include <..\src\mfc\afximpl.h>
#else
#include <..\src\afximpl.h>
#endif
#define __OXMFCIMPL_H__
#endif

#ifndef __OX_OLEIMPL2_H__
#ifdef MAP_LOGHIM_TO_PIX
#undef MAP_LOGHIM_TO_PIX
#endif
#ifdef MAP_PIX_TO_LOGHIM
#undef MAP_PIX_TO_LOGHIM
#endif
#if _MFC_VER < 0x0700
	#include <..\src\oleimpl2.h>
#else
	#include <..\src\mfc\oleimpl2.h>
#endif
#define __OX_OLEIMPL2_H__
#endif

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif


#define REG_VERSION    		_T("Version")
#define REG_VERSION_NO		2		// current version of docking state

#ifdef _DEBUG
//#define _DEBUG_WNDPOS			// provide debug info on the window positioning algorithm
#endif

// dwMRCDockBarMap - table mapping standard ID's to styles
// Exists in MFC30.DLL, but not exported, so have to code it here
// renamed it 'cos there seems to be a difference between MFC4.0 and 4.1
static const DWORD dwMRCDockBarMap[4][2] =
	{
        { AFX_IDW_DOCKBAR_TOP,      CBRS_TOP    },
        { AFX_IDW_DOCKBAR_BOTTOM,   CBRS_BOTTOM },
        { AFX_IDW_DOCKBAR_LEFT,     CBRS_LEFT   },
        { AFX_IDW_DOCKBAR_RIGHT,    CBRS_RIGHT  },
	};

/////////////////////////////////////////////////////////////////////////////
// COXFrameWndSizeDock

IMPLEMENT_DYNCREATE(COXFrameWndSizeDock, CFrameWnd)

#define new DEBUG_NEW

/////////////////////////////////////////////////////////////////////////////
// Definition of static members

// Data members -------------------------------------------------------------
// protected:

// private:
	
// Member functions ---------------------------------------------------------
// public:

COXFrameWndSizeDock::COXFrameWndSizeDock()
{
}

COXFrameWndSizeDock::~COXFrameWndSizeDock()
{
#ifdef _DEBUG
	CObArray arrWnd;
	GetFloatingBars(arrWnd);  // debug code to see what's still around !
#endif
}


BEGIN_MESSAGE_MAP(COXFrameWndSizeDock, CFrameWnd)
	//{{AFX_MSG_MAP(COXFrameWndSizeDock)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_QUERYSNAPPING, OnQuerySnapping)
END_MESSAGE_MAP()


void COXFrameWndSizeDock::OnDestroy()
{
	if(GetTopLevelFrame()==this || GetTopLevelFrame()==NULL)
	{
		// tidy up any outstanding control bars...
		COXSizeControlBar::TidyUp(this);		
	}

	CFrameWnd::OnDestroy();
}

LRESULT COXFrameWndSizeDock::OnQuerySnapping(WPARAM, LPARAM)
{
	return m_bEnableSnapping;
}

// dock bars will be created in the order specified by dwMRCDockBarMap
// this also controls which gets priority during layout
// this order can be changed by calling EnableDocking repetitively
// with the exact order of priority

// This is over-ridden primarily because we need to insert our own CDockBar class
// to handle the recalc layout, and this is the place they are created.
void COXFrameWndSizeDock::EnableDocking(DWORD dwDockStyle)
	{
	// must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
    ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
	
    m_pFloatingFrameClass = RUNTIME_CLASS(COXSizableMiniDockFrameWnd); // protected member
    for (int i = 0; i < 4; i++)
		{
		if (dwMRCDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)          // protected
			{
			CDockBar* pDock = (CDockBar*)GetControlBar(dwMRCDockBarMap[i][0]);
            if (pDock == NULL)
				{
				pDock = new COXSizeDockBar;
				if (!pDock->Create(this,
					WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE |
					dwMRCDockBarMap[i][1], dwMRCDockBarMap[i][0]))
                    {
					AfxThrowResourceException();
                    }
                }
			}
		}
	}

// although this is not a virtual function in MFC 4.0 and we can't guarantee the override
void COXFrameWndSizeDock::FloatControlBar(CControlBar* pBar, CPoint point, DWORD dwStyle)
	{
	CFrameWnd::FloatControlBar(pBar, point, dwStyle);
	pBar->SendMessage(WM_OX_APP_AFTERFLOAT_MSG);		// force update of float style
	}

void COXFrameWndSizeDock::ShowControlBar(CControlBar* pBar, BOOL bShow, BOOL bDelay)
	{
	CFrameWnd::ShowControlBar(pBar, bShow, bDelay);
	}


// Tiles the bars docked in the specified orientation
void COXFrameWndSizeDock::TileDockedBars(DWORD dwDockStyle)
	{
	for (int i = 0; i < 4; i++)
		{
		if (dwMRCDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)  //protected
			{
			COXSizeDockBar* pDock = (COXSizeDockBar*)GetControlBar(dwMRCDockBarMap[i][0]);
            // ASSERT(pDock == NULL || pDock->IsKindOf(RUNTIME_CLASS(COXSizeDockBar)));
            if (pDock != NULL && (pDock->m_dwStyle && dwDockStyle == dwDockStyle))
				{
				pDock->TileDockedBars();
				}
			}
		}
	}


void COXFrameWndSizeDock::ArrangeFloatingBars(DWORD dwOrient)
	{
	CObArray arrWnd;
	GetFloatingBars(arrWnd);
	ArrangeWindows(arrWnd, dwOrient);
	}

void COXMDIFrameWndSizeDock::ArrangeFloatingBars(DWORD dwOrient)
	{
	CObArray arrWnd;
	GetFloatingBars(arrWnd);
	ASSERT (this->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd)));
	ASSERT(m_hWndMDIClient != NULL);
	// Use the MDI Client window - not the normal client area
	CWnd* pMDIClientWnd = CWnd::FromHandle(m_hWndMDIClient);
	ArrangeWindowsInWindow(pMDIClientWnd, arrWnd, dwOrient);
	
	// clear all the MOVED flags for sizeable windows...
	for (int i = PtrToInt(arrWnd.GetUpperBound()); i >= 0; i--)
		{
        COXSizableMiniDockFrameWnd* pFloatFrame = (COXSizableMiniDockFrameWnd*)arrWnd[i]; 
        
		ASSERT(pFloatFrame->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)));
		pFloatFrame->ModifyStyle(CBRS_MOVED_BY_USER, 0);
		}
	}


void COXMDIFrameWndSizeDock::ArrangeWindows(CObArray& arrWnd, DWORD dwOrient)
	{
	ASSERT (this->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd)));
	ASSERT(m_hWndMDIClient != NULL);
	// Use the MDI Client window - not the normal client area
	CWnd* pMDIClientWnd = CWnd::FromHandle(m_hWndMDIClient);
	ArrangeWindowsInWindow (pMDIClientWnd, arrWnd, dwOrient);
	}



void COXFrameWndSizeDock::ArrangeWindows(CObArray& arrWnd, DWORD dwOrient)
	{
	ArrangeWindowsInWindow (this, arrWnd, dwOrient);
	}


// Appends the floating bars, visible bars to an array
void COXFrameWndSizeDock::GetFloatingBars(CObArray& arrWnd)
	{
	CPtrList& listControlBars = m_listControlBars;
	
	POSITION pos = listControlBars.GetHeadPosition();
	while (pos != NULL)
		{
		CControlBar* pBar = (CControlBar*)listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);
		if (!pBar->IsDockBar() && pBar->IsFloating() && pBar->IsVisible()) 	// not a dockbar and floating....
			{
			ASSERT(pBar->m_pDockBar != NULL);
			CWnd* pFloatFrame = ((CWnd*)pBar->m_pDockBar)->GetParent(); 
			ASSERT(pBar != NULL);
			arrWnd.Add(pFloatFrame);
			}
		}
	}


// Destroys the dynamic bars in an application
void COXFrameWndSizeDock::DestroyDynamicBars()
	{
	CPtrList& listControlBars = m_listControlBars;
	
	CObArray arrBars;
	COXSizeControlBar* pBar;
	
	// pass through the list and build an array of bars to destroy
	POSITION pos = listControlBars.GetHeadPosition();
	while (pos != NULL)
		{
		pBar = (COXSizeControlBar*)listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);
		if (pBar->IsKindOf(RUNTIME_CLASS(COXSizeControlBar)) &&
			(pBar->m_Style & SZBARF_AUTOTIDY) == SZBARF_AUTOTIDY)
			arrBars.Add(pBar);
		}
	
	// now destroy these bars...
	for (int i = PtrToInt(arrBars.GetUpperBound()); i >= 0; i--)
		{
		pBar = (COXSizeControlBar*)arrBars[i];
		pBar->DestroyWindow();
		}
	}


struct BarSizeSaveInfo 
	{
    CSize   FloatSize;          // floating size
	CSize	HorzDockSize;       // size when docked horizontally
    CSize   VertDockSize;       // size when docked vertically
	BOOL	bMDIFloating;		// floating in an MDI child window
	};


void COXFrameWndSizeDock::SaveSizeBarState(LPCTSTR pszProfileName)
	{
	DestroyDynamicBars();			// remove bars allocated dynamically
	// - we reload these at present
	
	CFrameWnd::SaveBarState(pszProfileName);	// save the raw states
#ifdef _VERBOSE_TRACE
	TRACE0("Loading Bar Sizes\n");
#endif
	SaveBarSizes(pszProfileName, TRUE);			// save additional info
	AfxGetApp()->WriteProfileInt(pszProfileName, REG_VERSION, REG_VERSION_NO);
	}



void COXFrameWndSizeDock::LoadSizeBarState(LPCTSTR pszProfileName)
{
	// check the registry version. If it doesn't match, do nothing...
	// this prevents us trying to load registry info from a previous version, that
	// is unlikely to make sense to the code below.
	if (AfxGetApp()->GetProfileInt(pszProfileName, REG_VERSION, 0) != 
		REG_VERSION_NO)
	{
		WriteProfileString(pszProfileName, NULL, NULL);		// this deletes this key from the registry
		return;
	}

	RecalcLayout();
	InvalidateRect(NULL);
	UpdateWindow();

	////////
	// remove TBSTYLE_FLAT style out of CToolBar
	CDockState state;
	state.LoadState(pszProfileName);

	CObArray arrFlatBars;
	int nIndex=0;
	for (nIndex=0; nIndex<state.m_arrBarInfo.GetSize(); nIndex++)
	{
		CControlBarInfo* pInfo=(CControlBarInfo*)state.m_arrBarInfo[nIndex];
		ASSERT(pInfo!=NULL);
		pInfo->m_pBar=GetControlBar(pInfo->m_nBarID);
		if (pInfo->m_pBar!=NULL)
		{
			if(pInfo->m_pBar->IsKindOf(RUNTIME_CLASS(CToolBar)) && 
				pInfo->m_pBar->GetStyle()&TBSTYLE_FLAT)
			{
					arrFlatBars.Add((CObject*)pInfo->m_pBar);
					pInfo->m_pBar->ModifyStyle(TBSTYLE_FLAT,0);
			}
		}
	}
	////////

	SetDockState(state);

	////////
	// set TBSTYLE_FLAT style for CToolBar
	for (nIndex=0; nIndex<arrFlatBars.GetSize(); nIndex++)
	{
		((CToolBar*)arrFlatBars.GetAt(nIndex))->ModifyStyle(0,TBSTYLE_FLAT);
	}
	////////

#ifdef _VERBOSE_TRACE
	TRACE(_T("Loading Bar Sizes\n"));
#endif
	SaveBarSizes(pszProfileName, FALSE);		// load the sizes back

	// Clear the dockbars' hidden lists to prevent interference with recalc layout
	for (int i = 0; i < 4; i++)
	{
		COXSizeDockBar* pDock = 
			(COXSizeDockBar*)GetControlBar(dwMRCDockBarMap[i][0]);
		if (pDock != NULL)
		{
			ASSERT(pDock->IsKindOf(RUNTIME_CLASS(COXSizeDockBar)));
			pDock->m_arrHiddenBars.RemoveAll();
		}
	}

	RecalcLayout();
	if(IsWindowVisible())
	{
		InvalidateRect(NULL);
		UpdateWindow();
	}
}


// Saves all the sizeable bars info
// uses the "ID" of the bar as a key. The bar will already exist on a 
// load, so this seems safe enough
void COXFrameWndSizeDock::SaveBarSizes(LPCTSTR pszSection, BOOL bSave)
{
	struct BarSizeSaveInfo BSI;
	COXSizeControlBar* pBar;
	TCHAR szBarId[20] = _T("BarSize_");

	CPtrArray arrFloatingBars;

	POSITION pos = m_listControlBars.GetHeadPosition();
	while (pos != NULL)
	{
		pBar = (COXSizeControlBar*)m_listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);

		if (pBar->IsKindOf(RUNTIME_CLASS(COXSizeControlBar)))
		{
			UINT nID = pBar->GetDlgCtrlID();
			UTBStr::itot(nID, szBarId + 8, 12, 10);
			
			if (bSave)
			{
				BSI.VertDockSize 	= pBar->m_VertDockSize;
				BSI.HorzDockSize	= pBar->m_HorzDockSize;
				BSI.FloatSize 		= pBar->m_FloatSize;
				BSI.bMDIFloating = FALSE;
				// if floating in a MDI Float window.
				CFrameWnd* pBarFrame = pBar->GetDockingFrame();
				if (pBarFrame != NULL && 
					pBarFrame->IsKindOf(RUNTIME_CLASS(COXMDIFloatWnd)))
				{
					ASSERT(pBar->IsFloating());
					BSI.bMDIFloating = TRUE;
				}

				AfxGetApp()->WriteProfileBinary(pszSection, szBarId, 
					(LPBYTE)&BSI, sizeof BSI);
			}
			else
			{
				BarSizeSaveInfo* pBSI;
				UINT nBytesRead;
				if (AfxGetApp()->GetProfileBinary(pszSection, szBarId, 
					(LPBYTE*)&pBSI, &nBytesRead))
				{
					pBar->m_VertDockSize	= pBSI->VertDockSize;
					pBar->m_HorzDockSize	= pBSI->HorzDockSize;
					pBar->m_FloatSize 		= pBSI->FloatSize;
					
					// Now have to set the actual window size. The reason for 
					// this is that the Adjustment algorithm looks at actual 
					// window rect sizes, so it doesn't have to worry about 
					// borders etc.
					CSize NewSize = pBar->CalcFixedLayout(FALSE, 
						(pBar->m_dwStyle & CBRS_ORIENT_HORZ) != 0);
					pBar->SetWindowPos(0, 0, 0, NewSize.cx, NewSize.cy, 
						SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE);
					if (pBar->IsFloating())
					{
						if (pBSI->bMDIFloating)	// floating in an MDI frame - do the float
						{
							// have to cast to COXMDIFrameWndSizeDock - as this is a CFrameWnd function
							ASSERT(this->IsKindOf(RUNTIME_CLASS(COXMDIFrameWndSizeDock)));
							arrFloatingBars.Add(pBar);
						}
						else
						{
							CFrameWnd* pFrame = pBar->GetParentFrame();
							if (pFrame != NULL)
							{
								// Clear the dockbars' hidden lists to prevent 
								// interference with recalc layout
								for (int i = 0; i < 4; i++)
								{
									COXSizeDockBar* pDock = 
										(COXSizeDockBar*)GetControlBar(dwMRCDockBarMap[i][0]);
									if(pDock!=NULL)
									{
										ASSERT(pDock->
											IsKindOf(RUNTIME_CLASS(COXSizeDockBar)));
										pDock->m_arrHiddenBars.RemoveAll();
									}
								}
								pFrame->RecalcLayout();
							}
						}
					}

					delete [](LPBYTE)pBSI;
				}
#ifdef _VERBOSE_TRACE
				TRACE(_T("Bar ID=%d, Floating(%d,%d), HorzDocked(%d,%d), VertDocked(%d.%d)\n"),
					nID,BSI.FloatSize.cx,	BSI.FloatSize.cy,
					BSI.VertDockSize.cx, BSI.VertDockSize.cy,
					BSI.HorzDockSize.cx, BSI.HorzDockSize.cy);
#endif

			}
			
#ifdef _VERBOSE_TRACE
			CString strTitle;
			pBar->GetWindowText(strTitle);
			TRACE(_T("%s '%s' ID=%d Float(%d,%d) Horz(%d,%d) Vert(%d,%d)\n"),
				LPCTSTR(pBar->GetRuntimeClass()->m_lpszClassName),
					LPCTSTR(strTitle), nID,
						pBar->m_FloatSize.cx, pBar->m_FloatSize.cy,
							pBar->m_HorzDockSize.cx,  pBar->m_HorzDockSize.cy,
								pBar->m_VertDockSize.cx,  pBar->m_VertDockSize.cy);
#endif
		}
	}

	// Clear the dockbars' hidden lists to prevent interference with recalc layout
	for (int i = 0; i < 4; i++)
	{
		COXSizeDockBar* pDock = (COXSizeDockBar*)GetControlBar(dwMRCDockBarMap[i][0]);
		if(pDock!=NULL)
		{
			ASSERT(pDock->IsKindOf(RUNTIME_CLASS(COXSizeDockBar)));
			pDock->m_arrHiddenBars.RemoveAll();
		}
	}

	// recalc the layout - so we end up with a meaningful set of bars
	RecalcLayout();			

	if (!bSave)
	{
		for (int i = 0; i < arrFloatingBars.GetSize(); i++)
		{
			pBar = (COXSizeControlBar*)arrFloatingBars[i];
			ASSERT(pBar->m_pDockContext != NULL);
			((COXMDIFrameWndSizeDock*)this)->FloatControlBarInMDIChild(pBar, 
				pBar->m_pDockContext->m_ptMRUFloatPos, CBRS_ALIGN_TOP, 
				pBar->IsWindowVisible());
		}
	}
}


void COXFrameWndSizeDock::SetDockState(const CDockState& state)
{
	// first pass through barinfo's sets the m_pBar member correctly
	// creating floating frames if necessary
	int i = 0;
	for (i = 0; i < state.m_arrBarInfo.GetSize(); i++)
	{
		CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
		ASSERT(pInfo != NULL);
		if (pInfo->m_bFloating)
		{
			// need to create floating frame to match
			CMiniDockFrameWnd* pDockFrame = CreateFloatingFrame(
				pInfo->m_bHorz ? CBRS_ALIGN_TOP : CBRS_ALIGN_LEFT);
			ASSERT(pDockFrame != NULL);
			CRect rect(pInfo->m_pointPos, CSize(10, 10));
			pDockFrame->CalcWindowRect(&rect);
			pDockFrame->SetWindowPos(NULL, rect.left, rect.top, 0, 0,
				SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
			CDockBar* pDockBar =
				(CDockBar*)pDockFrame->GetDlgItem(AFX_IDW_DOCKBAR_FLOAT);
			ASSERT(pDockBar != NULL);
			ASSERT_KINDOF(CDockBar, pDockBar);
			pInfo->m_pBar = pDockBar;
		}
		else // regular dock bar or toolbar
		{
			pInfo->m_pBar = GetControlBar(pInfo->m_nBarID);
		}
		if(pInfo->m_pBar!=NULL)
			pInfo->m_pBar->m_nMRUWidth = pInfo->m_nMRUWidth;
	}

	// the second pass will actually dock all of the control bars and
	//  set everything correctly
	for (i = 0; i < state.m_arrBarInfo.GetSize(); i++)
	{
		CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
		ASSERT(pInfo != NULL);
		if(pInfo->m_pBar != NULL)
		{
			// dockbars are handled differently
			if (pInfo->m_pBar->IsDockBar())
			{
				((CDockBar*)(pInfo->m_pBar))->SetBarInfo(pInfo,this);
			}
			else
			{
				// don't set position when not docked
				UINT nFlags = SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER;
				if (pInfo->m_pBar->m_pDockBar == NULL)
					nFlags |= SWP_NOMOVE;

				pInfo->m_pBar->m_nMRUWidth = pInfo->m_nMRUWidth;
				pInfo->m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);

				if (pInfo->m_bDocking)
				{
					ASSERT(pInfo->m_pBar->m_pDockContext != NULL);
					// You need to call EnableDocking before calling LoadBarState

					pInfo->m_pBar->m_pDockContext->m_uMRUDockID = 
						pInfo->m_uMRUDockID;
					pInfo->m_pBar->m_pDockContext->m_rectMRUDockPos = 
						pInfo->m_rectMRUDockPos;
					pInfo->m_pBar->m_pDockContext->m_dwMRUFloatStyle = 
						pInfo->m_dwMRUFloatStyle;
					pInfo->m_pBar->m_pDockContext->m_ptMRUFloatPos = 
						pInfo->m_ptMRUFloatPos;
				}

				// move and show/hide the window
				pInfo->m_pBar->SetWindowPos(NULL, pInfo->m_pointPos.x, pInfo->m_pointPos.y, 0, 0,
					nFlags | (pInfo->m_bVisible ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
			}
		}
	}

	// last pass shows all the floating windows that were previously shown
	for (i = 0; i < state.m_arrBarInfo.GetSize(); i++)
	{
		CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
		ASSERT(pInfo != NULL);
		if(pInfo->m_pBar==NULL) //toolbar id's probably changed
		{
			TRACE(_T("Unable to restore bar state - id has probably changed\n"));
		}
		if (pInfo->m_pBar!=NULL && pInfo->m_bFloating)
		{
			CFrameWnd* pFrameWnd = pInfo->m_pBar->GetParentFrame();
			CDockBar* pDockBar = (CDockBar*)pInfo->m_pBar;
			ASSERT_KINDOF(CDockBar, pDockBar);
			if (pDockBar->GetDockedVisibleCount() > 0)
			{
				pFrameWnd->RecalcLayout();
				pFrameWnd->ShowWindow(SW_SHOWNA);
			}
		}
	}
	DelayRecalcLayout();
}


void COXFrameWndSizeDock::GetDockState(CDockState& state) const
{
	state.Clear(); //make sure dockstate is empty
	// get state info for each bar
	POSITION pos = m_listControlBars.GetHeadPosition();
	while (pos != NULL)
	{
		CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);
		CControlBarInfo* pInfo = new CControlBarInfo;
		pBar->GetBarInfo(pInfo);
		state.m_arrBarInfo.Add(pInfo);
	}
}


// private class - don't want this exported !
class OX_CLASS_DECL CWndSpaceElt : public CObject
{
	DECLARE_DYNAMIC(CWndSpaceElt);
	
	public:
		WORD ht;
		WORD wd;
};

IMPLEMENT_DYNAMIC(CWndSpaceElt, CObject);


// helper function to find list position
void PositionInSpcList(CWnd* pWnd, CObList& SpcList, DWORD dwOrient,
					   CWnd* pParentWnd, CSize& ParentSize, HDWP hDwp)	
	{
	
	CRect WndRect;
	pWnd->GetWindowRect(&WndRect);		// external dimensions of the window
	CSize WndSize;
	WndSize = WndRect.Size();			// size of rectangle
   	POSITION pos;
	
#ifdef _DEBUG
	CString strTitle;
	pWnd->GetWindowText(strTitle);
#ifdef _DEBUG_WNDPOS
	TRACE(_T("Inserting Window: %s, cx = %d, cy = %d\n"), LPCTSTR(strTitle), WndSize.cx, WndSize.cy);
#endif
	pos = SpcList.GetHeadPosition();
	int nTotalHeightBefore = 0;
	while (pos != NULL)
		{
		CWndSpaceElt* pSpcElt = (CWndSpaceElt*)SpcList.GetNext(pos);
		ASSERT(pSpcElt != NULL);
		
#ifdef _DEBUG_WNDPOS
		TRACE(_T("    ht= %d w=%d\n"), pSpcElt->ht, pSpcElt->wd);
#endif
		nTotalHeightBefore += pSpcElt->ht;
		}

//	ASSERT(nTotalHeightBefore == ParentSize.cy);		
#endif
	
	int nHt = WndSize.cy;			// height of window....
	int nWd = WndSize.cx;			// width of window (used below)
	int nHtLeft;
	
	int nCurY = 0;					// current Y position of scan
	int nMinX = 0xffff;				// minimum X position found so far;
	int nMinY = 0xffff;				// again should be ok...
	
	POSITION MinListPos = NULL;		// position in the list with this minimum X;
	
	pos = SpcList.GetHeadPosition();
	while (pos != NULL)
		{
		POSITION posCurrent = pos;
		CWndSpaceElt* pSpcElt = (CWndSpaceElt*)SpcList.GetNext(pos);
		ASSERT(pSpcElt != NULL);
		ASSERT_VALID(pSpcElt);
	
		// if we inserted in this position, what would the width be ? 
		// Set nHtLeft, ThisPosX accordingly....
		nHtLeft = nHt;
		int nThisX = 0;
		POSITION posLoop = posCurrent;
		while (posLoop != NULL) 
			{
			CWndSpaceElt* pLoopSpcElt = (CWndSpaceElt*)SpcList.GetNext(posLoop);
			nThisX = __max(nThisX, pLoopSpcElt->wd);
			if (nThisX > nMinX)
				break;		// give up if we're already beyond the current minimum
			nHtLeft -= pLoopSpcElt->ht;
			if (nHtLeft <= 0)
				{
				if (nThisX < nMinX)
					{
					nMinX = nThisX;
					MinListPos = posCurrent;	// acutually the position after the current index in the list
					nMinY = nCurY;
					}
				break;
				}
			}
		
		nCurY += pSpcElt->ht;	// update current Y position.
		}
	
	
	if (MinListPos == NULL || nMinX > ParentSize.cx)	// window wouldn't fit anywhere in the window cleanly, 
		{
#ifdef 	_DEBUG_WNDPOS
		TRACE(_T("No insert position found\n"));
#endif
		return;				// ignore this for now
		}
	
	ASSERT(MinListPos != NULL && nMinX < 0xffff);
	
	// work out the new position for the window
	// Might want to delay window positioning in future
	CPoint WndPt;
	WndPt.x = ((( dwOrient & CBRS_ARRANGE_LEFT ) == CBRS_ARRANGE_LEFT) ?  nMinX : ParentSize.cx - nMinX - WndSize.cx);
	WndPt.y = ((( dwOrient & CBRS_ARRANGE_TOP ) == CBRS_ARRANGE_TOP)  ?  nMinY : ParentSize.cy - nMinY - WndSize.cy);
	ASSERT(WndPt.y >= -1);
	
#ifdef _DEBUG_WNDPOS
	TRACE(_T("Positioning at: (%d, %d) nMinY=%d, nMinX=%d\n"), WndPt.x, WndPt.y, nMinY, nMinX);
#endif

	// if not child of requested window, convert co-ords to Screen
	if ((( pWnd->GetStyle() & WS_POPUP ) == WS_POPUP) || pWnd->GetParent() != pParentWnd)
		pParentWnd->ClientToScreen(&WndPt);
	
	
	CRect rcWnd;
	pWnd->GetWindowRect(rcWnd);
	// attempt to optimize by only moving windows that have changed position...
	if (rcWnd.TopLeft() != WndPt || rcWnd.Size() != WndSize)
		{
		if (hDwp == NULL)
			pWnd->SetWindowPos(NULL, WndPt.x, WndPt.y, WndSize.cx, WndSize.cy,
			SWP_NOSIZE | SWP_NOZORDER);
		else
			::DeferWindowPos(hDwp, pWnd->m_hWnd, NULL, WndPt.x,  WndPt.y, WndSize.cx, WndSize.cy,
			SWP_NOSIZE | SWP_NOZORDER);
		}
	
	// now update the SpcList.
	nHtLeft = nHt;
	ASSERT(nHt > 0);
	ASSERT(MinListPos != NULL);	// can't actually happen
	CWndSpaceElt * pSpcElt;
	POSITION InsertPos = NULL;
	while (pos != NULL)
		{
		POSITION Oldpos = pos;
		pSpcElt = (CWndSpaceElt*)SpcList.GetNext(pos);

		ASSERT_VALID(pSpcElt);
		if (pSpcElt->ht > nHtLeft)
			{		
			ASSERT(pSpcElt->ht >= nHtLeft);
			pSpcElt->ht = (WORD)(pSpcElt->ht - (WORD)nHtLeft);			
			nHtLeft = 0;
			InsertPos = Oldpos;		// position to insert before
			break;
			}
		nHtLeft -= pSpcElt->ht;
		
		CWndSpaceElt* pOldElt = (CWndSpaceElt*)SpcList.GetAt(Oldpos);
		ASSERT(pOldElt != NULL && pOldElt->IsKindOf(RUNTIME_CLASS(CWndSpaceElt)));
		SpcList.RemoveAt(Oldpos);				// remove that element
		
		ASSERT(pSpcElt != NULL && pSpcElt->IsKindOf(RUNTIME_CLASS(CWndSpaceElt)));
		delete pOldElt;
		}
//	ASSERT(nHtLeft == 0);
	
	// should now be looking at the element we need to shrink...
	// NB: If pos = NULL then we removed to the end of the list...
	pSpcElt = new CWndSpaceElt;
	pSpcElt->wd = (WORD)(nMinX + nWd);
	pSpcElt->ht = (WORD)nHt;
	if (InsertPos == NULL)
		SpcList.AddTail(pSpcElt);
	else
		SpcList.InsertBefore(InsertPos, pSpcElt);

#ifdef _DEBUG
#ifdef _DEBUG_WNDPOS
	TRACE0("After insert:\n");
#endif
	pos = SpcList.GetHeadPosition();
	int nTotalHeightAfter = 0;
	while (pos != NULL)
		{
		CWndSpaceElt* pSpcElt = (CWndSpaceElt*)SpcList.GetNext(pos);
		ASSERT(pSpcElt != NULL);
		ASSERT_VALID(pSpcElt);
		nTotalHeightAfter += pSpcElt->ht;
#ifdef _DEBUG_WNDPOS
		TRACE2("    ht= %d w=%d\n", pSpcElt->ht, pSpcElt->wd);
#endif
		}
	
//	ASSERT(nTotalHeightAfter == ParentSize.cy);		
//	ASSERT(nTotalHeightBefore == nTotalHeightAfter);
#endif
	}

int __cdecl CompareWndRect(const void* elem1, const void* elem2)
	{
	CRect rect1;
	CRect rect2;
	CWnd* pWnd1 = *((CWnd**)elem1);
	CWnd* pWnd2 = *((CWnd**)elem2);
	pWnd1->GetWindowRect(&rect1);
	pWnd2->GetWindowRect(&rect2);
	// array will be sorted into increasing order, so want the larger rectangles first.
	CSize size1 = rect1.Size();
	CSize size2 = rect2.Size();
	return ((size2.cx * size2.cy) - (size1.cx * size1.cy));
	}	


// Arranges the windows within the rectangle of another window.
void ArrangeWindowsInWindow (CWnd* pParentWnd, CObArray& arrWnd, DWORD dwOrient)
	{
	if (arrWnd.GetSize() == 0)			// no windows to size.. do nothing
		return;

	CRect ClientRect;
	pParentWnd->GetClientRect(&ClientRect);
	
	CSize ParentSize = ClientRect.Size();
	if (ParentSize.cy == 0)
		return;							// no height => not much we can do	
	
	CObList SpcList;					// list used to keep track of window spacing
	
	// add initial Arrange rectangle to the list;	
	CWndSpaceElt* pSpcElt = new CWndSpaceElt;
	pSpcElt->wd = 0;
	pSpcElt->ht = (WORD)ClientRect.Height();
	SpcList.AddTail(pSpcElt); 
	
	// sort array of window positions by size so that we position the largest windows first.
	// this improves the results quite a bit
	CObject ** pArrData = arrWnd.GetData();
	ASSERT(pArrData != NULL);		// shouldn't be NULL as array is non-empty, but check anyway	
	qsort(pArrData, arrWnd.GetSize(), sizeof(CObject *), CompareWndRect); 	

	HDWP hDWP = BeginDeferWindowPos(PtrToInt(arrWnd.GetSize()));	   // defer window moves to save on refresh
	
	// iterate thru all the windows in the list looking for a position to put it
	for (int nWndNo = 0; nWndNo < arrWnd.GetSize(); nWndNo++)
		{
		CWnd* pWnd = (CWnd*)arrWnd[nWndNo];
		ASSERT(pWnd != NULL);
		ASSERT_VALID(pWnd);
		PositionInSpcList(pWnd, SpcList, dwOrient, pParentWnd, ParentSize, hDWP);
		} 
	
	if (hDWP != NULL)
		::EndDeferWindowPos(hDWP);		// move the windows
	
	// Remove elements from the SpcList;
	while (!SpcList.IsEmpty())
		{
		CWndSpaceElt* pElt = (CWndSpaceElt*)SpcList.GetTail();
		delete pElt;
		SpcList.RemoveTail();
		}
	}


////////////////////////////////////////////////////////////////////////////////
// Diagnostics
#ifdef _DEBUG
void COXFrameWndSizeDock::AssertValid() const
	{
	CFrameWnd::AssertValid();
	}

void COXFrameWndSizeDock::Dump(CDumpContext& dc) const
	{
	CFrameWnd::Dump(dc);
	}
#endif

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// COXMDIFrameWndSizeDock frame
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(COXMDIFrameWndSizeDock, CMDIFrameWnd)

/////////////////////////////////////////////////////////////////////////////
// Definition of static members

// Data members -------------------------------------------------------------
// protected:

// private:
	
// Member functions ---------------------------------------------------------
// public:

COXMDIFrameWndSizeDock::COXMDIFrameWndSizeDock()
	: m_pActiveDockChild(NULL),
	m_bBeingDestroyed(FALSE),
	m_pLastActiveCtrlBar(NULL)
{
}

COXMDIFrameWndSizeDock::~COXMDIFrameWndSizeDock()
{
#ifdef _DEBUG
	CObArray arrWnd;
	GetFloatingBars(arrWnd);  // debug code to see what's still around !
#endif
}


BEGIN_MESSAGE_MAP(COXMDIFrameWndSizeDock, CMDIFrameWnd)
//{{AFX_MSG_MAP(COXMDIFrameWndSizeDock)
	ON_WM_DESTROY()
	ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
	ON_WM_CLOSE()
	ON_WM_ACTIVATE()
	ON_COMMAND_EX(ID_VIEW_STATUS_BAR, OnBarCheck)
	//}}AFX_MSG_MAP
	ON_COMMAND(ID_WINDOW_NEW, OnWindowNew)
	ON_MESSAGE(WM_QUERYSNAPPING, OnQuerySnapping)
END_MESSAGE_MAP()


void COXMDIFrameWndSizeDock::OnDestroy()
{
	if(GetTopLevelFrame()==this || GetTopLevelFrame()==NULL)
	{
		// tidy up any outstanding control bars...
		COXSizeControlBar::TidyUp(this);		
	}

	CMDIFrameWnd::OnDestroy();
}

LRESULT COXMDIFrameWndSizeDock::OnQuerySnapping(WPARAM, LPARAM)
{
	return m_bEnableSnapping;
}


void COXMDIFrameWndSizeDock::FloatControlBarInMDIChild(CControlBar* pBar, CPoint point, DWORD dwStyle, BOOL bVisible /*=TRUE*/)
// float a control bar in an MDI Child window
// pBar = bar to float
// point = position in screen co-ordinates
{
	ASSERT(pBar != NULL);
	
	// point is in screen co-ords - map to client
	::ScreenToClient(m_hWndMDIClient, &point);

	// clip to client MDI client rectangle - ensures it's going to be visible
	CRect rcCtrlBar;
	pBar->GetClientRect(&rcCtrlBar);
	CRect rcMDIClient;
	::GetClientRect(m_hWndMDIClient, &rcMDIClient);
	point.x = __min(point.x, rcMDIClient.right - rcCtrlBar.Width());
	point.x = __max(point.x, rcMDIClient.left);		
	point.y = __min(point.y, rcMDIClient.bottom  - rcCtrlBar.Height());
	point.y = __max(point.y, rcMDIClient.top);		
	
	
	// If the bar is already floating in an MDI child, then just move it
	// MFC has a similar optimization for CMiniDockFrameWnd 
	if (pBar->m_pDockSite != NULL && pBar->m_pDockBar != NULL)
		{
		CDockBar* pDockBar = pBar->m_pDockBar;
		ASSERT(pDockBar->IsKindOf(RUNTIME_CLASS(CDockBar)));
		CFrameWnd* pDockFrame = (CFrameWnd*)pDockBar->GetParent();
		ASSERT(pDockFrame != NULL);
		ASSERT(pDockFrame->IsKindOf(RUNTIME_CLASS(CFrameWnd)));
		if (pDockFrame->IsKindOf(RUNTIME_CLASS(COXMDIFloatWnd)))
			{
			// already a floating as an MDI child, so just move it.
			if (pDockBar->m_bFloating && pDockBar->GetDockedCount() == 1 &&
				(dwStyle & pDockBar->m_dwStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_ANY)
				{
				pDockFrame->SetWindowPos(NULL, point.x, point.y, 0, 0,
					SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
				return;
				}
			}
		}
	
	// Create a COXMDIFloatWnd, and dock the bar into it.
	COXMDIFloatWnd* pDockFrame=
		(COXMDIFloatWnd*)(RUNTIME_CLASS(COXMDIFloatWnd))->CreateObject();
	ASSERT(pDockFrame != NULL);
	if (!pDockFrame->Create(this, dwStyle))
		AfxThrowResourceException();
	
	pDockFrame->SetWindowPos(NULL, point.x, point.y, 0, 0,
		SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
	
	if (pDockFrame->m_hWndOwner == NULL)
		pDockFrame->m_hWndOwner = pBar->m_hWnd;
	
	// Gets the dockbar created by the COXMDIFloatWnd
	CDockBar* pDockBar = (CDockBar*)pDockFrame->GetDlgItem(AFX_IDW_DOCKBAR_FLOAT);
	ASSERT(pDockBar != NULL);
	ASSERT(pDockBar->IsKindOf(RUNTIME_CLASS(CDockBar)));
	
	ASSERT(pBar->m_pDockSite == this);
	// if this assertion occurred it is because the parent of pBar was not
	//  initially this CFrameWnd when pBar's OnCreate was called
	// (this control bar should have been created with a different
	//  parent initially)
	
	pDockBar->DockControlBar(pBar);
	pDockFrame->RecalcLayout();

	if(bVisible)
	{
		pDockFrame->ShowWindow(SW_SHOWNA);
		pDockFrame->UpdateWindow(); 
	}
	
	::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
}	

// removes the control bar from an MDI floating window, and then floats the bar
void COXMDIFrameWndSizeDock::UnFloatInMDIChild(CControlBar* pBar, CPoint point, DWORD dwStyle)
	{
	ASSERT(pBar != NULL);
	ASSERT(pBar->IsFloating());
	COXMDIFloatWnd * pFloatFrame = (COXMDIFloatWnd *)pBar->GetParentFrame();
	ASSERT(pFloatFrame->IsKindOf(RUNTIME_CLASS(COXMDIFloatWnd)));
	
	// point at which to float is ignored at present - use the co-ordinates of the current frame
	CRect rcMDIFloat;
	pFloatFrame->GetWindowRect(&rcMDIFloat);
	point = rcMDIFloat.TopLeft();

	// This is basically the code from MFC's CFrameWnd::FloatControlBar(), with the
	// test to avoid destroying/creating the floating frame window removed. 
	// Tried explicitly removing the control bar, but this doesn't work as it destroys the
	// CMDIFloatWnd, which in turn kills the child control bar. So need to create the floating
	// frame first, and then dock into this.  
	CMiniDockFrameWnd* pDockFrame = CreateFloatingFrame(dwStyle);
	ASSERT(pDockFrame != NULL);
	pDockFrame->SetWindowPos(NULL, point.x, point.y, 0, 0,
		SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
	if (pDockFrame->m_hWndOwner == NULL)
		pDockFrame->m_hWndOwner = pBar->m_hWnd;
	
	CDockBar* pDockBar = (CDockBar*)pDockFrame->GetDlgItem(AFX_IDW_DOCKBAR_FLOAT);
	ASSERT(pDockBar != NULL);
	ASSERT(pDockBar->IsKindOf(RUNTIME_CLASS(CDockBar)));
	
	ASSERT(pBar->m_pDockSite == this);
	// if this assertion occurred it is because the parent of pBar was not
	//  initially this CFrameWnd when pBar's OnCreate was called
	// (this control bar should have been created with a different
	//  parent initially)
	
	pDockBar->DockControlBar(pBar);
	pDockFrame->RecalcLayout();
	pDockFrame->ShowWindow(SW_SHOWNA);
	pDockFrame->UpdateWindow();

	::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
	}


// if control bar supplied, then set just resize it
void ForceLayoutAdjust(CControlBar* pBar)
	{
	CDockBar* pDockBar;
	ASSERT(pBar != NULL);
	pDockBar = pBar->m_pDockBar;
	if (pDockBar!= NULL && pDockBar->IsKindOf(RUNTIME_CLASS(COXSizeDockBar)))
		((COXSizeDockBar*)pDockBar)->m_CountBars = 0;			
	}

#ifdef _DEBUG
void COXMDIFrameWndSizeDock::AssertValid() const
	{
	CMDIFrameWnd::AssertValid();
	}

void COXMDIFrameWndSizeDock::Dump(CDumpContext& dc) const
	{
	CMDIFrameWnd::Dump(dc);
	dc << "\nCOXMDIFrameWndSizeDock - dockbars";
	}
#endif


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

void COXMDIFrameWndSizeDock::HookActivation()
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(m_hWndMDIClient!=NULL);

	CWnd* pActiveWnd=MDIGetActive();

	CWnd* pMDIClient=CWnd::FromHandle(m_hWndMDIClient);
	CWnd* pChild=pMDIClient->GetWindow(GW_CHILD);
	while(pChild!=NULL)
	{
		if(pChild->IsKindOf(RUNTIME_CLASS(COXMDIChildWndSizeDock)))
		{
			BOOL bActive=(pActiveWnd==pChild) ? TRUE : FALSE;
			((COXMDIChildWndSizeDock*)pChild)->SendMessage(WM_NCACTIVATE,bActive);
		}
		pChild=pChild->GetNextWindow();
	}

	CView* pView;
	pView=((COXMDIChildWndSizeDock*)pActiveWnd)->GetActiveView();
	if(pView!=NULL)
	{
		BOOL bSetHack=FALSE;
		DWORD dwStyle=pView->GetStyle();
		CFrameWnd* pFrame=pView->GetParentFrame();
		if(pFrame->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)) && 
			!((dwStyle&WS_VISIBLE)==0))
		{
			::SetWindowLongPtr(pView->GetSafeHwnd(),GWL_STYLE,dwStyle&~WS_VISIBLE);
			if(pView->SetParent(this)!=NULL)
			{
				bSetHack=TRUE;
			}
		}
		

		SetActiveView(pView);

		if(bSetHack)
		{
			pView->SetParent(&(((COXMDIChildWndSizeDock*)pActiveWnd)->m_dockBar));
			::SetWindowLongPtr(pView->GetSafeHwnd(),GWL_STYLE,dwStyle);
		}
	}

	OnUpdateFrameTitle(TRUE);
}

BOOL COXMDIFrameWndSizeDock::IsDockable(CWnd* pWnd)
{
	if(pWnd->IsKindOf(RUNTIME_CLASS(COXMDIChildWndSizeDock)))
	{
		return ((COXMDIChildWndSizeDock*)pWnd)->IsDockable();
	}
	return FALSE;
}

BOOL COXMDIFrameWndSizeDock::IsFrontChildMaximized()
{
	BOOL bMaximized=FALSE;
	CMDIChildWnd* pChild=CMDIFrameWnd::MDIGetActive(&bMaximized);
	bMaximized=pChild==NULL ? FALSE : bMaximized;
	return bMaximized;
}

void COXMDIFrameWndSizeDock::SetActiveChild(CWnd* pWnd)
{
	if(pWnd==NULL || !::IsWindow(pWnd->m_hWnd))
	{
		m_pActiveDockChild=NULL;		
	}
	else
	{
		ASSERT_KINDOF(COXMDIChildWndSizeDock,pWnd);
		m_pActiveDockChild=(COXMDIChildWndSizeDock*)pWnd;		
	}
}

COXMDIChildWndSizeDock* COXMDIFrameWndSizeDock::GetActiveChild() 
{ 
	if(m_pActiveDockChild!=NULL)
	{
		if(!::IsWindow(m_pActiveDockChild->m_hWnd))
		{
			m_pActiveDockChild=NULL;
		}
	}
	return m_pActiveDockChild; 
}

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

void COXMDIFrameWndSizeDock::MDIActivate(CWnd* pWndActivate)
{ 
	ASSERT(::IsWindow(m_hWnd));

	if(IsDockable(pWndActivate))
	{
		SetActiveChild(pWndActivate);
		TRACE(_T("COXMDIFrameWndSizeDock::MDIActivate::Dockable\n"));
	}
	else
	{
		SetActiveChild(NULL);
		CMDIFrameWnd::MDIActivate(pWndActivate);
		TRACE(_T("COXMDIFrameWndSizeDock::MDIActivate::Non-Dockable\n"));
	}
	HookActivation();
}

void COXMDIFrameWndSizeDock::MDIMaximize(CWnd* pWnd)
{
	ASSERT(::IsWindow(m_hWnd));

	if(!IsDockable(pWnd))
	{
		CMDIFrameWnd::MDIMaximize(pWnd);
	}
}

void COXMDIFrameWndSizeDock::MDIRestore(CWnd* pWnd)
{ 
	ASSERT(::IsWindow(m_hWnd)); 

	if(!IsDockable(pWnd))
	{
		CMDIFrameWnd::MDIRestore(pWnd);
	}
}

CMDIChildWnd* COXMDIFrameWndSizeDock::MDIGetActive(BOOL* pbMaximized) const
{
	ASSERT(::IsWindow(m_hWndMDIClient));

	CMDIChildWnd* pActiveWnd;
	if(m_pActiveDockChild==NULL)
	{
		pActiveWnd=CMDIFrameWnd::MDIGetActive(pbMaximized);
	}
	else
	{
		if(pbMaximized!=NULL)
		{
			*pbMaximized=FALSE;
		}
		pActiveWnd=(CMDIChildWnd*)m_pActiveDockChild;
	}

	if(pActiveWnd!=NULL)
	{
		if(!::IsWindow(pActiveWnd->m_hWnd))
		{
			pActiveWnd=NULL;
		}
	}

	return pActiveWnd;
}

BOOL COXMDIFrameWndSizeDock::IsChild(const CWnd* pWnd)
{
	if(AfxGetMainWnd()==this && pWnd!=NULL && pWnd->IsKindOf(RUNTIME_CLASS(CView)))
	{
		CFrameWnd* pFrame=pWnd->GetParentFrame();
		if(pFrame->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)))
		{
			return TRUE;
		}
	}
	return CMDIFrameWnd::IsChild(pWnd);
}

BOOL COXMDIFrameWndSizeDock::OnBarCheck(UINT nID)
{
	ASSERT(ID_VIEW_STATUS_BAR == AFX_IDW_STATUS_BAR);
	ASSERT(ID_VIEW_TOOLBAR == AFX_IDW_TOOLBAR);

	if(CFrameWnd::OnBarCheck(nID))
	{
		CControlBar* pBar = GetControlBar(nID);
		if(pBar && pBar->IsKindOf(RUNTIME_CLASS(COXSizeControlBar)))
		{
			if(((COXSizeControlBar*)pBar)->m_pDockSite != NULL && 
				((COXSizeControlBar*)pBar)->m_pDockBar != NULL)
			{
				if(MDIGetActive() == pBar->GetParentFrame() && 
					!pBar->IsWindowVisible())
				{
					MDINext();
				}
				::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
			}
		}
		return TRUE;
	}
	return FALSE;
}

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

LRESULT COXMDIFrameWndSizeDock::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	if(nMsg==WM_SETTEXT)
	{
		CMDIChildWnd* pActiveChild=MDIGetActive();
		if(pActiveChild!=NULL && IsDockable(pActiveChild))
		{
			return CWnd::DefWindowProc(nMsg, wParam, lParam);
		}
	}

	return CMDIFrameWnd::DefWindowProc(nMsg, wParam, lParam);
}

BOOL COXMDIFrameWndSizeDock::PreTranslateMessage(MSG* pMsg)
{
	// check for special cancel modes for ComboBoxes
	if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_NCLBUTTONDOWN)
		AfxCancelModes(pMsg->hwnd);    // filter clicks

	// allow tooltip messages to be filtered
	if (CWnd::PreTranslateMessage(pMsg))
		return TRUE;

#ifndef _AFX_NO_OLE_SUPPORT
	// allow hook to consume message
	if (m_pNotifyHook != NULL && m_pNotifyHook->OnPreTranslateMessage(pMsg))
		return TRUE;
#endif

	CMDIChildWnd* pActiveChild = MDIGetActive();

	// current active child gets first crack at it
	if (pActiveChild != NULL && pActiveChild->PreTranslateMessage(pMsg))
		return TRUE;

	if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
	{
		// translate accelerators for frame and any children
		if (m_hAccelTable != NULL &&
			::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg))
		{
			return TRUE;
		}

		// special processing for MDI accelerators last
		// and only if it is not in SDI mode (print preview)
		if (GetActiveView() == NULL)
		{
			if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
			{
				// the MDICLIENT window may translate it
				if (::TranslateMDISysAccel(m_hWndMDIClient, pMsg))
					return TRUE;
			}
		}
	}

	return FALSE;
}

BOOL COXMDIFrameWndSizeDock::DestroyWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	
	SetActiveView(NULL);
	TRACE(_T("MainWindow destroyed\n"));
	return CMDIFrameWnd::DestroyWindow();
}

/////////////////////////////////////////////////////////////////////////////
// Special UI processing depending on current active child

void COXMDIFrameWndSizeDock::OnUpdateFrameTitle(BOOL bAddToTitle)
{
	if ((GetStyle() & FWS_ADDTOTITLE) == 0)
		return;     // leave it alone!

#ifndef _AFX_NO_OLE_SUPPORT
	// allow hook to set the title (used for OLE support)
	if (m_pNotifyHook != NULL && m_pNotifyHook->OnUpdateFrameTitle())
		return;
#endif

	CMDIChildWnd* pActiveChild=MDIGetActive();
	if(pActiveChild!=NULL && ::IsWindow(pActiveChild->m_hWnd))
	{
		CDocument* pDocument = GetActiveDocument();
		if(bAddToTitle && (pActiveChild->GetStyle() & WS_MAXIMIZE) == 0 && 
			(pDocument != NULL || 
			(pDocument = pActiveChild->GetActiveDocument()) != NULL))
		{
			UpdateFrameTitleForDocument(pDocument->GetTitle());
		}
		else
		{
			UpdateFrameTitleForDocument(NULL);
		}
	}
	else
	{
		UpdateFrameTitleForDocument(NULL);
	}
}

BOOL COXMDIFrameWndSizeDock::OnCmdMsg(UINT nID, int nCode, void* pExtra, 
									  AFX_CMDHANDLERINFO* pHandlerInfo)
{
	// Print Preview
	if (m_lpfnCloseProc != NULL)
		return CMDIFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);

	if (CMDIFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;

	SetActiveView(NULL);

	return FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// Smarts for updating the window menu based on the current child

void COXMDIFrameWndSizeDock::OnUpdateFrameMenu(HMENU hMenuAlt)
{
	CMDIChildWnd* pActiveWnd = MDIGetActive();
	if (pActiveWnd != NULL)
	{
		// let child update the menu bar
		pActiveWnd->OnUpdateFrameMenu(TRUE, pActiveWnd, hMenuAlt);
	}
	else
	{
		// no child active, so have to update it ourselves
		//  (we can't send it to a child window, since pActiveWnd is NULL)
		if (hMenuAlt == NULL)
			hMenuAlt = m_hMenuDefault;  // use default
		::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuAlt, NULL);
	}
}

CFrameWnd* COXMDIFrameWndSizeDock::GetActiveFrame()
{
	CMDIChildWnd* pActiveChild=NULL;
	pActiveChild = MDIGetActive();
	if (pActiveChild == NULL)
		return this;
	return pActiveChild;
}

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

BOOL COXMDIFrameWndSizeDock::OnCommand(WPARAM wParam, LPARAM lParam)
{
	// send to MDI child first - will be re-sent through OnCmdMsg later
	CMDIChildWnd* pActiveChild = MDIGetActive();
	
	if (pActiveChild != NULL && AfxCallWndProc(pActiveChild,
	  pActiveChild->m_hWnd, WM_COMMAND, wParam, lParam) != 0)
		return TRUE; // handled by child

	if (CFrameWnd::OnCommand(wParam, lParam))
		return TRUE; // handled through normal mechanism (MDI child or frame)

	HWND hWndCtrl = (HWND)lParam;

	ASSERT(AFX_IDM_FIRST_MDICHILD == 0xFF00);
	if (hWndCtrl == NULL && (LOWORD(wParam) & 0xf000) == 0xf000)
	{
		// menu or accelerator within range of MDI children
		// default frame proc will handle it
		DefWindowProc(WM_COMMAND, wParam, lParam);
		return TRUE;
	}

	return FALSE;   // not handled
}

/////////////////////////////////////////////////////////////////////////////
// Standard MDI Commands

// Two function for all standard MDI "Window" commands
void COXMDIFrameWndSizeDock::OnUpdateMDIWindowCmd(CCmdUI* pCmdUI)
{
	ASSERT(m_hWndMDIClient != NULL);
	pCmdUI->Enable(MDIGetActive() != NULL);
}

void COXMDIFrameWndSizeDock::OnWindowNew()
{
	CMDIChildWnd* pActiveChild = MDIGetActive();
	CDocument* pDocument;
	if (pActiveChild == NULL ||
	  (pDocument = pActiveChild->GetActiveDocument()) == NULL)
	{
		TRACE0("Warning: No active document for WindowNew command.\n");
		AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
		return;     // command failed
	}

	// otherwise we have a new frame !
	CDocTemplate* pTemplate = pDocument->GetDocTemplate();
	ASSERT_VALID(pTemplate);
	CFrameWnd* pFrame = pTemplate->CreateNewFrame(pDocument, pActiveChild);
	if (pFrame == NULL)
	{
		TRACE0("Warning: failed to create new frame.\n");
		return;     // command failed
	}

	pTemplate->InitialUpdateFrame(pFrame, pDocument);
	HookActivation();
}

LRESULT COXMDIFrameWndSizeDock::OnCommandHelp(WPARAM wParam, LPARAM lParam)
{
	if (lParam == 0 && IsTracking())
		lParam = HID_BASE_COMMAND+m_nIDTracking;

	CMDIChildWnd* pActiveChild = MDIGetActive();
	if (pActiveChild != NULL && AfxCallWndProc(pActiveChild,
	  pActiveChild->m_hWnd, WM_COMMANDHELP, wParam, lParam) != 0)
	{
		// handled by child
		return TRUE;
	}

	if (CFrameWnd::OnCommandHelp(wParam, lParam))
	{
		// handled by our base
		return TRUE;
	}

	if (lParam != 0)
	{
		AfxGetApp()->WinHelp(lParam);
		return TRUE;
	}
	return FALSE;
}

void COXMDIFrameWndSizeDock::OnClose()
{
	if (m_lpfnCloseProc != NULL && !(*m_lpfnCloseProc)(this))
		return;

	if(m_bBeingDestroyed)
	{
		return;
	}

	m_bBeingDestroyed=TRUE;


	CWinApp* pApp = AfxGetApp();
	if (pApp->m_pMainWnd == this)
	{
		// attempt to save all documents
		if(!pApp->SaveAllModified())
		{
			m_bBeingDestroyed=FALSE;
			return;     // don't close it
		}
		else
		{
			if(pApp->m_pDocManager != NULL)
			{
				POSITION pos=pApp->m_pDocManager->GetFirstDocTemplatePosition();
				while(pos!=NULL)
				{
					CDocTemplate* pTemplate=pApp->m_pDocManager->GetNextDocTemplate(pos);
					ASSERT_KINDOF(CDocTemplate, pTemplate);

					POSITION posDoc=pTemplate->GetFirstDocPosition();
					while (posDoc!=NULL)
					{
						CDocument* pDoc=pTemplate->GetNextDoc(posDoc);
						pDoc->SetModifiedFlag(FALSE);
					}
				}
			}
		}

		// hide the application's windows before closing all the documents
		pApp->HideApplication();

		UndockAllViews();

		// close all documents first
		pApp->CloseAllDocuments(FALSE);

		// don't exit if there are outstanding component objects
		if (!AfxOleCanExitApp())
		{
			// take user out of control of the app
			AfxOleSetUserCtrl(FALSE);

			// don't destroy the main window and close down just yet
			//  (there are outstanding component (OLE) objects)
			return;
		}

		// there are cases where destroying the documents may destroy the
		//  main window of the application.
		if (!afxContextIsDLL && pApp->m_pMainWnd == NULL)
		{
			AfxPostQuitMessage(0);
			return;
		}
	}

	// then destroy the window
	DestroyWindow();
}

void COXMDIFrameWndSizeDock::OnActivate(UINT nState, CWnd* pWndOther, 
										BOOL bMinimized) 
{
	if(nState==WA_INACTIVE)
	{
		if(m_pLastActiveCtrlBar!=NULL)		
		{	
			m_pLastActiveCtrlBar->SetActive(FALSE,FALSE);
		}
	}
	else if(nState!=WA_CLICKACTIVE)
	{
		if(m_pLastActiveCtrlBar!=NULL)
		{			
			m_pLastActiveCtrlBar->SetActive(TRUE,TRUE);
		}
	}

	CMDIFrameWnd::OnActivate(nState, pWndOther, bMinimized);	
}

void COXMDIFrameWndSizeDock::UndockAllViews()
{
	CWnd* pMDIClient=CWnd::FromHandle(m_hWndMDIClient);
	CWnd* pChild=pMDIClient->GetWindow(GW_CHILD);
	while(pChild!=NULL)
	{
		if(IsDockable(pChild))
		{
			if(::IsWindow(((COXMDIChildWndSizeDock*)pChild)->m_dockBar.m_hWnd))
			{
				((COXMDIChildWndSizeDock*)pChild)->m_dockBar.DetachMDIChild(FALSE);
			}
		}
		pChild=pChild->GetNextWindow();
	}
}

void COXMDIFrameWndSizeDock::SaveSizeBarState(LPCTSTR pszProfileName)
{
	// remove bars allocated dynamically
	((COXFrameWndSizeDock*)this)->DestroyDynamicBars();			
	// - we reload these at present
	
	SaveBarState(pszProfileName);	// save the raw states
#ifdef _VERBOSE_TRACE
	TRACE0("Loading Bar Sizes\n");
#endif
	// save additional info
	((COXFrameWndSizeDock*)this)->SaveBarSizes(pszProfileName, TRUE);			
	AfxGetApp()->WriteProfileInt(pszProfileName, REG_VERSION, REG_VERSION_NO);
}

void COXMDIFrameWndSizeDock::SaveBarState(LPCTSTR lpszProfileName) const
{
	CDockState state;
	GetDockState(state);
	state.SaveState(lpszProfileName);
}

void COXMDIFrameWndSizeDock::GetDockState(CDockState& state) const
{
	state.Clear(); //make sure dockstate is empty
	// get state info for each bar
	POSITION pos = m_listControlBars.GetHeadPosition();
	while (pos != NULL)
	{
		CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);
		if(!pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
		{
			CControlBarInfo* pInfo = new CControlBarInfo;
			pBar->GetBarInfo(pInfo);
			state.m_arrBarInfo.Add(pInfo);
		}
	}
}

void COXMDIFrameWndSizeDock::FloatControlBar(CControlBar* pBar, CPoint point, DWORD dwStyle)
{
	ASSERT(pBar != NULL);

	// if the bar is already floating and the dock bar only contains this
	// bar and same orientation then move the window rather than recreating
	// the frame
	if (pBar->m_pDockSite != NULL && pBar->m_pDockBar != NULL)
	{
		CDockBar* pDockBar = pBar->m_pDockBar;
		ASSERT_KINDOF(CDockBar, pDockBar);
		if (pDockBar->m_bFloating && pDockBar->GetDockedCount() == 1 &&
			(dwStyle & pDockBar->m_dwStyle & CBRS_ALIGN_ANY) != 0)
		{
			COXSizableMiniDockFrameWnd* pDockFrame =
				(COXSizableMiniDockFrameWnd*)pDockBar->GetParent();
			ASSERT(pDockFrame != NULL);
			ASSERT_KINDOF(COXSizableMiniDockFrameWnd, pDockFrame);
			pDockFrame->SetWindowPos(NULL, point.x, point.y, 0, 0,
				SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
			pDockFrame->RecalcLayout(TRUE);
			pDockFrame->UpdateWindow();
			return;
		}
	}

	if (pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
	{
		dwStyle |= CBRS_SIZE_DYNAMIC;
		if (dwStyle & CBRS_ORIENT_VERT)
		{
			dwStyle &= ~CBRS_ALIGN_ANY;
			dwStyle |= CBRS_ALIGN_TOP;
		}
	}

	COXSizableMiniDockFrameWnd* pDockFrame = 
		(COXSizableMiniDockFrameWnd*) CreateFloatingFrame(dwStyle);
	ASSERT(pDockFrame != NULL);
	pDockFrame->SetWindowPos(NULL, point.x, point.y, 0, 0,
		SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
	if (pDockFrame->m_hWndOwner == NULL)
		pDockFrame->m_hWndOwner = pBar->m_hWnd;

	CDockBar* pDockBar = (CDockBar*)pDockFrame->GetDlgItem(AFX_IDW_DOCKBAR_FLOAT);
	ASSERT(pDockBar != NULL);
	ASSERT_KINDOF(CDockBar, pDockBar);

	ASSERT(pBar->m_pDockSite == this);
	// if this assertion occurred it is because the parent of pBar was not
	//  initially this CFrameWnd when pBar's OnCreate was called
	// (this control bar should have been created with a different
	//  parent initially)

	pDockBar->DockControlBar(pBar);
//	pDockBar->GetParent()->ModifyStyle(WS_POPUP,WS_CHILD);
//	pDockBar->GetParent()->SetParent(AfxGetMainWnd());
	pDockFrame->RecalcLayout(TRUE);
	if (GetWindowLongPtr(pBar->m_hWnd, GWL_STYLE) & WS_VISIBLE)
	{
		pDockFrame->ShowWindow(SW_SHOWNA);
		pDockFrame->UpdateWindow();
	}
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// COXMDIChildWndSizeDock frame
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

#ifdef _OXIE4PATCH
UINT COXMDIChildWndSizeDock::m_nDockMessageID=WM_DOCKCHILDWND;
#else
UINT COXMDIChildWndSizeDock::m_nDockMessageID=
	::RegisterWindowMessage(_T("_DOCK_MDICHILD_"));
#endif // _OXIE4PATCH

IMPLEMENT_DYNCREATE(COXMDIChildWndSizeDock, CMDIChildWnd)

/////////////////////////////////////////////////////////////////////////////
// Definition of static members

// Data members -------------------------------------------------------------
// protected:

// private:
	
// Member functions ---------------------------------------------------------
// public:

COXMDIChildWndSizeDock::COXMDIChildWndSizeDock()
{
	m_bDockable=FALSE;
	
	VERIFY(m_sDockMenuItem.LoadString(IDS_OX_MDICHILDITEM));//"Dock window"

	m_dwDockStyle=CBRS_ALIGN_ANY;

	m_bBeingDestroyed=FALSE;
}

COXMDIChildWndSizeDock::~COXMDIChildWndSizeDock()
{
}

BEGIN_MESSAGE_MAP(COXMDIChildWndSizeDock, CMDIChildWnd)
//{{AFX_MSG_MAP(COXMDIChildWndSizeDock)
	ON_WM_MDIACTIVATE()
	ON_WM_NCACTIVATE()
	ON_WM_MOUSEACTIVATE()
	ON_WM_CLOSE()
	ON_WM_CONTEXTMENU()
	ON_WM_PARENTNOTIFY()
	ON_WM_SYSCOMMAND()
	ON_WM_NCRBUTTONDOWN()
	//}}AFX_MSG_MAP
	ON_WM_STYLECHANGING()
	ON_MESSAGE(WM_SETTEXT,OnSetText)
#ifdef _OXIE4PATCH
	ON_COMMAND(WM_DOCKCHILDWND,OnMakeItDockable)
#else
	ON_COMMAND(m_nDockMessageID,OnMakeItDockable)
#endif // _OXIE4PATCH
END_MESSAGE_MAP()

BOOL COXMDIChildWndSizeDock::MakeItDockable(BOOL bDockable, DWORD style, bool dockToSide)
{
	if(!IsDockableFrame())
	{
		return FALSE;
	}

	if(bDockable==m_bDockable)
	{
		return TRUE;
	}

	BOOL bResult;
	if(bDockable)
	{
		bResult=m_dockBar.AttachMDIChild(this, style, dockToSide);
		RecalcLayout();
	}
	else
	{
		ASSERT(::IsWindow(m_dockBar.m_hWnd));
		bResult=m_dockBar.DetachMDIChild();
		RecalcLayout();
	}

	m_bDockable=bDockable;	

	return bResult;
}

BOOL COXMDIChildWndSizeDock::IsDockableFrame()
{
	ASSERT(::IsWindow(m_hWnd));
	CMDIFrameWnd* pMDIFrame=GetMDIFrame();
	return pMDIFrame->IsKindOf(RUNTIME_CLASS(COXMDIFrameWndSizeDock));
}

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

BOOL COXMDIChildWndSizeDock::Create(LPCTSTR lpszClassName,
	LPCTSTR lpszWindowName, DWORD dwStyle,
	const RECT& rect, CMDIFrameWnd* pParentWnd,
	CCreateContext* pContext)
{
	if (pParentWnd == NULL)
	{
		CWnd* pMainWnd = AfxGetThread()->m_pMainWnd;
		ASSERT(pMainWnd != NULL);
		ASSERT_KINDOF(CMDIFrameWnd, pMainWnd);
		pParentWnd = (CMDIFrameWnd*)pMainWnd;
	}
	ASSERT(::IsWindow(pParentWnd->m_hWndMDIClient));

	// insure correct window positioning
	pParentWnd->RecalcLayout();

	// first copy into a CREATESTRUCT for PreCreate
	CREATESTRUCT cs;
	cs.dwExStyle = 0L;
	cs.lpszClass = lpszClassName;
	cs.lpszName = lpszWindowName;
	cs.style = dwStyle;
	cs.x = rect.left;
	cs.y = rect.top;
	cs.cx = rect.right - rect.left;
	cs.cy = rect.bottom - rect.top;
	cs.hwndParent = pParentWnd->m_hWnd;
	cs.hMenu = NULL;
	cs.hInstance = AfxGetInstanceHandle();
	cs.lpCreateParams = (LPVOID)pContext;

	if (!PreCreateWindow(cs))
	{
		PostNcDestroy();
		return FALSE;
	}
	// extended style must be zero for MDI Children (except under Win4)
#if  _MFC_VER < 0x0700
	ASSERT(afxData.bWin4 || cs.dwExStyle == 0);
#endif
	ASSERT(cs.hwndParent == pParentWnd->m_hWnd);    // must not change

	// now copy into a MDICREATESTRUCT for real create
	MDICREATESTRUCT mcs;
	mcs.szClass = cs.lpszClass;
	mcs.szTitle = cs.lpszName;
	mcs.hOwner = cs.hInstance;
	mcs.x = cs.x;
	mcs.y = cs.y;
	mcs.cx = cs.cx;
	mcs.cy = cs.cy;
	mcs.style = cs.style & ~(WS_MAXIMIZE | WS_VISIBLE);
	mcs.lParam = (LPARAM)cs.lpCreateParams;

	// create the window through the MDICLIENT window
	AfxHookWindowCreate(this);
	HWND hWnd = (HWND)::SendMessage(pParentWnd->m_hWndMDIClient,
		WM_MDICREATE, 0, (LPARAM)&mcs);
	if (!AfxUnhookWindowCreate())
		PostNcDestroy();        // cleanup if MDICREATE fails too soon

	if (hWnd == NULL)
		return FALSE;

	// special handling of visibility (always created invisible)
	if (cs.style & WS_VISIBLE)
	{
		// place the window on top in z-order before showing it
		::BringWindowToTop(hWnd);

		// show it as specified
		if (cs.style & WS_MINIMIZE)
			ShowWindow(SW_SHOWMINIMIZED);
		else if (cs.style & WS_MAXIMIZE)
			ShowWindow(SW_SHOWMAXIMIZED);
		else
			ShowWindow(SW_SHOWNORMAL);

		// make sure it is active (visibility == activation)
		if(IsDockableFrame())
		{
			((COXMDIFrameWndSizeDock*)pParentWnd)->MDIActivate(this);
		}
		else
		{
			pParentWnd->MDIActivate(this);
		}

		// refresh MDI Window menu
		::SendMessage(pParentWnd->m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
	}

#ifdef _MAC
	// force the size box to be visible
	ModifyStyleEx(0, WS_EX_FORCESIZEBOX);

	// if the window is already visible, we need to redraw the area covered by
	// the sizebox so that the sizebox is drawn
	if (IsWindowVisible())
	{
		RECT rc;
		GetClientRect(&rc);
		rc.left = rc.right - (GetSystemMetrics(SM_CXVSCROLL) - 1);
		rc.top = rc.bottom - (GetSystemMetrics(SM_CYHSCROLL) - 1);
		RedrawWindow(&rc, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
	}
#endif


	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if(pSysMenu)
	{
		OnAddSystemMenuItems(pSysMenu);
		ASSERT(hWnd == m_hWnd);
	}
	return TRUE;
}


void COXMDIChildWndSizeDock::OnAddSystemMenuItems(CMenu* pSysMenu)
{
	ASSERT(pSysMenu!=NULL);
	pSysMenu->AppendMenu(MF_SEPARATOR);
	pSysMenu->AppendMenu(m_bDockable ? MF_CHECKED : MF_UNCHECKED, 
		m_nDockMessageID, m_sDockMenuItem);
}

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

CMDIChildWnd* COXMDIChildWndSizeDock::MDIGetActive(BOOL* pbMaximized)
{
	CMDIFrameWnd* pFrameWnd = GetMDIFrame();
	CMDIChildWnd* pActiveWnd;
	if(IsDockableFrame())
	{
		pActiveWnd=((COXMDIFrameWndSizeDock*)pFrameWnd)->MDIGetActive(pbMaximized);
	}
	else
	{
		pActiveWnd=pFrameWnd->MDIGetActive(pbMaximized);
	}

	if(pActiveWnd!=NULL && !::IsWindow(pActiveWnd->m_hWnd))
	{
		pActiveWnd=NULL;
	}

	return pActiveWnd;
	
}

void COXMDIChildWndSizeDock::MDIDestroy()
{ 
	ASSERT(::IsWindow(m_hWnd));
	CMDIChildWnd::MDIDestroy();
}

void COXMDIChildWndSizeDock::MDIActivate()
{ 
	ASSERT(::IsWindow(m_hWnd));

	CMDIChildWnd::MDIActivate();
}

void COXMDIChildWndSizeDock::MDIMaximize()
{ 
	ASSERT(::IsWindow(m_hWnd)); 

	if(!IsDockable())
	{
		CMDIChildWnd::MDIMaximize();
	}
}

void COXMDIChildWndSizeDock::MDIRestore()
{ 
	ASSERT(::IsWindow(m_hWnd)); 

	if(!IsDockable())
	{
		CMDIChildWnd::MDIRestore();
	}
}

BOOL COXMDIChildWndSizeDock::OnCmdMsg(UINT nID, int nCode, void* pExtra,
									  AFX_CMDHANDLERINFO* pHandlerInfo)
{
	return CMDIChildWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

void COXMDIChildWndSizeDock::ActivateFrame(int nCmdShow)
{
	BOOL bVisibleThen = (GetStyle() & WS_VISIBLE) != 0;
	CMDIFrameWnd* pFrameWnd = GetMDIFrame();
	ASSERT_VALID(pFrameWnd);

	// determine default show command
	if (nCmdShow == -1)
	{
		// get maximized state of frame window (previously active child)
		BOOL bMaximized;
		if(IsDockableFrame())
		{
			((COXMDIFrameWndSizeDock*)pFrameWnd)->MDIGetActive(&bMaximized);
		}
		else
		{
			pFrameWnd->MDIGetActive(&bMaximized);
		}

		// convert show command based on current style
		DWORD dwStyle = GetStyle();
		if (bMaximized || (dwStyle & WS_MAXIMIZE))
			nCmdShow = SW_SHOWMAXIMIZED;
		else if (dwStyle & WS_MINIMIZE)
			nCmdShow = SW_SHOWMINIMIZED;
	}

	// finally, show the window
	CFrameWnd::ActivateFrame(nCmdShow);

	// update the Window menu to reflect new child window
	CMDIFrameWnd* pFrame = GetMDIFrame();
	::SendMessage(pFrame->m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);

	// Note: Update the m_bPseudoInactive flag.  This is used to handle the
	//  last MDI child getting hidden.  Windows provides no way to deactivate
	//  an MDI child window.

	BOOL bVisibleNow = (GetStyle() & WS_VISIBLE) != 0;
	if (bVisibleNow == bVisibleThen)
		return;

	////////////////////////////////////
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	//
	// probably have to rewrite
	//
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	////////////////////////////////////
	if (!bVisibleNow)
	{
		// get current active window according to Windows MDI
		HWND hWnd = (HWND)::SendMessage(pFrameWnd->m_hWndMDIClient,
			WM_MDIGETACTIVE, 0, 0);
		if (hWnd != m_hWnd)
		{
			// not active any more -- window must have been deactivated
			ASSERT(!m_bPseudoInactive);
			return;
		}

		// check next window
		ASSERT(hWnd != NULL);
		pFrameWnd->MDINext();

		// see if it has been deactivated now...
		hWnd = (HWND)::SendMessage(pFrameWnd->m_hWndMDIClient,
			WM_MDIGETACTIVE, 0, 0);
		if (hWnd == m_hWnd)
		{
			// still active -- fake deactivate it
			ASSERT(hWnd != NULL);
			OnMDIActivate(FALSE, NULL, this);
			m_bPseudoInactive = TRUE;   // so MDIGetActive returns NULL
		}
	}
	else if (m_bPseudoInactive)
	{
		// if state transitioned from not visible to visible, but
		//  was pseudo deactivated -- send activate notify now
		OnMDIActivate(TRUE, this, NULL);
		ASSERT(!m_bPseudoInactive); // should get set in OnMDIActivate!
	}
}

BOOL COXMDIChildWndSizeDock::PreTranslateMessage(MSG* pMsg)
{
	// check for special cancel modes for combo boxes
	if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_NCLBUTTONDOWN)
		AfxCancelModes(pMsg->hwnd);    // filter clicks

	// allow tooltip messages to be filtered
	if (CWnd::PreTranslateMessage(pMsg))
		return TRUE;

	// we can't call 'CFrameWnd::PreTranslate' since it will translate
	//  accelerators in the context of the MDI Child - but since MDI Child
	//  windows don't have menus this doesn't work properly.  MDI Child
	//  accelerators must be translated in context of their MDI Frame.

	if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
	{
		// use document specific accelerator table over m_hAccelTable
		HACCEL hAccel = GetDefaultAccelerator();
		return hAccel != NULL &&
		   ::TranslateAccelerator(GetMDIFrame()->m_hWnd, hAccel, pMsg);
	}
	return FALSE;
}

void COXMDIChildWndSizeDock::OnSysCommand(UINT nID, LPARAM lParam)
{
	if(nID==m_nDockMessageID)
	{
		OnMakeItDockable();
	}
	else
	{
		CMDIChildWnd::OnSysCommand(nID, lParam);
	}
}

BOOL COXMDIChildWndSizeDock::UpdateClientEdge(LPRECT lpRect)
{
#if  _MFC_VER < 0x0700
	if (!afxData.bWin4)
		return FALSE;
#endif

	// only adjust for active MDI child window
	CMDIFrameWnd* pFrameWnd = GetMDIFrame();
	CMDIChildWnd* pChild=MDIGetActive();
	if (pChild == NULL || pChild == this)
	{
		// need to adjust the client edge style as max/restore happens
		LONG_PTR dwStyle = ::GetWindowLongPtr(pFrameWnd->m_hWndMDIClient, GWL_EXSTYLE);
		LONG_PTR dwNewStyle = dwStyle;
		if (pChild != NULL && !(GetExStyle() & WS_EX_CLIENTEDGE) &&
		  (GetStyle() & WS_MAXIMIZE))
			dwNewStyle &= ~(WS_EX_CLIENTEDGE);
		else
			dwNewStyle |= WS_EX_CLIENTEDGE;

		if (dwStyle != dwNewStyle)
		{
			// SetWindowPos will not move invalid bits
			::RedrawWindow(pFrameWnd->m_hWndMDIClient, NULL, NULL,
				RDW_INVALIDATE | RDW_ALLCHILDREN);

			// remove/add WS_EX_CLIENTEDGE to MDI client area
			::SetWindowLongPtr(pFrameWnd->m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle);
			::SetWindowPos(pFrameWnd->m_hWndMDIClient, NULL, 0, 0, 0, 0,
				SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE |
				SWP_NOZORDER | SWP_NOCOPYBITS);

			// return new client area
			if (lpRect != NULL)
				::GetClientRect(pFrameWnd->m_hWndMDIClient, lpRect);
			return TRUE;
		}
	}
	return FALSE;
}

BOOL COXMDIChildWndSizeDock::DestroyWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	
	if (m_hWnd == NULL)
		return FALSE;

	m_bBeingDestroyed=TRUE;

	if(::IsWindow(m_dockBar.m_hWnd) && !m_dockBar.IsBeingDestroyed())
	{
		m_dockBar.DestroyWindow();
	} 

	// avoid changing the caption during the destroy message(s)
	CMDIFrameWnd* pFrameWnd = GetMDIFrame();
	HWND hWndFrame = pFrameWnd->m_hWnd;
	ASSERT(::IsWindow(hWndFrame));
	LONG_PTR dwStyle = SetWindowLongPtr(hWndFrame, GWL_STYLE,
		GetWindowLongPtr(hWndFrame, GWL_STYLE) & ~FWS_ADDTOTITLE);

	ASSERT(m_pViewActive==NULL || ::IsWindow(m_pViewActive->m_hWnd));

	pFrameWnd->SetActiveView(NULL);
	MDIDestroy();

	if (::IsWindow(hWndFrame))
	{
		ASSERT(hWndFrame == pFrameWnd->m_hWnd);
		SetWindowLongPtr(hWndFrame, GWL_STYLE, dwStyle);
		pFrameWnd->OnUpdateFrameTitle(TRUE);
	}

	TRACE(_T("ChildWindow destroyed\n"));
	return TRUE;
}

void COXMDIChildWndSizeDock::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, 
										   CWnd* pDeactivateWnd) 
{
	CMDIChildWnd::OnMDIActivate(bActivate,pActivateWnd,pDeactivateWnd);
	
	// TODO: Add your message handler code here
}

BOOL COXMDIChildWndSizeDock::OnNcActivate(BOOL bActive) 
{
	// TODO: Add your message handler code here and/or call default

	// I've got some doubts
	return CMDIChildWnd::OnNcActivate(bActive);
}

void COXMDIChildWndSizeDock::OnNcRButtonDown(UINT nHitTest, CPoint point)
{
	CMDIChildWnd::OnNcRButtonDown(nHitTest,point);

	if(nHitTest==HTCAPTION && GetSystemMenu(FALSE)==NULL)
	{
		OnContextMenu(this,point);
	}
}

int COXMDIChildWndSizeDock::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
{
	// TODO: Add your message handler code here and/or call default

	int nResult = CMDIChildWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
	return nResult;
}

void COXMDIChildWndSizeDock::OnStyleChanging(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
{
	if(m_bDockable && nStyleType&GWL_STYLE && lpStyleStruct->styleNew&WS_VISIBLE)
	{
		lpStyleStruct->styleNew&=~WS_VISIBLE;
	}
}

LPARAM COXMDIChildWndSizeDock::OnSetText(UINT wParam, LONG lParam)
{
	// TODO: Add your specialized code here and/or call the base class

	if(m_bDockable)
	{
		if(::IsWindow(m_dockBar.m_hWnd))
		{
			m_dockBar.SendMessage(WM_SETTEXT,wParam,lParam);
		}
	}
	return Default();
}


void COXMDIChildWndSizeDock::OnClose() 
{
	if (m_lpfnCloseProc != NULL && !(*m_lpfnCloseProc)(this))
		return;

	if(m_bBeingDestroyed)
	{
		return;
	}

	m_bBeingDestroyed=TRUE;

	// Note: only queries the active document
	ASSERT(m_pViewActive==NULL || ::IsWindow(m_pViewActive->m_hWnd));
	CDocument* pDocument = GetActiveDocument();
	if(pDocument != NULL)
	{
		if(!pDocument->CanCloseFrame(this))
		{
			// document can't close right now -- don't close it
			m_bBeingDestroyed=FALSE;
			return;
		}
	}

	// detect the case that this is the last frame on the document and
	// shut down with OnCloseDocument instead.
	if(pDocument!=NULL && pDocument->m_bAutoDelete)
	{
		BOOL bOtherFrame = FALSE;
		POSITION pos = pDocument->GetFirstViewPosition();
		while (pos != NULL)
		{
			CView* pView = pDocument->GetNextView(pos);
			ASSERT_VALID(pView);
			if (pView->GetParentFrame() != this)
			{
				bOtherFrame = TRUE;
				break;
			}
		}
		if (!bOtherFrame)
		{
			pDocument->OnCloseDocument();
			return;
		}

		// allow the document to cleanup before the window is destroyed
		pDocument->PreCloseFrame(this);
	}

	// then destroy the window
	DestroyWindow();
}

void COXMDIChildWndSizeDock::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	UNREFERENCED_PARAMETER(pWnd);

	CMenu menu;
	if (menu.CreatePopupMenu())
	{
		OnAddContextMenuItems(menu.m_hMenu);
		menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
	}
}

void COXMDIChildWndSizeDock::OnAddContextMenuItems(HMENU hMenu)
{
	CMenu Menu;
	Menu.Attach(hMenu);
	
	Menu.AppendMenu(m_bDockable ? MF_CHECKED : MF_UNCHECKED, 
		m_nDockMessageID, m_sDockMenuItem);

	Menu.Detach();	// detatch MFC object
}

void COXMDIChildWndSizeDock::OnMakeItDockable() 
{
	// TODO: Add your command handler code here
	MakeItDockable(!m_bDockable);
}

void COXMDIChildWndSizeDock::OnUpdateFrameTitle(BOOL bAddToTitle)
{
	// update our parent window first
	GetMDIFrame()->OnUpdateFrameTitle(bAddToTitle);

	if ((GetStyle() & FWS_ADDTOTITLE) == 0)
		return;     // leave child window alone!

	CDocument* pDocument = GetActiveDocument();
	if (bAddToTitle && pDocument != NULL)
	{
		TCHAR szText[256+_MAX_PATH];
		lstrcpy(szText, pDocument->GetTitle());
		if (m_nWindow > 0)
			wsprintf(szText + lstrlen(szText), _T(":%d"), m_nWindow);

		// set title if changed, but don't remove completely
		AfxSetWindowText(m_hWnd, szText);

		if(m_bDockable)
		{
			if(::IsWindow(m_dockBar.m_hWnd))
			{
				m_dockBar.SetWindowText(szText);
			}
		}
	}
}

void COXMDIChildWndSizeDock::OnParentNotify(UINT message, LPARAM lParam)
{
	if(LOWORD(message)==WM_DESTROY)
	{
		CWnd* pWnd=FromHandle((HWND)lParam);
		if(pWnd->IsKindOf(RUNTIME_CLASS(CView)) && 
			!pWnd->IsKindOf(RUNTIME_CLASS(CPreviewView)))
		{
			SetActiveView(NULL);
			GetMDIFrame()->SetActiveView(NULL);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// COXSizeViewBar frame
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////


IMPLEMENT_DYNAMIC(COXSizeViewBar, COXSizeControlBar)

/////////////////////////////////////////////////////////////////////////////
// Definition of static members

// Data members -------------------------------------------------------------
// protected:

// private:
	
// Member functions ---------------------------------------------------------
// public:

COXSizeViewBar::COXSizeViewBar(int nStyle) : COXSizeControlBar(nStyle)
{
	m_pChildWnd=NULL;
	m_pView=NULL;

	m_bBeingDestroyed=FALSE;
}

COXSizeViewBar::~COXSizeViewBar()
{
}


BEGIN_MESSAGE_MAP(COXSizeViewBar, COXSizeControlBar)
	//{{AFX_MSG_MAP(COXSizeViewBar)
	ON_WM_NCACTIVATE()
	ON_WM_DESTROY()
	ON_WM_NCDESTROY()
	ON_WM_CONTEXTMENU()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_SETTEXT,OnSetText)
	ON_MESSAGE(WM_ADDCONTEXTMENUITEMS, OnAddContextMenuItems)
	ON_MESSAGE(WM_ACTIVATEVIEWBAR,OnActivateViewBar)
END_MESSAGE_MAP()


void COXSizeViewBar::OnSizedOrDocked(int cx, int cy, BOOL bFloating, int flags)
{
	COXSizeControlBar::OnSizedOrDocked(cx, cy, bFloating, flags);

	if(::IsWindow(m_pChildWnd->m_hWnd) && m_pChildWnd->IsDockable())
	{
		ASSERT(::IsWindow(m_pView->m_hWnd));

		CRect rect;
		if(bFloating)
		{
			m_WrapperWnd.UnwrapView();
			GetDockingFrame()->RecalcLayout();
			GetClientRect(&rect);
		}
		else
		{
			m_WrapperWnd.WrapView(this,m_pView);
			m_WrapperWnd.GetClientRect(&rect);
		}
		m_pView->MoveWindow(&rect);

		if(m_pChildWnd==m_pChildWnd->MDIGetActive(&m_bMaximized) && m_pView!=NULL)
		{
			m_pView->SetFocus();
		}

	}
}

BOOL COXSizeViewBar::AttachMDIChild(COXMDIChildWndSizeDock* pWnd, DWORD dock, bool dockToSide)
{
	ASSERT(pWnd->IsKindOf(RUNTIME_CLASS(COXMDIChildWndSizeDock)));
	m_pChildWnd=pWnd;
	m_pView=m_pChildWnd->GetActiveView();
	
	if(m_pView==NULL)
	{
		return FALSE;
	}

	CMDIFrameWnd* pFrame=(CMDIFrameWnd*)m_pChildWnd->GetMDIFrame();
	ASSERT_KINDOF(CMDIFrameWnd, pFrame);

	BOOL bFirstTime=FALSE;
	if(!::IsWindow(m_hWnd))
	{
		if(!Create(pFrame,_T("")))   
		{
			return FALSE;
		}
		EnableDocking(m_pChildWnd->m_dwDockStyle);
		ShowWindow(SW_HIDE);

		bFirstTime=TRUE;
	}

	CString sWindowText;
	m_pChildWnd->GetWindowText(sWindowText);
	SetWindowText(sWindowText);

	CWnd* pPrevParent=m_pView->SetParent(this);
	ASSERT(pPrevParent!=NULL);

	m_bMaximized=FALSE;
	if(m_pChildWnd==m_pChildWnd->MDIGetActive(&m_bMaximized))
	{
		if(m_bMaximized && m_pChildWnd->IsDockableFrame())
		{
			((COXMDIFrameWndSizeDock*)pFrame)->MDINext();
			m_pChildWnd->ShowWindow(SW_HIDE);
			m_pChildWnd->MDIRestore();
			m_pChildWnd->ShowWindow(SW_HIDE);
		}

		BOOL bOldDockable=m_pChildWnd->m_bDockable;
		m_pChildWnd->m_bDockable=TRUE;
		m_pChildWnd->MDIActivate();
		m_pChildWnd->m_bDockable=bOldDockable;
	}

	m_pChildWnd->ShowWindow(SW_HIDE);

	if(bFirstTime)
	{
		ShowWindow(SW_SHOWNA);
		UINT nDockBarID=0;

		if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_TOP && dock == CBRS_ALIGN_TOP)
			nDockBarID=AFX_IDW_DOCKBAR_TOP;
		else if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_BOTTOM && dock == CBRS_ALIGN_BOTTOM)
			nDockBarID=AFX_IDW_DOCKBAR_BOTTOM;
		else if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_LEFT && dock == CBRS_ALIGN_LEFT)
			nDockBarID=AFX_IDW_DOCKBAR_LEFT;
		else if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_RIGHT && dock == CBRS_ALIGN_RIGHT)
			nDockBarID=AFX_IDW_DOCKBAR_RIGHT;

		// The older code would allow users to specify the side by setting the style, so still allow that
		if (!nDockBarID)
		{
		if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_TOP)
			nDockBarID=AFX_IDW_DOCKBAR_TOP;
		else if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_BOTTOM)
			nDockBarID=AFX_IDW_DOCKBAR_BOTTOM;
		else if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_LEFT)
			nDockBarID=AFX_IDW_DOCKBAR_LEFT;
		else if(m_pChildWnd->m_dwDockStyle & CBRS_ALIGN_RIGHT)
			nDockBarID=AFX_IDW_DOCKBAR_RIGHT;
		}
	
		POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
		CDockBar* pDockBar = NULL;

		if (dockToSide)
		{
			while (pos != NULL)
			{
				pDockBar = (CDockBar*)pFrame->m_listControlBars.GetNext(pos);
			}
		}
		
		if (pDockBar)
		{
			CRect rcDock;
			pDockBar->GetWindowRect(&rcDock);
			rcDock.OffsetRect(1, 1);
			pFrame->DockControlBar(this,nDockBarID, rcDock);
		}
		else
		{
        		pFrame->DockControlBar(this,nDockBarID);
        	}
	}
	else
	{
		pFrame->ShowControlBar(this, (GetStyle() & WS_VISIBLE) == 0, TRUE);
		pFrame->RecalcLayout();

		CRect rect;
		GetWindowRect(rect);
		BOOL bOldDockable=m_pChildWnd->m_bDockable;
		m_pChildWnd->m_bDockable=TRUE;
		OnSizedOrDocked(rect.Width(),rect.Height(),IsFloating(),2);
		m_pChildWnd->m_bDockable=bOldDockable;
	}

	// refresh MDI Window menu
	::SendMessage(pFrame->m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);

	return TRUE;
}

BOOL COXSizeViewBar::DetachMDIChild(BOOL bRedraw)
{
	if(::IsWindow(m_pChildWnd->m_hWnd) && m_pChildWnd->IsDockable() &&
		m_pChildWnd->IsDockableFrame())
	{
		COXMDIFrameWndSizeDock* pFrame=(COXMDIFrameWndSizeDock*)m_pChildWnd->GetMDIFrame();
		ASSERT_KINDOF(COXMDIFrameWndSizeDock, pFrame);
		
		if(!IsFloating() && ::IsWindow(m_WrapperWnd.m_hWnd) && 
			!m_WrapperWnd.IsBeingDestroyed())
		{
			m_WrapperWnd.UnwrapView();
		}

		CWnd* pPrevParent=m_pView->SetParent(m_pChildWnd);
		ASSERT(pPrevParent!=NULL);

		pFrame->SetActiveView(NULL);
		m_pChildWnd->SetActiveView(m_pView);

		if(bRedraw)
		{
			pFrame->ShowControlBar(this, (GetStyle() & WS_VISIBLE) == 0, FALSE);
			pFrame->RecalcLayout();
		}

		if(m_pChildWnd==m_pChildWnd->MDIGetActive())
		{
			BOOL bOldDockable=m_pChildWnd->m_bDockable;
			m_pChildWnd->m_bDockable=FALSE;
			m_pChildWnd->MDIActivate();
			if(m_bMaximized || pFrame->IsFrontChildMaximized())
			{
				m_pChildWnd->MDIMaximize();
			}
			m_pChildWnd->m_bDockable=bOldDockable;

			CRect rect;
			m_pChildWnd->GetClientRect(rect);
			m_pView->MoveWindow(&rect);
		}

		if(bRedraw)
		{
			m_pChildWnd->ShowWindow(SW_SHOW);
		}

		// refresh MDI Window menu
		::SendMessage(pFrame->m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);

		return TRUE;
	}

	return FALSE;
}

LONG COXSizeViewBar::OnActivateViewBar(UINT wParam, LONG lParam)
{
	BOOL bActive=wParam;

	switch(lParam)
	{
	case ID_SOURCE_MDICHILD:
		{
			if(::IsWindow(m_pChildWnd->m_hWnd) && m_pChildWnd->IsDockable())
			{
				if(!IsFloating())
				{
					if(::IsWindow(m_WrapperWnd.m_hWnd))
					{
						m_WrapperWnd.SendMessage(WM_NCACTIVATE,bActive);
					}
				}
				else
				{
					CFrameWnd* pFrame=GetParentFrame();
					if(pFrame!=NULL && 
						pFrame->IsKindOf(RUNTIME_CLASS(COXSizableMiniDockFrameWnd)))
					{
						pFrame->SendMessage(WM_NCACTIVATE,FALSE);
						pFrame->SendMessage(WM_FLOATSTATUS,
							bActive ? FS_ACTIVATE : FS_DEACTIVATE);
					}
				}
			}
			break;
		}
	case ID_SOURCE_BARWRAPPER:
	case ID_SOURCE_MINIDOCK:
		{
			if(::IsWindow(m_pChildWnd->m_hWnd) && m_pChildWnd->IsDockable())
			{
				// This was causing a bug, not sure why it was here.
/*				if(bActive && m_pChildWnd->IsDockableFrame())
				{
					COXMDIFrameWndSizeDock* pFrame=
						(COXMDIFrameWndSizeDock*)m_pChildWnd->GetMDIFrame();
					if(pFrame->MDIGetActive()!=m_pChildWnd)
					{
						m_pChildWnd->MDIActivate();
					}
				}
*/
				if(bActive && m_pChildWnd->IsDockable() && m_pView!=NULL && 
					::IsWindow(m_pView->GetSafeHwnd()))
				{
					m_pView->SetFocus();
				}
			}
			break;
		}
	}

	SetActive(bActive);

	return TRUE;
}

BOOL COXSizeViewBar::OnNcActivate(BOOL bActive) 
{
	// TODO: Add your message handler code here and/or call default

	return COXSizeControlBar::OnNcActivate(bActive);
}

void COXSizeViewBar::OnDestroy() 
{
	m_bBeingDestroyed=TRUE;

	COXSizeControlBar::OnDestroy();

	// TODO: Add your message handler code here
	
	if(::IsWindow(m_pChildWnd->m_hWnd) && m_pChildWnd->IsDockable())
	{
		DetachMDIChild(FALSE);
	}
}

void COXSizeViewBar::OnNcDestroy() 
{
	m_bBeingDestroyed=TRUE;

	COXSizeControlBar::OnNcDestroy();
	
	// TODO: Add your message handler code here
	
	if(::IsWindow(m_WrapperWnd.m_hWnd) && !m_WrapperWnd.IsBeingDestroyed())
	{
		m_WrapperWnd.DestroyWindow();
	}

	if(::IsWindow(m_pChildWnd->m_hWnd))
	{
		if(!m_pChildWnd->IsBeingDestroyed() && m_pChildWnd->IsDockable())
		{
			m_pChildWnd->PostMessage(WM_CLOSE);
		}
		else
		{
			m_pChildWnd->GetMDIFrame()->SetActiveView(NULL);
		}
	}
	TRACE(_T("ViewBarWindow destroyed\n"));
}

void COXSizeViewBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
	// don't call the default implementation that resets the 
	// active/inactive state for control bar. In the case with this window
	// it is being managed independently
	UpdateDialogControls(pTarget, bDisableIfNoHndler);
}

LONG COXSizeViewBar::OnAddContextMenuItems(WPARAM wParam, LPARAM lParam)
{
	ASSERT(::IsWindow(m_pChildWnd->m_hWnd));

	UNREFERENCED_PARAMETER(wParam);

	m_pChildWnd->OnAddContextMenuItems((HMENU)lParam);

	return TRUE;
}

LPARAM COXSizeViewBar::OnSetText(UINT wParam, LONG lParam)
{
	// TODO: Add your specialized code here and/or call the base class

	if(!IsFloating())
	{
		if(::IsWindow(m_WrapperWnd.m_hWnd))
		{
			m_WrapperWnd.SendMessage(WM_SETTEXT,wParam,lParam);
		}
	}
	else
	{
		CFrameWnd* pFrame=GetParentFrame();
		ASSERT_KINDOF(CMiniDockFrameWnd,pFrame);
		pFrame->SendMessage(WM_SETTEXT,wParam,lParam);
	}

	return Default();
}

// Now run off WM_CONTEXTMENU: if user wants standard handling, then let him have it
void COXSizeViewBar::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	if (m_Style & SZBARF_STDMOUSECLICKS)
	{
		CMenu menu;
		if (menu.CreatePopupMenu())
		{
			OnAddContextMenuItems(0, (LPARAM)menu.m_hMenu);
			menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
		}
	} 
	else
	{
		CControlBar::OnContextMenu(pWnd, point);
	}
}

BOOL COXSizeViewBar::QueryCloseView()
{
	if(::IsWindow(GetSafeHwnd()) && ::IsWindow(m_pView->GetSafeHwnd())
		 && ::IsWindow(m_pChildWnd->GetSafeHwnd()))	
	{
		CDocument* pDocument = m_pView->GetDocument();
		if(pDocument != NULL)
		{
			if(!pDocument->CanCloseFrame(m_pChildWnd))
			{
				// document can't close right now -- don't close it
				return FALSE;
			}
		}
	}

	return TRUE;
}

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


COXSizeBarWrapper::COXSizeBarWrapper()
{
	m_pParentWnd=NULL;
	m_pView=NULL;

	m_bBeingDestroyed=FALSE;
}

COXSizeBarWrapper::~COXSizeBarWrapper()
{
}


BEGIN_MESSAGE_MAP(COXSizeBarWrapper, CWnd)
	//{{AFX_MSG_MAP(COXSizeBarWrapper)
	ON_WM_NCHITTEST()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MOUSEACTIVATE()
	ON_WM_DESTROY()
	ON_WM_NCDESTROY()
	ON_WM_CLOSE()
	ON_WM_NCACTIVATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()



BOOL COXSizeBarWrapper::Create(COXSizeViewBar* pParentWnd)
{
	ASSERT_VALID(pParentWnd);
    ASSERT(::IsWindow(pParentWnd->GetSafeHwnd()));

	m_pParentWnd=pParentWnd;

	WNDCLASS wndClass;
	wndClass.style=CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; 
    wndClass.lpfnWndProc=AfxWndProc; 
    wndClass.cbClsExtra=0; 
    wndClass.cbWndExtra=0; 
    wndClass.hInstance=AfxGetInstanceHandle(); 
    wndClass.hIcon=0; 
    wndClass.hCursor=::LoadCursor(NULL,IDC_ARROW); 
    wndClass.hbrBackground=0; 
    wndClass.lpszMenuName=NULL; 
	wndClass.lpszClassName=_T("MDIChildWndDockWrapper");
	
	if(!AfxRegisterClass(&wndClass))
	{
		return FALSE;
	}

	CRect rect;
	m_pParentWnd->GetClientRect(rect);
	rect.OffsetRect(-rect.TopLeft());
	CString sWindowText;
	m_pParentWnd->GetWindowText(sWindowText);

    if(!CWnd::CreateEx(/*WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE*/0,wndClass.lpszClassName, 
		sWindowText,WS_CHILD|/*WS_BORDER|WS_DLGFRAME|WS_SYSMENU|*/WS_VISIBLE/*|WS_OVERLAPPED|0x00008000*/, 
		rect,m_pParentWnd,0,NULL))
	{
        return FALSE;
	}

	SendMessage(WM_NCACTIVATE,TRUE);

    return TRUE;
}

void COXSizeBarWrapper::WrapView(COXSizeViewBar* pParentWnd, CView* pView)
{
	ASSERT(::IsWindow(pParentWnd->m_hWnd));
	ASSERT(::IsWindow(pView->m_hWnd));

	if(!::IsWindow(m_hWnd))
	{
	    if(!Create(pParentWnd))
		{
			AfxThrowMemoryException();
		}
	}

	m_pView=pView;

	CRect rect;
	pParentWnd->GetClientRect(rect);
	rect.OffsetRect(-rect.TopLeft());

	CWnd* pPrevParent=m_pView->SetParent(this);
	ASSERT(pPrevParent!=NULL);

	SetWindowPos(NULL,rect.left,rect.top,rect.Width(),rect.Height(),SWP_NOZORDER);
	ShowWindow(SW_SHOW);
	UpdateWindow();
}

void COXSizeBarWrapper::UnwrapView()
{
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(::IsWindow(m_pParentWnd->m_hWnd));
	if(::IsWindow(m_pView->m_hWnd))
	{
		CWnd* pPrevParent=m_pView->SetParent(m_pParentWnd);
		ASSERT(pPrevParent!=NULL);
		ShowWindow(SW_HIDE);
	}
}

///////////////////////////////////////////////////////////////
#if _MSC_VER >= 1400
LRESULT COXSizeBarWrapper::OnNcHitTest(CPoint point)
#else
UINT COXSizeBarWrapper::OnNcHitTest(CPoint point)
#endif
{
#if _MSC_VER >= 1400
	LRESULT nHitTest=CWnd::OnNcHitTest(point);
#else
	UINT nHitTest=CWnd::OnNcHitTest(point);
#endif
	// TODO: Add your message handler code here and/or call default

	switch(nHitTest)
	{
	case HTCAPTION:
	case HTCLIENT:
		{
			ASSERT(::IsWindow(m_pParentWnd->GetSafeHwnd()));
			ClientToScreen(&point);
			m_pParentWnd->ScreenToClient(&point);
			nHitTest=m_pParentWnd->SendMessage(WM_NCHITTEST,0, 
				MAKELONG(point.x,point.y));
		}
	}

	return nHitTest;
}


void COXSizeBarWrapper::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	ASSERT(::IsWindow(m_pParentWnd->GetSafeHwnd()));

	ClientToScreen(&point);
	m_pParentWnd->ScreenToClient(&point);
	m_pParentWnd->SendMessage(WM_LBUTTONDOWN,nFlags,MAKELONG(point.x,point.y));
}

void COXSizeBarWrapper::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	ASSERT(::IsWindow(m_pParentWnd->GetSafeHwnd()));
	m_pParentWnd->SendMessage(WM_LBUTTONDBLCLK,nFlags,MAKELONG(point.x,point.y));
}

int COXSizeBarWrapper::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
{
	// TODO: Add your message handler code here and/or call default
	
	ASSERT(::IsWindow(m_pParentWnd->GetSafeHwnd()));
	int nResult = CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
	if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT)
		return nResult;   // window does not want to activate

	// activate this window if necessary
	m_pParentWnd->SendMessage(WM_ACTIVATEVIEWBAR,TRUE,ID_SOURCE_BARWRAPPER);

	return nResult;
}

void COXSizeBarWrapper::OnDestroy() 
{
	m_bBeingDestroyed=TRUE;

	CWnd::OnDestroy();
	
	// TODO: Add your message handler code here
	
	if(::IsWindow(m_pParentWnd->GetSafeHwnd()) && !m_pParentWnd->IsBeingDestroyed())	
	{
		ASSERT_KINDOF(COXSizeViewBar,m_pParentWnd);
		if(!m_pParentWnd->IsFloating())
		{
			UnwrapView();
		}
	}
}

void COXSizeBarWrapper::OnNcDestroy() 
{
	m_bBeingDestroyed=TRUE;

	CWnd* pChild=GetWindow(GW_CHILD);
	ASSERT(pChild==NULL);

	CWnd::OnNcDestroy();
	
	// TODO: Add your message handler code here
	
	if(::IsWindow(m_pParentWnd->GetSafeHwnd()) && !m_pParentWnd->IsBeingDestroyed())	
	{
		ASSERT_KINDOF(COXSizeViewBar,m_pParentWnd);
		m_pParentWnd->DestroyWindow();
	}
	TRACE(_T("WrapperWindow destroyed\n"));
}


void COXSizeBarWrapper::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	
	m_bBeingDestroyed=TRUE;

	if(::IsWindow(m_pParentWnd->GetSafeHwnd()) && !m_pParentWnd->IsBeingDestroyed())	
	{
		if(!m_pParentWnd->QueryCloseView())
		{
			// document can't close right now -- don't close it
			m_bBeingDestroyed=FALSE;
			return;
		}
	}

	CWnd::OnClose();
}

BOOL COXSizeBarWrapper::OnNcActivate(BOOL bActive) 
{
	// TODO: Add your message handler code here and/or call default
	
	if(::IsWindow(m_pParentWnd->GetSafeHwnd()))	
	{
		COXMDIChildWndSizeDock* pMDIChild=m_pParentWnd->m_pChildWnd;
		if(::IsWindow(pMDIChild->m_hWnd))
		{
			if(pMDIChild->MDIGetActive()!=pMDIChild && bActive)
			{
				return FALSE;
			}
			else
			{
				return PtrToInt(Default());
			}
		}
	}

	return PtrToInt(CWnd::OnNcActivate(bActive));
}

/////////////////////////////////////////////////////////////////////////////
// CDocument

BEGIN_MESSAGE_MAP(COXDockDocument, CDocument)
	//{{AFX_MSG_MAP(COXDockDocument)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNAMIC(COXDockDocument, CDocument)






