2025-11-27 16:46:48 +09:00

3192 lines
82 KiB
C++

// ========================================================================================
// 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)