799 lines
47 KiB
C++
799 lines
47 KiB
C++
// ===================================================================================
|
||
// 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);
|
||
}
|