📄 bardock.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#ifdef AFX_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// CDockBar
BEGIN_MESSAGE_MAP(CDockBar, CControlBar)
//{{AFX_MSG_MAP(CDockBar)
ON_WM_NCCALCSIZE()
ON_WM_NCPAINT()
ON_WM_WINDOWPOSCHANGING()
ON_WM_PAINT()
ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDockBar construction
CDockBar::CDockBar(BOOL bFloating)
{
m_bFloating = bFloating;
m_bAutoDelete = TRUE;
m_arrBars.Add(NULL);
m_bLayoutQuery = FALSE;
m_rectLayout.SetRectEmpty();
// assume no margins
m_cxLeftBorder = m_cxRightBorder = m_cyBottomBorder = m_cyTopBorder = 0;
}
CDockBar::~CDockBar()
{
for (int i = 0; i < m_arrBars.GetSize(); i++)
{
CControlBar* pBar = GetDockedControlBar(i);
if (pBar != NULL && pBar->m_pDockBar == this)
pBar->m_pDockBar = NULL;
}
}
BOOL CDockBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
{
ASSERT(pParentWnd != NULL);
ASSERT_KINDOF(CFrameWnd, pParentWnd);
// save the style
m_dwStyle = (dwStyle & CBRS_ALL);
VERIFY(AfxDeferRegisterClass(AFX_WNDCONTROLBAR_REG));
// create the HWND
CRect rect;
rect.SetRectEmpty();
// Note: Parent must resize itself for control bar to be resized
return CWnd::Create(_afxWndControlBar, NULL, dwStyle, rect, pParentWnd, nID);
}
BOOL CDockBar::IsDockBar() const
{
return TRUE;
}
int CDockBar::GetDockedCount() const
{
int nCount = 0;
for (int i = 0; i < m_arrBars.GetSize(); i++)
{
if (GetDockedControlBar(i) != NULL)
nCount++;
}
return nCount;
}
int CDockBar::GetDockedVisibleCount() const
{
int nCount = 0;
for (int i = 0; i < m_arrBars.GetSize(); i++)
{
CControlBar* pBar = STATIC_DOWNCAST(CControlBar, (CObject*)GetDockedControlBar(i));
if (pBar != NULL && pBar->IsVisible())
nCount++;
}
return nCount;
}
/////////////////////////////////////////////////////////////////////////////
// CDockBar operations
void CDockBar::DockControlBar(CControlBar* pBar, LPCRECT lpRect)
{
ASSERT_VALID(this);
ASSERT_VALID(pBar);
ASSERT_KINDOF(CControlBar, pBar);
CRect rectBar;
pBar->GetWindowRect(&rectBar);
if (pBar->m_pDockBar == this && (lpRect == NULL || rectBar == *lpRect))
{
// already docked and no change in position
return;
}
// set CBRS_FLOAT_MULTI style if docking bar has it
if (m_bFloating && (pBar->m_dwDockStyle & CBRS_FLOAT_MULTI))
m_dwStyle |= CBRS_FLOAT_MULTI;
m_dwStyle &= ~(CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
m_dwStyle |= pBar->m_dwStyle & (CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
if (!(m_dwStyle & CBRS_FLOAT_MULTI))
{
TCHAR szTitle[_MAX_PATH];
pBar->GetWindowText(szTitle, _countof(szTitle));
AfxSetWindowText(m_hWnd, szTitle);
}
// align correctly and turn on all borders
DWORD dwStyle = pBar->GetBarStyle();
dwStyle &= ~(CBRS_ALIGN_ANY);
dwStyle |= (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;
if (m_bFloating)
dwStyle |= CBRS_FLOATING;
else
dwStyle &= ~CBRS_FLOATING;
pBar->SetBarStyle(dwStyle);
// hide first if changing to a new docking site to avoid flashing
BOOL bShow = FALSE;
if (pBar->m_pDockBar != this && pBar->IsWindowVisible())
{
pBar->SetWindowPos(NULL, 0, 0, 0, 0,
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_HIDEWINDOW);
bShow = TRUE;
}
int nPos = -1;
if (lpRect != NULL)
{
// insert into appropriate row
CRect rect(lpRect);
ScreenToClient(&rect);
CPoint ptMid(rect.left + rect.Width()/2, rect.top + rect.Height()/2);
nPos = Insert(pBar, rect, ptMid);
// position at requested position
pBar->SetWindowPos(NULL, rect.left, rect.top, rect.Width(),
rect.Height(), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}
else
{
// always add on current row, then create new one
m_arrBars.Add(pBar);
m_arrBars.Add(NULL);
// align off the edge initially
pBar->SetWindowPos(NULL, -afxData.cxBorder2, -afxData.cyBorder2, 0, 0,
SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}
// attach it to the docking site
if (pBar->GetParent() != this)
pBar->SetParent(this);
if (pBar->m_pDockBar == this)
pBar->m_pDockBar->RemoveControlBar(pBar, nPos);
else if (pBar->m_pDockBar != NULL)
pBar->m_pDockBar->RemoveControlBar(pBar, -1, m_bFloating && !pBar->m_pDockBar->m_bFloating);
pBar->m_pDockBar = this;
if (bShow)
{
ASSERT(!pBar->IsWindowVisible());
pBar->SetWindowPos(NULL, 0, 0, 0, 0,
SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);
}
// remove any place holder for pBar in this dockbar
RemovePlaceHolder(pBar);
// get parent frame for recalc layout
CFrameWnd* pFrameWnd = GetDockingFrame();
pFrameWnd->DelayRecalcLayout();
}
void CDockBar::ReDockControlBar(CControlBar* pBar, LPCRECT lpRect)
{
ASSERT_VALID(this);
ASSERT_VALID(pBar);
ASSERT_KINDOF(CControlBar, pBar);
ASSERT(pBar->m_pDockBar != this); // can't redock here if already docked here
CRect rectBar;
pBar->GetWindowRect(&rectBar);
if (pBar->m_pDockBar == this && (lpRect == NULL || rectBar == *lpRect))
{
// already docked and no change in position
return;
}
// set CBRS_FLOAT_MULTI style if docking bar has it
if (m_bFloating && (pBar->m_dwDockStyle & CBRS_FLOAT_MULTI))
m_dwStyle |= CBRS_FLOAT_MULTI;
m_dwStyle &= ~(CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
m_dwStyle |= pBar->m_dwStyle & (CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
if (!(m_dwStyle & CBRS_FLOAT_MULTI))
{
TCHAR szTitle[_MAX_PATH];
pBar->GetWindowText(szTitle, _countof(szTitle));
AfxSetWindowText(m_hWnd, szTitle);
}
// align correctly and turn on all borders
DWORD dwStyle = pBar->GetBarStyle();
dwStyle &= ~(CBRS_ALIGN_ANY);
dwStyle |= (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;
if (m_bFloating)
dwStyle |= CBRS_FLOATING;
else
dwStyle &= ~CBRS_FLOATING;
pBar->SetBarStyle(dwStyle);
int nPos = FindBar((CControlBar*)_AfxGetDlgCtrlID(pBar->m_hWnd));
if (nPos > 0)
m_arrBars[nPos] = pBar;
if (lpRect != NULL)
{
CRect rect(lpRect);
ScreenToClient(&rect);
if (nPos < 1)
{
CPoint ptMid(rect.left + rect.Width()/2, rect.top + rect.Height()/2);
nPos = Insert(pBar, rect, ptMid);
}
// position at requested position
pBar->SetWindowPos(NULL, rect.left, rect.top, rect.Width(),
rect.Height(), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}
else
{
if (nPos < 1)
{
// always add on current row, then create new one
m_arrBars.Add(pBar);
m_arrBars.Add(NULL);
}
// align off the edge initially
pBar->SetWindowPos(NULL, -afxData.cxBorder2, -afxData.cyBorder2, 0, 0,
SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
}
// attach it to the docking site
if (pBar->GetParent() != this)
pBar->SetParent(this);
if (pBar->m_pDockBar != NULL)
pBar->m_pDockBar->RemoveControlBar(pBar);
pBar->m_pDockBar = this;
// get parent frame for recalc layout
CFrameWnd* pFrameWnd = GetDockingFrame();
pFrameWnd->DelayRecalcLayout();
}
void CDockBar::RemovePlaceHolder(CControlBar* pBar)
{
// remove remembered docking position
if (HIWORD(pBar) != 0)
pBar = (CControlBar*)_AfxGetDlgCtrlID(pBar->m_hWnd);
int nOldPos = FindBar(pBar);
if (nOldPos > 0)
{
m_arrBars.RemoveAt(nOldPos);
// remove section indicator (NULL) if nothing else in section
if (m_arrBars[nOldPos-1] == NULL && m_arrBars[nOldPos] == NULL)
m_arrBars.RemoveAt(nOldPos);
}
}
BOOL CDockBar::RemoveControlBar(CControlBar* pBar, int nPosExclude, int nAddPlaceHolder)
{
ASSERT(nAddPlaceHolder == 1 || nAddPlaceHolder == 0 || nAddPlaceHolder == -1);
ASSERT_VALID(this);
ASSERT(pBar != NULL);
int nPos = FindBar(pBar, nPosExclude);
ASSERT(nPos > 0);
if (nAddPlaceHolder == 1)
{
m_arrBars[nPos] = (void*)_AfxGetDlgCtrlID(pBar->m_hWnd);
// check for already existing place holder
int nPosOld = FindBar((CControlBar*)m_arrBars[nPos], nPos);
if (nPosOld > 0)
{
m_arrBars.RemoveAt(nPos);
// remove section indicator (NULL) if nothing else in section
if (m_arrBars[nPos-1] == NULL && m_arrBars[nPos] == NULL)
m_arrBars.RemoveAt(nPos);
}
}
else
{
m_arrBars.RemoveAt(nPos);
if (m_arrBars[nPos-1] == NULL && m_arrBars[nPos] == NULL)
m_arrBars.RemoveAt(nPos);
// Remove any pre-existing place holders.
if (nAddPlaceHolder != -1)
RemovePlaceHolder(pBar);
}
// don't do anything more in the shutdown case!
if (pBar->m_pDockContext == NULL)
return FALSE;
// get parent frame for recalc layout/frame destroy
CFrameWnd* pFrameWnd = GetDockingFrame();
if (m_bFloating && GetDockedVisibleCount() == 0)
{
if (GetDockedCount() == 0)
{
pFrameWnd->DestroyWindow();
return TRUE; // Self-Destruct
}
else
pFrameWnd->ShowWindow(SW_HIDE);
}
else
pFrameWnd->DelayRecalcLayout();
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CDockBar layout
CSize CDockBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
ASSERT_VALID(this);
CSize sizeFixed = CControlBar::CalcFixedLayout(bStretch, bHorz);
// get max size
CSize sizeMax;
if (!m_rectLayout.IsRectEmpty())
sizeMax = m_rectLayout.Size();
else
{
CRect rectFrame;
CFrameWnd* pFrame = GetParentFrame();
pFrame->GetClientRect(&rectFrame);
sizeMax = rectFrame.Size();
}
// prepare for layout
AFX_SIZEPARENTPARAMS layout;
layout.hDWP = m_bLayoutQuery ?
NULL : ::BeginDeferWindowPos(m_arrBars.GetSize());
CPoint pt(-afxData.cxBorder2, -afxData.cyBorder2);
int nWidth = 0;
BOOL bWrapped = FALSE;
// layout all the control bars
for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
{
CControlBar* pBar = GetDockedControlBar(nPos);
void* pVoid = m_arrBars[nPos];
if (pBar != NULL)
{
if (pBar->IsVisible())
{
// get ideal rect for bar
DWORD dwMode = 0;
if ((pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) &&
(pBar->m_dwStyle & CBRS_FLOATING))
dwMode |= LM_HORZ | LM_MRUWIDTH;
else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ)
dwMode |= LM_HORZ | LM_HORZDOCK;
else
dwMode |= LM_VERTDOCK;
CSize sizeBar = pBar->CalcDynamicLayout(-1, dwMode);
CRect rect(pt, sizeBar);
// get current rect for bar
CRect rectBar;
pBar->GetWindowRect(&rectBar);
ScreenToClient(&rectBar);
if (bHorz)
{
// Offset Calculated Rect out to Actual
if (rectBar.left > rect.left && !m_bFloating)
rect.OffsetRect(rectBar.left - rect.left, 0);
// If ControlBar goes off the right, then right justify
if (rect.right > sizeMax.cx && !m_bFloating)
{
int x = rect.Width() - afxData.cxBorder2;
x = max(sizeMax.cx - x, pt.x);
rect.OffsetRect(x - rect.left, 0);
}
// If ControlBar has been wrapped, then left justify
if (bWrapped)
{
bWrapped = FALSE;
rect.OffsetRect(-(rect.left + afxData.cxBorder2), 0);
}
// If ControlBar is completely invisible, then wrap it
else if ((rect.left >= (sizeMax.cx - afxData.cxBorder2)) &&
(nPos > 0) && (m_arrBars[nPos - 1] != NULL))
{
m_arrBars.InsertAt(nPos, (CObject*)NULL);
pBar = NULL; pVoid = NULL;
bWrapped = TRUE;
}
if (!bWrapped)
{
if (rect != rectBar)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -