Click here to Skip to main content
15,886,362 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox - Updates and User Contributions

Rate me:
Please Sign up or sign in to vote.
4.79/5 (26 votes)
12 Feb 2013CPOL8 min read 254.8K   23.7K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
// ===================================================================================
// 					Class Implementation : COXDragDockContext
// ===================================================================================

// Header file : OXDragDockContext.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"
#include <afxpriv.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


#include "OXDragDockContext.h"
#include "OXMainRes.h"  // for some resource strings

#include "OXSizeCtrlBar.h"
#include "OXSizeDockBar.h"
#include "OXMDIFloatWnd.h"

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

#define new DEBUG_NEW

#define HORZF(dw) (dw & CBRS_ORIENT_HORZ)
#define VERTF(dw) (dw & CBRS_ORIENT_VERT)

// adjust supplied rectangle, so that point, pt is inside it.
// Adjusted slightly from original orientation to ensure point is now
// within specificed rectangle.
static void AdjustRectangle(CRect& rect, CPoint pt)
{
	int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
					(pt.x > rect.right) ? (pt.x - rect.right) : 0;
//	int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
//					(pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
//	rect.OffsetRect(nXOffset, nYOffset);
	rect.OffsetRect(nXOffset, 0);
}

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

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

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

COXDragDockContext::COXDragDockContext(CControlBar* pBar)
	: CDockContext(pBar)
{
}

COXDragDockContext::~COXDragDockContext()
{
}


/////////////////////////////////////////////////////////////////////////////
// COXDragDockContext operations

// start dragging. This is the only routine exposed externally. 
// pt = mouse position at start of drag (screen co-ords) 
void COXDragDockContext::StartDrag(CPoint pt)
{
   	ASSERT_VALID(m_pBar);
   	ASSERT(m_pBar->IsKindOf(RUNTIME_CLASS(COXSizeControlBar)));

   	COXSizeControlBar* pSzBar = (COXSizeControlBar*)m_pBar;

    // get styles from bar
   	m_dwDockStyle = m_pBar->m_dwDockStyle;
   	m_dwStyle = m_pBar->m_dwStyle & CBRS_ALIGN_ANY;
   	ASSERT(m_dwStyle != 0);
	
	// check to see we're not hanging from a COXMDIFloatWnd. 
	// Disallow dragging if we are...
	if (m_pBar->IsFloating())
	{
		CFrameWnd* pFrameWnd = m_pBar->GetParentFrame();
		ASSERT(pFrameWnd != NULL);
		ASSERT(pFrameWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)));
		if (pFrameWnd->IsKindOf(RUNTIME_CLASS(COXMDIFloatWnd)))
			return;				// do nothing if floating inside a COXMDIFloatWnd
	}
	
	// dragging has started message (only if window will actually dock !)
    if ((m_dwDockStyle & CBRS_ALIGN_ANY) == CBRS_ALIGN_ANY)
		AfxGetMainWnd()->SendMessage(WM_SETMESSAGESTRING, IDS_OX_MRC_STARTDOCKING);
	
    // handle pending WM_PAINT messages
    MSG msg;
    while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
	{
		if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
			return;
		ASSERT(msg.message == WM_PAINT);
        DispatchMessage(&msg);
	}
	
    // initialize drag state
   	m_rectLast.SetRectEmpty();
   	m_sizeLast.cx = m_sizeLast.cy = 0;
   	m_bForceFrame = m_bFlip = m_bDitherLast = FALSE;
	
	
   	// get current bar location 
   	CRect rect;
   	m_pBar->GetWindowRect(rect);
   	m_ptLast = pt;
   	m_ptStart = pt;
	BOOL bHorz = HORZF(m_dwStyle);
	
   	// MFC includes code for flipping orientation using the shift key - I wasn't keen
	// on this... (sorry) so I've left it out for now. Some references are still left
	// in for it, in case I decide to implement it.
   	
   	// Start by working out the possible rectangles that dragging could result in.
	// These are:
	// m_rectFrameDragHorz	: floating frame, horizontal orientation
	// m_rectFrameDragVert	: floating frame, vertical orientation (not used, 'cos
	//									flipping not allowed)
	//
	// m_rectDragHorz		: docking horizontally, another bar already on this row
	// m_rectDragVert		: docking vertically, another bar already on this row
	
	// m_rectDragHorzAlone  : docking horizontally, on a new row
	// m_rectDragVertAlone  : docking vertically, on a new row
	
	
	// calculate dragging rects if you drag on the new row/column
	//
	CRect rectBorder;
	m_pDockSite->RepositionBars(0,0xffff,AFX_IDW_PANE_FIRST, 
		CFrameWnd::reposQuery,&rectBorder);
	m_pDockSite->ClientToScreen(rectBorder);
	CWnd* pLeftDockBar=m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT);
	if(pLeftDockBar!=NULL && pLeftDockBar->GetStyle()&WS_VISIBLE)
	{
		CRect rectDockBar;
		pLeftDockBar->GetWindowRect(rectDockBar);
		rectBorder.left-=rectDockBar.Width();
	}
	CWnd* pRightDockBar=m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_RIGHT);
	if(pRightDockBar!=NULL && pRightDockBar->GetStyle()&WS_VISIBLE)
	{
		CRect rectDockBar;
		pRightDockBar->GetWindowRect(rectDockBar);
		rectBorder.right+=rectDockBar.Width();
	}
	m_rectDragHorzAlone=CRect(CPoint(rectBorder.left,rect.top),rectBorder.Size());
	m_rectDragVertAlone=CRect(CPoint(rect.left,rectBorder.top),rectBorder.Size());

	m_rectDragHorzAlone.bottom=m_rectDragHorzAlone.top+pSzBar->m_HorzDockSize.cy;
	m_rectDragVertAlone.right=m_rectDragVertAlone.left+pSzBar->m_VertDockSize.cx;
	//
	//////////////////////////////////////////////////////////////


	//////////////////
	//
	int nDockAreaWidth = rectBorder.Width();
	int nDockAreaHeight = rectBorder.Height();

	CSize HorzAloneSize(nDockAreaWidth, pSzBar->m_HorzDockSize.cy);
	CSize VertAloneSize(pSzBar->m_VertDockSize.cx, nDockAreaHeight);
	
	// sizes to use when docking into a row that already has some bars.
	// use the stored sizes - unless they are > the max dock area - 
	// in which case make a guess.
	if (pSzBar->m_VertDockSize.cy >= nDockAreaHeight - 16)
		VertAloneSize.cy = nDockAreaHeight / 3;
	else 
		VertAloneSize.cy = pSzBar->m_VertDockSize.cy;
	
	if (pSzBar->m_HorzDockSize.cx >= nDockAreaWidth - 16)
		HorzAloneSize.cx = nDockAreaWidth / 3;
	else
		HorzAloneSize.cx = pSzBar->m_HorzDockSize.cx;
	

	m_rectDragHorz = CRect(rect.TopLeft(), HorzAloneSize);
	m_rectDragVert = CRect(rect.TopLeft(), VertAloneSize);
	//
	///////////////////


   	// rectangle for the floating frame...
   	m_rectFrameDragVert = m_rectFrameDragHorz = 
		CRect(rect.TopLeft(), pSzBar->m_FloatSize);
   	
   	// To work out the size we actually create a floating mini frame, and then see how big
   	// it is
	CMiniDockFrameWnd* pFloatFrame =
		m_pDockSite->CreateFloatingFrame(bHorz ? CBRS_ALIGN_TOP : CBRS_ALIGN_LEFT);
   	if (pFloatFrame == NULL)
		AfxThrowMemoryException();
   	pFloatFrame->CalcWindowRect(&m_rectFrameDragHorz);
   	pFloatFrame->CalcWindowRect(&m_rectFrameDragVert);
// 	m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
// 	m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
   	pFloatFrame->DestroyWindow();

	// adjust rectangles so that point is inside
	AdjustRectangle(m_rectDragHorzAlone, pt);
	AdjustRectangle(m_rectDragVertAlone, pt);
   	AdjustRectangle(m_rectDragHorz, pt);
   	AdjustRectangle(m_rectDragVert, pt);
   	AdjustRectangle(m_rectFrameDragHorz, pt);
   	AdjustRectangle(m_rectFrameDragVert, pt);
	
   	// lock window update while dragging
   	ASSERT(m_pDC == NULL);
   	CWnd* pWnd = CWnd::GetDesktopWindow();
#ifndef _MAC
    if (pWnd->LockWindowUpdate()) 
		m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
    else
#endif
		m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE);
    ASSERT(m_pDC != NULL); 
	
	// initialize tracking state and enter tracking loop
	m_dwOverDockStyle = CanDock();
    Move(pt);   // call it here to handle special keys
    Track();
}


void COXDragDockContext::Move(CPoint pt)
{
	CPoint ptOffset = pt - m_ptLast;
	
#ifdef _MAC
    // prevent dragging the floating window completely under the menu bar
    GDHandle hgd = _AfxFindDevice(pt.x, pt.y);
    if (hgd == NULL || hgd == GetMainDevice() ||
		TestDeviceAttribute(hgd, hasAuxMenuBar))
	{
		CRect rect;
		
        if ((HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip))
			rect = m_rectFrameDragHorz;
        else
			rect = m_rectFrameDragVert;
		
        // determine our new position
		rect.OffsetRect(ptOffset);
		
        // keep us on the screen if we were getting too close to the menu bar
        int yMBarBottom = (*hgd)->gdRect.top + GetMBarHeight() + 4;
        if (rect.bottom < yMBarBottom)
		{
			pt.y += yMBarBottom - rect.bottom;
            ptOffset.y += yMBarBottom - rect.bottom;
		}
	}
#endif
	
	// offset all drag rects to new position
    m_rectDragHorz.OffsetRect(ptOffset);
    m_rectFrameDragHorz.OffsetRect(ptOffset);
    m_rectDragVert.OffsetRect(ptOffset);
    m_rectFrameDragVert.OffsetRect(ptOffset);
	
	// these rectangles only move in 1 direction

	m_rectDragHorzAlone.top += ptOffset.y;
	m_rectDragHorzAlone.bottom += ptOffset.y;
	m_rectDragVertAlone.left  += ptOffset.x;
	m_rectDragVertAlone.right += ptOffset.x;
	
    m_ptLast = pt;
	
    // if control key is down don't dock
    m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
	
    // update feedback
    DrawFocusRect();
}


void COXDragDockContext::OnKey(int nChar, BOOL bDown)
	{
	if (nChar == VK_CONTROL)
		UpdateState(&m_bForceFrame, bDown);
	}


void COXDragDockContext::EndDrag()
{
    CancelDrag();
	if (m_ptStart == m_ptLast)
		return;
	
	m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
	if (m_dwOverDockStyle != 0)
	{
		// dockbar we're going to dock at.
		CDockBar* pDockBar = GetDockBar();
        ASSERT(pDockBar != NULL);
    
        // check the original dockbar - if a valid CSizeDockBar...
		// work out the row number.
		CDockBar* pOrigDockBar = m_pBar->m_pDockBar;
		int nOrigCheckSum = -1;
		if (pOrigDockBar != NULL && 
			pOrigDockBar->IsKindOf(RUNTIME_CLASS(COXSizeDockBar)))
			nOrigCheckSum = ((COXSizeDockBar*)pOrigDockBar)->CheckSumBars();

		// Now we're going to actually dock the window.
		
		// Update the appropriate size in the control bar.
		if (HORZF(m_dwOverDockStyle)) 
		{
			((COXSizeControlBar*)m_pBar)->m_HorzDockSize = m_rectDragDock.Size();
		}
		else
		{
			((COXSizeControlBar*)m_pBar)->m_VertDockSize = m_rectDragDock.Size();
		}
		
        m_pDockSite->DockControlBar(m_pBar, pDockBar, m_rectDragDock);
        
		// if into a sizeable dockbar (always we be !), then adjust other bars in the same row
		// to attempt to maintain size
		if (pDockBar->IsKindOf(RUNTIME_CLASS(COXSizeDockBar)))
		{
			if (pOrigDockBar != pDockBar || 
				((COXSizeDockBar*)pDockBar)->CheckSumBars() != nOrigCheckSum)
			{
				((COXSizeDockBar*)pDockBar)->AdjustForNewBar(m_pBar);
			}
			// force RecalcLayout below to adjust sizes always for the bar into 
			// which we have docked  - this is needed as if the bar doesn't 
			// actually changed position in the array, but has changed size 
			// (because the docking algorithm above guess the size wrong, then 
			// we need to set it back again.
			((COXSizeDockBar*)pDockBar)->m_CountBars = 0;			
		}
		// This RecalcLayout is what will adjust the size.
		m_pDockSite->RecalcLayout();
	}
    else
	{
    	m_ptMRUFloatPos = m_rectFrameDragHorz.TopLeft();
		m_pDockSite->FloatControlBar(m_pBar, m_rectFrameDragHorz.TopLeft(),
			CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI));
		m_pBar->SendMessage(WM_OX_APP_AFTERFLOAT_MSG);
		
		// set flag to indicate user has moved the bar - done as a style flag on the window.
		CWnd* pFrameWnd = m_pBar->GetParentFrame();
		ASSERT(pFrameWnd->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)));
		pFrameWnd->ModifyStyle(0, CBRS_MOVED_BY_USER);		
	}
}


void COXDragDockContext::CancelDrag()
{
	DrawFocusRect(TRUE);    // gets rid of focus rect
    ReleaseCapture();
	
    CWnd* pWnd = CWnd::GetDesktopWindow();
#ifndef _MAC
    pWnd->UnlockWindowUpdate();
#endif
    if (m_pDC != NULL)
	{
		pWnd->ReleaseDC(m_pDC);
        m_pDC = NULL;
	}
	
	// Tell main window to clear it's status bar
	CWnd* pMainWnd = AfxGetMainWnd();
	ASSERT(pMainWnd != NULL);
	pMainWnd->SendMessage(WM_SETMESSAGESTRING, (WPARAM)AFX_IDS_IDLEMESSAGE);
}


/////////////////////////////////////////////////////////////////////////////
// Implementation

void COXDragDockContext::DrawFocusRect(BOOL bRemoveRect)
{
	ASSERT(m_pDC != NULL);
	
    // default to thin frame
    CSize size(CX_BORDER, CY_BORDER);
	
    // determine new rect and size
    CRect rect;
    CBrush* pWhiteBrush = 
		CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
    CBrush* pDitherBrush = CDC::GetHalftoneBrush();
    CBrush* pBrush = pWhiteBrush;
	
    if (m_dwOverDockStyle != 0)
	{
		rect = m_rectDragDock;
	}
    else
	{
#ifndef _MAC
		// use thick frame instead
        size.cx = GetSystemMetrics(SM_CXFRAME) - CX_BORDER;
        size.cy = GetSystemMetrics(SM_CYFRAME) - CY_BORDER;
#endif
		rect = m_rectFrameDragHorz;
		pBrush = pDitherBrush;
	}
	if (bRemoveRect)
		size.cx = size.cy = 0;

#if _MFC_VER < 0x0700	
    if ( afxData.bWin4 && (HORZF(m_dwOverDockStyle) || VERTF(m_dwOverDockStyle)))
#else
    if (HORZF(m_dwOverDockStyle) || VERTF(m_dwOverDockStyle))
#endif
	{
		// looks better one pixel in (makes the bar look pushed down)
		rect.InflateRect(-CX_BORDER, -CY_BORDER);
	}
	
    // draw it and remember last size
    m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast,
		pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush);
    m_rectLast = rect;
    m_sizeLast = size;
    m_bDitherLast = (pBrush == pDitherBrush);
}


void COXDragDockContext::UpdateState(BOOL* pFlag, BOOL bNewValue)
{
    if (*pFlag != bNewValue)
	{
		*pFlag = bNewValue;
        m_dwOverDockStyle = (m_bForceFrame) ? 0 : CanDock();
        DrawFocusRect();
	}
}


DWORD COXDragDockContext::CanDock()
{
	BOOL bStyleHorz;
    DWORD dwDock = 0; // Dock Canidate
    DWORD dwCurr = 0; // Current Orientation
	
    // let's check for something in our current orientation first
    // then if the shift key is not forcing our orientation then
    // check for horizontal or vertical orientations as long
    // as we are close enough
    ASSERT(m_dwStyle != 0);
	
    bStyleHorz = HORZF(m_dwStyle);
	
    m_pTargetDockBar = NULL;
	
    // can simplify this, 'cos most of the rectangles are actually the same
    if (dwDock == 0 && HORZF(m_dwDockStyle)/* && m_rectDragHorzAlone.PtInRect(m_ptLast)*/)
	{
        dwDock = m_pDockSite->CanDock(m_rectDragHorzAlone,
			m_dwDockStyle & ~CBRS_ORIENT_VERT, (CDockBar**)&m_pTargetDockBar);
	}
    if (dwDock == 0 && VERTF(m_dwDockStyle)/* && m_rectDragVertAlone.PtInRect(m_ptLast)*/)
	{
        dwDock = m_pDockSite->CanDock(m_rectDragVertAlone,
			m_dwDockStyle & ~CBRS_ORIENT_HORZ, (CDockBar**)&m_pTargetDockBar);
	}
	
	if (dwDock != 0)	// will dock somewhere - now look for 1/2 bars on the row...
	{
		if (HORZF(dwDock))
		{
			m_rectDragDock = m_rectDragHorzAlone;
			dwCurr = m_pDockSite->CanDock(m_rectDragHorz, 
				m_dwDockStyle & ~CBRS_ORIENT_VERT, (CDockBar**)&m_pTargetDockBar);

			if (dwCurr != 0)
			{
				int nBars=m_pTargetDockBar->BarsOnThisRow(m_pBar,m_rectDragHorzAlone);
				if(nBars!=0)
				{
					m_rectDragDock = m_rectDragHorz;

					// v9.3 - update 04 fixed resizing of docked item if moving to same bar - AAW 2009-03-29
					if (m_pBar->m_pDockBar == m_pTargetDockBar)
					{
						// if we're planning to move it to the same bar, don't change our width.
						CRect rct;
						m_pBar->GetWindowRect(&rct);
						m_rectDragDock.bottom = m_rectDragDock.right +
							rct.Width();
					}
					else
					// AAW END
					{
						m_rectDragDock.right = m_rectDragDock.left+
							m_rectDragHorzAlone.Width()/(nBars+1);
					}
				}
			}
		}		
		
		if (VERTF(dwDock))
		{
			m_rectDragDock = m_rectDragVertAlone;
			dwCurr = m_pDockSite->CanDock(m_rectDragVert, 
				m_dwDockStyle & ~CBRS_ORIENT_HORZ, (CDockBar**)&m_pTargetDockBar);
			
			if (dwCurr != 0)
			{
				int nBars=m_pTargetDockBar->BarsOnThisRow(m_pBar,m_rectDragVertAlone);
				if(nBars!=0)
				{
					m_rectDragDock = m_rectDragVert;
					// v9.3 - update 04 fixed resizing of docked item if moving to same bar - AAW 2009-03-29
					if (m_pBar->m_pDockBar == m_pTargetDockBar)
					{   // if we're planning to move it to the same bar, don't change our height.
						CRect rct;
						m_pBar->GetWindowRect(&rct);
						m_rectDragDock.bottom = m_rectDragDock.top +
							rct.Height();
					}
					else
					// AAW END
					{
						m_rectDragDock.bottom = m_rectDragDock.top+
							m_rectDragVertAlone.Height()/(nBars+1);
					}
				}
			}
		}		
	}

    return dwCurr;
}

// should have m_dwOverDockStyle and m_rectDragDock set before calling this
// routine.
CDockBar* COXDragDockContext::GetDockBar()
{
	DWORD dw = 0;
    CDockBar* pBar;
    if (HORZF(m_dwOverDockStyle))
	{
    	dw = m_pDockSite->CanDock(m_rectDragDock,
			m_dwOverDockStyle & ~CBRS_ORIENT_VERT, &pBar);
        ASSERT(dw != 0);
        ASSERT(pBar != NULL);
        return pBar;
	}
	if (VERTF(m_dwOverDockStyle))
	{
    	dw = m_pDockSite->CanDock(m_rectDragDock,
			m_dwOverDockStyle & ~CBRS_ORIENT_HORZ, &pBar);
        ASSERT(dw != 0);
        ASSERT(pBar != NULL);
        return pBar;
	}
    return NULL;
}


BOOL COXDragDockContext::Track()
{
    // don't handle if capture already set
    if (::GetCapture() != NULL)
        return FALSE;
	
    // set capture to the window which received this message
    m_pBar->SetCapture();
    ASSERT(m_pBar == CWnd::GetCapture());
	
    // get messages until capture lost or cancelled/accepted
    while(CWnd::GetCapture() == m_pBar)
	{
        MSG msg;
#ifndef _MAC
        if (!::GetMessage(&msg, NULL, 0, 0))
#else
			// don't allow yielding while tracking since we don't have LockWindowUpdate
			if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE|PM_NOYIELD))
            continue;
        if (msg.message == WM_QUIT)
#endif
		{
            AfxPostQuitMessage(PtrToInt(msg.wParam));
            break;
		}
		
        switch (msg.message)
		{
            case WM_LBUTTONUP:		// drag finished 
                EndDrag();
                return TRUE;
				
            case WM_MOUSEMOVE:
                Move(msg.pt);
                break;
				
            case WM_KEYUP:
                OnKey((int)msg.wParam, FALSE);
                break;
				
            case WM_KEYDOWN:
				OnKey((int)msg.wParam, TRUE);
                if (msg.wParam == VK_ESCAPE)
					goto exit_cancel_drag;
                break;
				
			case WM_RBUTTONDOWN:
				goto exit_cancel_drag;
				
				// just dispatch rest of the messages
            default:
                DispatchMessage(&msg);
				break;
		}
	}
    
exit_cancel_drag:			// goto  - can't use break as we're inside a switch()    
	CancelDrag();
	return FALSE;
}

// Wow - another genuine virtual function in CDockContext !
// overridden to prevent windows floated in an MDI window from being double-clicked
void COXDragDockContext::ToggleDocking()
{
   	ASSERT_VALID(m_pBar);
   	ASSERT(m_pBar->IsKindOf(RUNTIME_CLASS(COXSizeControlBar)));

	// check to see we're not hanging from a COXMDIFloatWnd. 
	// Disallow toggle docking if we are
	if (m_pBar->IsFloating())
	{
		CFrameWnd* pFrameWnd = m_pBar->GetParentFrame();
		ASSERT(pFrameWnd != NULL);
		ASSERT(pFrameWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)));
		if (pFrameWnd->IsKindOf(RUNTIME_CLASS(COXMDIFloatWnd)))
			return;				// do nothing if floating inside a COXMDIFloatWnd
	}

	CDockContext::ToggleDocking();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions