Click here to Skip to main content
11,432,627 members (65,110 online)
Click here to Skip to main content
Add your own
alternative version

The Ultimate Toolbox - Updates and User Contributions

, 12 Feb 2013 CPOL
Updates and User Contributions for the Ultimate Toolbox Libraries
OutlookDemoUpdate.zip
Ultimate Grid
Demos
OutlookStyle
OutlookStyle.aps
OutlookStyle.dsp
OutlookStyle.dsw
OutlookStyle.suo
res
bitmap1.bmp
bmattach.bmp
bmp00001.bmp
bmp00002.bmp
bmp00003.bmp
Flags.bmp
OutlookStyle.ico
OutlookStyleDoc.ico
Toolbar.bmp
toolbar1.bmp
toolbar2.bmp
toolbarf.bmp
UltimateGrid72_Src_Update01.zip
CellTypes
Include
Source
UltimateGrid72_Src_Update02.zip
DataSources
ODBC
OleDB
EditControls
UltimateGrid72_Src_Update03.zip
UltimateGrid72_Src_Update04.zip
UltimateGrid73_src.zip
BuildDLL
Build DLL.dsp
Build DLL.dsw
res
BuildLib
ugmfclib.dsp
ugmfclib.dsw
Lib
Skel
UltimateTCP-IP42_Src_Update01.zip
Ultimate TCP-IP
Include
Security
Include
Source
source
UltimateTCP-IP42_Src_Update02.zip
Examples
Client
Mail
icon1.ico
icon2.ico
MailClientS.suo
test.dsp
test.dsw
UltimateTCP-IP42_Src_Update03.zip
ultimatetoolbox93_src_update01.zip
Ultimate Toolbox
include
source
UltimateToolbox93_Src_Update02.zip
lib
Build DLLs
Build Libs
UltimateToolbox93_Src_Update03.zip
UltimateToolbox93_Src_Update04.zip
UltimateToolbox93_Src_Update05.zip
// ========================================================================================
// 							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

// v93 update 03 - 64-bit - moved here from below
#include "UTB64Bit.h"

#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;
	}
}

// v9.3 - update 03 - 64-bit - changed these to LRESULT, WPARAM, LPARAM from LPARAM, UINT, LONG
LRESULT COXMDIChildWndSizeDock::OnSetText(WPARAM wParam, LPARAM 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;
}

// v9.3 - update 03 - 64-bit - changed these to LRESULT, WPARAM, LPARAM from LPARAM, UINT, LONG
LRESULT COXSizeViewBar::OnActivateViewBar(WPARAM wParam, LPARAM lParam)
{
	// v9.3 - update 03 - 64-bit - added (BOOL) cast
	BOOL bActive=(BOOL)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);
}

// v9.3 - update 03 - 64-bit - changed ret type from LONG to LRESULT
LRESULT COXSizeViewBar::OnAddContextMenuItems(WPARAM wParam, LPARAM lParam)
{
	ASSERT(::IsWindow(m_pChildWnd->m_hWnd));

	UNREFERENCED_PARAMETER(wParam);

	m_pChildWnd->OnAddContextMenuItems((HMENU)lParam);

	return TRUE;
}

// v9.3 - update 03 - 64-bit - changed these to LRESULT, WPARAM, LPARAM from LPARAM, UINT, LONG
LRESULT COXSizeViewBar::OnSetText(WPARAM wParam, LPARAM 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)






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)

Share

About the Author

The Ultimate Toolbox
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.
Group type: Organisation

402 members


| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150428.2 | Last Updated 13 Feb 2013
Article Copyright 2008 by The Ultimate Toolbox
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid