// ======================================================================================== // 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 #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; nIndexm_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; nIndexModifyStyle(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)