Click here to Skip to main content
15,884,836 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.7K   23.6K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
// ===================================================================================
// 					Class Implementation : COXSizableMiniDockFrameWnd
// ===================================================================================

// Header file : OXSzMiniDockFrmWnd.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 <afxole.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

// v93 update 03 - 64-bit
#include "UTB64Bit.h"

#include "OXSzMiniDockFrmWnd.h"

#include "OXSizeCtrlBar.h"
#include "OXSizeDockBar.h"
#include "OXFrameWndDock.h"

#include "OXSkins.h"

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


IMPLEMENT_DYNCREATE(COXSizableMiniDockFrameWnd, CMiniDockFrameWnd)

#define new DEBUG_NEW

// Helper function: used below
void AdjustForBorders(CRect& rect, DWORD dwStyle);

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

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

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

BEGIN_MESSAGE_MAP(COXSizableMiniDockFrameWnd, CMiniDockFrameWnd)
	//{{AFX_MSG_MAP(COXSizableMiniDockFrameWnd)
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_CLOSE()
    ON_WM_NCLBUTTONDOWN()
    ON_WM_NCHITTEST()
	ON_WM_MOUSEACTIVATE()
    ON_WM_NCACTIVATE()
	ON_WM_PARENTNOTIFY()
	ON_WM_SYSCOMMAND()
    ON_WM_INITMENUPOPUP()
	ON_WM_ACTIVATE()
	ON_WM_NCPAINT()
	ON_WM_SETCURSOR()
	ON_WM_NCLBUTTONUP()
	ON_WM_DESTROY()
	ON_WM_NCRBUTTONDOWN()
    ON_WM_WINDOWPOSCHANGED()
	ON_WM_NCMOUSEMOVE()
	//}}AFX_MSG_MAP
    // Global help commands
END_MESSAGE_MAP()

HHOOK COXSizableMiniDockFrameWnd::m_hMouseHook = NULL;
HWND COXSizableMiniDockFrameWnd::m_hwndPrevMouseMoveWnd = NULL;

COXSizableMiniDockFrameWnd::COXSizableMiniDockFrameWnd() :
	m_pMiniFrameSkin(NULL)
{

}

COXSizableMiniDockFrameWnd::~COXSizableMiniDockFrameWnd()
{
	if ( m_pMiniFrameSkin != NULL )
		delete m_pMiniFrameSkin;
}

int COXSizableMiniDockFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CMiniDockFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	m_nContainedBarType = Unknown;

	m_bBeingDestroyed=FALSE;

	// Hook the mouse
	if (m_hMouseHook == NULL)
		m_hMouseHook = ::SetWindowsHookEx(WH_MOUSE, MouseProc, 0, AfxGetApp()->m_nThreadID);

	return 1;
}

void COXSizableMiniDockFrameWnd::OnSysCommand(UINT nID, LPARAM lParam)
{
	// Call DrawCaption to prevent the original caption from drawing
	GetMiniFrameSkin()->DrawCaption(this);

	// CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at position 1
	// in the array
	CControlBar* pBar=((COXSizeDockBar *)&m_wndDockBar)->GetFirstControlBar();
	if(pBar!=NULL)
	{
		ASSERT_KINDOF(CControlBar, pBar);
		ASSERT(pBar->m_pDockContext != NULL);
		if(pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
		{
			COXMDIChildWndSizeDock* pMDIChild=((COXSizeViewBar*)pBar)->m_pChildWnd;
			if(::IsWindow(pMDIChild->m_hWnd))
			{
				if(nID==pMDIChild->m_nDockMessageID)
				{
					pMDIChild->OnMakeItDockable();
					return;
				}
			}
		}
	}

	CMiniDockFrameWnd::OnSysCommand(nID, lParam);
}

// respond to the miniframe resizing. If we've got a sizeable control
// bar in the window, then we set it's size. Need to adjust for the
// window borders. The window will then get repositioned by a ReCalcLayout()
void COXSizableMiniDockFrameWnd::OnSize(UINT /* nType */, int cx, int cy)
	{
    if (cx == 0 && cy == 0)
		return;
	
    // We don't support CBRS_FLOAT_MULTI
    if ((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0)
		{
        // CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at position 1
        // in the array
        COXSizeControlBar* pBar = ((COXSizeDockBar*)(&m_wndDockBar))->GetFirstControlBar();
        // ignore size request if not visible....
        if (pBar != NULL && COXSizeDockBar::IsSizeable(pBar) && pBar->IsVisible())
			{
			CRect rect(0, 0, cx, cy);
			AdjustForBorders(rect, pBar->m_dwStyle);
			
            pBar->m_FloatSize.cx = rect.Width();
            pBar->m_FloatSize.cy = rect.Height();
			}
		}
    RecalcLayout();
	}


BOOL COXSizableMiniDockFrameWnd::PreCreateWindow(CREATESTRUCT &cs)
	{
	// modify frame style so it is fully sizeable - we will modify this again later
	// if we discover that we have a standard MFC control bar inside the frame
	// turn on thick frame styles. MFS_THICKFRAME is what's expected, but also need WS_THICKFRAME,
	// as NT expects this to be able to do the resizing.
	cs.style |= MFS_THICKFRAME | WS_THICKFRAME; 
    cs.style &= ~( MFS_MOVEFRAME | MFS_4THICKFRAME );		
    return CMiniDockFrameWnd::PreCreateWindow(cs);
	}



// over-ridden so we can find out the type of the bar in this window
#if _MSC_VER >= 1400
LRESULT COXSizableMiniDockFrameWnd::OnNcHitTest(CPoint point)
#else
UINT COXSizableMiniDockFrameWnd::OnNcHitTest(CPoint point)
#endif
{
	return CMiniDockFrameWnd::OnNcHitTest(point);
}


// if we've got a COXSizeControlBar inside this frame, and it's a resize,
// then we can use the default window's sizing. 
void COXSizableMiniDockFrameWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
{

	enum ContainedBarType Type = GetContainedBarType();
	if (Type == MRCSizeBar)
	{
		if (nHitTest >= HTSIZEFIRST && nHitTest <= HTSIZELAST)
		{
			// special activation for floating toolbars
			ActivateTopParent();
			CMiniFrameWnd::OnNcLButtonDown(nHitTest, point);
			return;
		}
		else if (nHitTest == HTSYSMENU)
		{
			// do the system menu - ie give move,size,hide, etc options as would Win95.						
#if _MFC_VER < 0x0700		
			InvertSysMenu();
#endif
			CPoint pt(0,0);
			ClientToScreen(&pt);
			CRect rcSysIcon;
			GetWindowRect(&rcSysIcon);
			rcSysIcon.right = rcSysIcon.left + 12;		// NB:hard-coded value for width of system icon
			rcSysIcon.bottom = pt.y;					
			
			CMenu* pSysMenu = GetSystemMenu(FALSE);
			int nCmd = pSysMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, pt.x, pt.y, this, & rcSysIcon);
#if _MFC_VER < 0x0700	
			InvertSysMenu();
#endif	
			if (nCmd != 0)
			{
				SendMessage(WM_SYSCOMMAND, nCmd, 0);
			}
			return;
		}
	}

	if (nHitTest == HTCLOSE)
	{
		if (!GetMiniFrameSkin()->DrawCaptionButtons(this))
			CMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
		else
		{
			// If the close button is hidden emulate a caption click
			if (GetSystemMenu(FALSE)->GetMenuItemCount() == 0)
				CMiniDockFrameWnd::OnNcLButtonDown(HTCAPTION, point);
		}
	}
	else
	{
		if (nHitTest == HTCAPTION)
		{
			// special activation for floating toolbars
			ActivateTopParent();

			// initiate toolbar drag for non-CBRS_FLOAT_MULTI toolbars
			if ((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0)
			{
				// Get a pointer to the control bar
				int nPos = 1;	
				CControlBar* pBar = NULL;
				while (pBar == NULL && nPos < m_wndDockBar.m_arrBars.GetSize())
					pBar = (CControlBar*) m_wndDockBar.m_arrBars[nPos++];

				if (AfxGetMainWnd()->SendMessage(WM_QUERYSNAPPING))
				{
					// Snaping is enabled

					// Handle COXCoolToolBar
					COXCoolToolBar* pToolBar = DYNAMIC_DOWNCAST(COXCoolToolBar, pBar);
					if (pToolBar)
					{
						// We have a toolbar
						CRect rectThis, rectToolBar;
						GetWindowRect(rectThis);
						pToolBar->GetWindowRect(rectToolBar);
						
						CPoint ptClient(point);
						pToolBar->ScreenToClient(&ptClient);
						ptClient.x += rectToolBar.left - rectThis.left;
						ptClient.y += rectToolBar.top - rectThis.top;
						
						pToolBar->SaveMouseOffset(ptClient);

						pToolBar->SetCapture();
						pToolBar->m_bDragging = true;
						::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
						
						return;
					}

					// Handle COXSizeControlBar
					COXSizeControlBar* pControlBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pBar);
					if (pControlBar)
					{
						// We have a docking window
						CRect rectThis, rectControlBar;
						GetWindowRect(rectThis);
						pControlBar->GetWindowRect(rectControlBar);
						
						CPoint ptClient(point);
						pControlBar->ScreenToClient(&ptClient);
						ptClient.x += rectControlBar.left - rectThis.left;
						ptClient.y += rectControlBar.top - rectThis.top;
						
						pControlBar->SaveMouseOffset(ptClient);
						pControlBar->SetCapture();
						pControlBar->m_bDragging = true;
						::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));

						return;
					}
				}
				else // snaping is disabled
				{
					CMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
					return;
				}
			}
		}
		else if (nHitTest >= HTSIZEFIRST && nHitTest <= HTSIZELAST)
		{

			// special activation for floating toolbars
			ActivateTopParent();

			// Get a pointer to the control bar
			int nPos = 1;	
			CControlBar* pBar = NULL;
			while (pBar == NULL && nPos < m_wndDockBar.m_arrBars.GetSize())
				pBar = (CControlBar*) m_wndDockBar.m_arrBars[nPos++];

			ASSERT(pBar != NULL);
			ASSERT_KINDOF(CControlBar, pBar);
			ASSERT(pBar->m_pDockContext != NULL);

			// CBRS_SIZE_DYNAMIC toolbars cannot have the CBRS_FLOAT_MULTI style
			ASSERT((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0);
			pBar->m_pDockContext->StartResize(nHitTest, point);
			return;

		}
		CMiniFrameWnd::OnNcLButtonDown(nHitTest, point);
	}
}


int COXSizableMiniDockFrameWnd::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
	// activate this window if necessary
	// CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at position 1
	// in the array
	CControlBar* pBar = ((COXSizeDockBar *)&m_wndDockBar)->GetFirstControlBar();
	if(pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
	{
		pBar->SendMessage(WM_ACTIVATEVIEWBAR,TRUE,ID_SOURCE_MINIDOCK);
	}

	enum ContainedBarType Type = GetContainedBarType();
	if (Type == MRCSizeBar)
	{
		if (nHitTest >= HTSIZEFIRST && nHitTest <= HTSIZELAST)
			return CMiniFrameWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
	}
	return CMiniDockFrameWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}



// returns the type of the contained bar
// Floating frames are created from CFrameWnd::CreateFloatingFrame(), and at this point,
// we don't know what type of control bar will eventually be in this frame. This routine
// determines the type of control bar, and sets the neccessary styles. Generally this routine gets
// called as soon as we do a WM_NCHITTEST on the window - ie before the user can get a chance to
// manipulate it with the mouse
//
// COXSizeControlBar - default style of WS_THICKFRAME is ok (we've overridden the create too)
//					    but we need to ensure "SC_SIZE" is on the menu, otherwise we can't
//						the default WM_NCLBUTTONDOWN won't generate an SC_SIZE.
//
// CControlBar, CBRS_SIZE_DYNAMIC
//					  - set MFS_4THICKFRAME (disallow diagonal sizing)
//
// CControlBar, not CBRS_SIZE_DYNAMIC
//					  - remove WS_THICKFRAME & add MFS_MOVEFRAME (we don't want sizing hit test values)
enum COXSizableMiniDockFrameWnd::ContainedBarType 
COXSizableMiniDockFrameWnd::GetContainedBarType()
	{
	if (m_nContainedBarType == Unknown)
		{
		m_nContainedBarType = MFCBase;
		if ((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0) // don't handle this
			{
			COXSizeControlBar* pBar = ((COXSizeDockBar*)(&m_wndDockBar))->GetFirstControlBar();
			if (pBar != NULL)
				{
				if (COXSizeDockBar::IsSizeable(pBar))
					{		
					m_nContainedBarType = MRCSizeBar;
					GetSystemMenu(TRUE);					// reset the system menu
					
					// delete sys menu items that might be present....
					CMenu* pSysMenu = GetSystemMenu(FALSE);
					if(pSysMenu!=NULL)
					{
						pSysMenu->DeleteMenu(SC_MAXIMIZE, MF_BYCOMMAND);
						pSysMenu->DeleteMenu(SC_MINIMIZE, MF_BYCOMMAND);
						pSysMenu->DeleteMenu(SC_RESTORE, MF_BYCOMMAND);
						pSysMenu->DeleteMenu(SC_TASKLIST, MF_BYCOMMAND);
						// remove anything with ID=0
						while (pSysMenu->DeleteMenu(0, MF_BYCOMMAND));	
					}
					
					// if window is meant to close, ensure sysmenu has "Close" on it, not "Hide"
					// MFC4.0 replaces "Close" with "Hide"
					// extract close text from ID_FILE_CLOSE after the "\n" for the tooltip prompt
					if (!(pBar->m_Style & SZBARF_DESTROY_ON_CLOSE))
						{
						CString strHide;
						if (strHide.LoadString(AFX_IDS_HIDE))
							{
							// modify menu text to be "Hide" instrad of close
							VERIFY(pSysMenu->ModifyMenu(SC_CLOSE, MF_BYCOMMAND | MF_STRING, SC_CLOSE, strHide));  
							} 
						}
					}
				else
					{
					if ((pBar->m_dwStyle & CBRS_SIZE_DYNAMIC))	 // dynamic bar - turn on MFS_4THICKFRAME
						{
						ModifyStyle(0, MFS_4THICKFRAME);	
						return m_nContainedBarType;
						}
					
					}
				}
			}
		if (m_nContainedBarType == MFCBase)
			{
			ModifyStyle(WS_THICKFRAME, MFS_MOVEFRAME);
			}
		}		
	// if bar is MFC bar (and not CBRS_SIZE_DYNAMIC, turn on MFS_MOVEFRAME)
	return m_nContainedBarType;
	}


void COXSizableMiniDockFrameWnd::OnClose()
{
	if(m_bBeingDestroyed)
	{
		return;
	}

	m_bBeingDestroyed=TRUE;

	if ((m_wndDockBar.m_dwStyle & CBRS_FLOAT_MULTI) == 0)
	{
		CControlBar* pBar = NULL;
		// CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at position 1
		// in the array
		pBar = ((COXSizeDockBar *)&m_wndDockBar)->GetFirstControlBar();
		if(pBar!=NULL && pBar->IsKindOf(RUNTIME_CLASS(COXSizeControlBar)))
		{
			if(((COXSizeControlBar*)pBar)->m_Style & SZBARF_DESTROY_ON_CLOSE)
            {
				// close the Frame Window
				CFrameWnd::OnClose();       // close the window
				delete pBar;            // now explicitly delete the control bar
				return;
			}
		}
		
		ASSERT(pBar != NULL);
		ASSERT_KINDOF(CControlBar, pBar);
		ASSERT(pBar->m_pDockContext != NULL);
		if(pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
		{
			COXSizeViewBar* pViewBar=(COXSizeViewBar*)pBar;
			if(::IsWindow(pViewBar->m_hWnd) && !pViewBar->IsBeingDestroyed())
			{
				if(!pViewBar->QueryCloseView())
				{
					// document can't be closed right now -- don't close it
					m_bBeingDestroyed=FALSE;
					return;
				}
				
				pViewBar->m_pChildWnd->GetMDIFrame()->
					ShowControlBar(pViewBar,FALSE,FALSE);
				pViewBar->m_pDockContext->ToggleDocking();
				pViewBar->m_WrapperWnd.SendMessage(WM_CLOSE);
				return;
			}
		}
	}

    // otherwise just hide it.
    CMiniDockFrameWnd::OnClose();

	m_bBeingDestroyed=FALSE; 

    return;
}

BOOL COXSizableMiniDockFrameWnd::OnNcActivate(BOOL bActive)
{
	return GetMiniFrameSkin()->OnNcActivate(bActive, this);
}

void COXSizableMiniDockFrameWnd::OnParentNotify(UINT message, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);

	if(message==WM_LBUTTONDOWN || message==WM_RBUTTONDOWN || message==WM_MBUTTONDOWN)
	{
		// activate this window if necessary
		// CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at position 1
		// in the array
		CControlBar* pBar = ((COXSizeDockBar *)&m_wndDockBar)->GetFirstControlBar();
		pBar->SendMessage(WM_ACTIVATEVIEWBAR,TRUE,ID_SOURCE_MINIDOCK);
	}
}

void COXSizableMiniDockFrameWnd::OnInitMenuPopup(CMenu* pMenu, UINT, BOOL bSysMenu)
{
	AfxCancelModes(m_hWnd);

	if (bSysMenu)
	{
		// CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at position 1
		// in the array
		CControlBar* pBar=((COXSizeDockBar *)&m_wndDockBar)->GetFirstControlBar();
		if(pBar!=NULL)
		{
			ASSERT_KINDOF(CControlBar, pBar);
			if(pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
			{
				COXMDIChildWndSizeDock* pMDIChild=((COXSizeViewBar*)pBar)->m_pChildWnd;
				if(::IsWindow(pMDIChild->m_hWnd))
				{
					if(pMenu->GetMenuState(pMDIChild->m_nDockMessageID,	
						MF_BYCOMMAND)==0xffffffff)
					{
						//HACK
//						pMenu->RemoveMenu(MF_BYPOSITION,2);

						pMenu->AppendMenu(MF_SEPARATOR);
						pMenu->AppendMenu(pMDIChild->m_bDockable ? 
							MF_CHECKED : MF_UNCHECKED, pMDIChild->m_nDockMessageID, 
							pMDIChild->m_sDockMenuItem);
					}
				}
			}
		}
	}
}

void COXSizableMiniDockFrameWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
	CMiniDockFrameWnd::OnActivate(nState, pWndOther, bMinimized);
	
	// CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at 
	// position 1 in the array
	CControlBar* pBar=((COXSizeDockBar *)&m_wndDockBar)->GetFirstControlBar();
	if(pBar!=NULL)
	{
		ASSERT_KINDOF(CControlBar, pBar);
		ASSERT(pBar->m_pDockContext != NULL);
		if(pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
		{
			pBar->SendMessage(WM_ACTIVATEVIEWBAR,nState==WA_INACTIVE ? FALSE : TRUE,
				ID_SOURCE_MINIDOCK);
		}
	}
}


BOOL COXSizableMiniDockFrameWnd::IsDockingViewBar()
{
	ASSERT_VALID(this);

	// CMiniDockFrameWnd class assumes if there is only 1 bar, then it's at 
	// position 1 in the array
	CControlBar* pBar=((COXSizeDockBar *)&m_wndDockBar)->GetFirstControlBar();
	if(pBar!=NULL)
	{
		ASSERT_KINDOF(CControlBar, pBar);
		ASSERT(pBar->m_pDockContext != NULL);
		if(pBar->IsKindOf(RUNTIME_CLASS(COXSizeViewBar)))
			return TRUE;
	}

	return FALSE;
}

// convert MiniDock size to a client size.. or vice versa.
void MiniDockToClient(CRect & rect, BOOL bConvertToClient)
{
	static int nCaptionY = -1;
	static int nBorderX, nBorderY;
	
	// if not set up, create a temporary floating frame to see how big it is.
	if (nCaptionY == -1)
	{
		CFrameWnd* pMainFrame = (CFrameWnd*)AfxGetMainWnd();
		CMiniDockFrameWnd* pTmpFloatFrame = pMainFrame->CreateFloatingFrame(0);
		
		// calculate frame dragging rectangle
		CRect rcFloat(0,0,0,0);
		
		pTmpFloatFrame->CalcWindowRect(&rcFloat);
		
		rcFloat.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
		
		nCaptionY = - rcFloat.top;
		nBorderY = rcFloat.bottom;
		nBorderX = rcFloat.right;
		
		pTmpFloatFrame->DestroyWindow();
	}		
	
	if (bConvertToClient)
	{
		rect.left += nBorderX;
		rect.right -= nBorderX;
		rect.top += nCaptionY;
		rect.bottom -= nBorderY;
	}
	else
	{
		rect.left -= nBorderX;
		rect.right += nBorderX;
		rect.top -= nCaptionY;
		rect.bottom += nBorderY;
	}
}


// Helper function: used below
// adjusts the size, depending on the borders specified by the CControlBar style
void AdjustForBorders(CRect& rect, DWORD dwStyle)
{
	if (dwStyle & CBRS_BORDER_LEFT)
		rect.left -= afxData.cxBorder2;
	if (dwStyle & CBRS_BORDER_TOP)
		rect.top -= afxData.cyBorder2;
	if (dwStyle & CBRS_BORDER_RIGHT)
		rect.right += afxData.cxBorder2;
	if (dwStyle & CBRS_BORDER_BOTTOM)
		rect.bottom += afxData.cyBorder2;
}

void COXSizableMiniDockFrameWnd::OnNcPaint() 
{
	GetMiniFrameSkin()->OnNcPaint(this);
}

COXMiniFrameSkin* COXSizableMiniDockFrameWnd::GetMiniFrameSkin()
{
	// Check if the app is derived from COXSkinnedApp
	COXSkinnedApp* pSkinnedApp = DYNAMIC_DOWNCAST(COXSkinnedApp, AfxGetApp());
	if (pSkinnedApp != NULL && pSkinnedApp->GetCurrentSkin() != NULL)
		return pSkinnedApp->GetCurrentSkin()->GetMiniFrameSkin();
	else
	{
		// Create a classic skin for this class if not created already
		if (m_pMiniFrameSkin == NULL)
			m_pMiniFrameSkin = new COXMiniFrameSkinClassic();

		return m_pMiniFrameSkin;
	}
}


BOOL COXSizableMiniDockFrameWnd::OnSetCursor(CWnd* /*pWnd*/, UINT nHitTest, UINT /*message*/) 
{
	// Since the default implementation of CWnd::OnSetCursor(...) draws the close button
	// in the caption, we need to re-implement its logic here and not draw that button.
	
	// Code from CMiniDockFrameWnd::OnSetCursor(...)
	CFrameWnd* pFrameWnd = GetTopLevelFrame();
	ASSERT_VALID(pFrameWnd);
	if (pFrameWnd->m_bHelpMode)
	{
		SetCursor(afxData.hcurHelp);
		return TRUE;
	}
	// End of code from CMiniDockFrameWnd::OnSetCursor(...)
	
	// Implementation of the logic of CWnd::OnSetCursor(...)
	// Get the appropriate cursor
	HCURSOR hCursor;

	if (nHitTest == HTBOTTOM || nHitTest == HTTOP)
		hCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENS);

	else if (nHitTest == HTBOTTOMLEFT || nHitTest == HTTOPRIGHT)
		hCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENESW);

	else if (nHitTest == HTBOTTOMRIGHT || nHitTest == HTTOPLEFT)
		hCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE);

	else if (nHitTest == HTRIGHT || nHitTest == HTLEFT)
		hCursor = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);

	else
		hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);

	::SetCursor(hCursor);
	// End of implementation of the logic of CWnd::OnSetCursor(...)

	return TRUE;
}

void COXSizableMiniDockFrameWnd::OnNcLButtonUp(UINT nHitTest, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	if (nHitTest == HTCLOSE && GetSystemMenu(FALSE)->GetMenuItemCount() > 0)
	{
		SendMessage(WM_SYSCOMMAND, SC_CLOSE, 0);
	}
	else
		CMiniDockFrameWnd::OnNcLButtonUp(nHitTest, point);
}

// Update the buttons of the mini frame window when the mouse leaves
LRESULT CALLBACK COXSizableMiniDockFrameWnd::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (nCode < 0)
		return ::CallNextHookEx(m_hMouseHook, nCode, wParam, lParam);

	if (nCode == HC_ACTION && (wParam == WM_MOUSEMOVE || wParam == WM_NCMOUSEMOVE))
	{

		MOUSEHOOKSTRUCT* pMH = (MOUSEHOOKSTRUCT*) lParam;

		// If the previous message was for COXSizableMiniDockFrameWnd and the current is not
		// we need to update the caption buttons
		COXSizableMiniDockFrameWnd* pPrev = DYNAMIC_DOWNCAST(COXSizableMiniDockFrameWnd,
			CWnd::FromHandlePermanent(m_hwndPrevMouseMoveWnd));
		COXSizableMiniDockFrameWnd* pCurrent = DYNAMIC_DOWNCAST(COXSizableMiniDockFrameWnd,
			CWnd::FromHandlePermanent(pMH->hwnd));

		if (pPrev != NULL && pCurrent != pPrev)
		{
			// The mouse just left the mini frame window
			pPrev->GetMiniFrameSkin()->DrawCaptionButtons(pPrev);
		}
		m_hwndPrevMouseMoveWnd = pMH->hwnd;
	}

	return CallNextHookEx(m_hMouseHook, nCode, wParam, lParam);
}

void COXSizableMiniDockFrameWnd::OnDestroy() 
{
	// Unhook the mouse
	if (m_hMouseHook)
	{
		::UnhookWindowsHookEx(m_hMouseHook);
		m_hMouseHook = NULL;
	}

	CMiniDockFrameWnd::OnDestroy();
}

void COXSizableMiniDockFrameWnd::OnNcRButtonDown(UINT /*nHitTest*/, CPoint point) 
{
	// Display the system menu					
#if _MFC_VER < 0x0700		
	InvertSysMenu();
#endif
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	int nCmd = pSysMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RETURNCMD, point.x, point.y, this);
#if _MFC_VER < 0x0700	
	InvertSysMenu();
#endif	
	if (nCmd != 0)
	{
		SendMessage(WM_SYSCOMMAND, nCmd, 0);
	}
	return;
}

void COXSizableMiniDockFrameWnd::OnNcMouseMove(UINT nHitTest, CPoint point) 
{
	GetMiniFrameSkin()->DrawCaptionButtons(this);	
	CMiniDockFrameWnd::OnNcMouseMove(nHitTest, point);
}

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