2025-11-27 16:46:48 +09:00

372 lines
9.3 KiB
C++

// ==========================================================================
// Class Implementation : COXDockTabCtrl
// ==========================================================================
// Source file : OXDockTabCtrl.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.
#include "stdafx.h"
#include "OXDockTabCtrl.h"
#include "OXCoolToolBar.h"
#include "OXSizeCtrlBar.h"
#include "OXSizeDockBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COXDockTabCtrl
COXDockTabCtrl::COXDockTabCtrl(COXSizeDockBar* pSizeDockBar)
{
m_pSizeDockBar = pSizeDockBar;
m_pLastSelectedBar = NULL;
}
COXDockTabCtrl::~COXDockTabCtrl()
{
}
BEGIN_MESSAGE_MAP(COXDockTabCtrl, COXSkinnedTabCtrl)
//{{AFX_MSG_MAP(COXDockTabCtrl)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelChange)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void COXDockTabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptLButtonDown = point;
COXSkinnedTabCtrl::OnLButtonDown(nFlags, point);
}
void COXDockTabCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
// In order to start dragging the left button must be down and the current point
// must be at least 3 pixels away from the point where the button was pressed
if ((nFlags & MK_LBUTTON) &&
(abs(point.x - m_ptLButtonDown.x) > 3 || abs(point.y - m_ptLButtonDown.y) > 3))
{
TCHITTESTINFO thti;
thti.pt = point;
int iIndex = HitTest(&thti);
if (iIndex != -1)
{
CControlBar* pBar = GetBar(iIndex);
// Handle COXCoolToolBar
COXCoolToolBar* pToolBar = DYNAMIC_DOWNCAST(COXCoolToolBar, pBar);
if (pToolBar)
{
// We have a toolbar
pToolBar->SaveMouseOffset(CPoint(0, 0));
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
pControlBar->SaveMouseOffset(CPoint(0, 0));
pControlBar->SetCapture();
pControlBar->m_bDragging = true;
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
return;
}
}
}
COXSkinnedTabCtrl::OnMouseMove(nFlags, point);
}
void COXDockTabCtrl::OnSelChange(NMHDR* /*pNMHDR*/, LRESULT* pResult)
{
// TODO: Add your control notification handler code here
ShowSelectedTab();
*pResult = 0;
}
// Inserts the given control bar as a new tab
void COXDockTabCtrl::InsertTab(CControlBar* pBar, int iIndex, BOOL bShowSelectedTab)
{
// If this is the only control bar in the dock bar do nothing
int iSizeControlBarCount = m_pSizeDockBar->GetSizeControlBarCount(pBar);
if (iSizeControlBarCount == 0)
return;
// Add a tab for all other size control bars that are docked but not tabbed
int i = 0;
for (i = 0; i < m_pSizeDockBar->m_arrBars.GetSize(); i++)
{
COXSizeControlBar* pSizeBar = DYNAMIC_DOWNCAST(COXSizeControlBar, m_pSizeDockBar->GetDockedControlBar(i));
if (pSizeBar != NULL && pSizeBar != pBar && FindTab(pSizeBar) == -1)
{
CString strTextOther;
pSizeBar->GetWindowText(strTextOther);
TCITEM tciOther;
tciOther.mask = TCIF_TEXT | TCIF_PARAM;
tciOther.pszText = strTextOther.GetBuffer(strTextOther.GetLength());
tciOther.lParam = (LPARAM) pSizeBar;
//Check added for visibility so that hidden control
//bars don't get shown - Nish - Feb 15th 2005
if(pSizeBar->IsWindowVisible())
InsertItem(0, &tciOther);
}
}
// Insert this control bar to the tab control
CString strText;
pBar->GetWindowText(strText);
TCITEM tci;
tci.mask = TCIF_TEXT | TCIF_PARAM;
tci.pszText = strText.GetBuffer(strText.GetLength());
tci.lParam = (LPARAM) pBar;
InsertItem(iIndex, &tci);
SetCurSel(iIndex);
// Reshresh the tab control
m_pSizeDockBar->PositionTabCtrl();
if (bShowSelectedTab)
ShowSelectedTab();
else
{
int iSelected = GetCurSel();
for (i = 0; i < GetItemCount(); i++)
{
CControlBar* pBar = GetBar(i);
if (iSelected != i)
pBar->GetDockingFrame()->ShowControlBar(pBar, FALSE, TRUE); // hide
}
}
}
void COXDockTabCtrl::ShowSelectedTab()
{
int iSelected = GetCurSel();
// Show first
for (int i = 0; i < GetItemCount(); i++)
{
CControlBar* pBar = GetBar(i);
if (iSelected == i)
{
pBar->GetDockingFrame()->ShowControlBar(pBar, TRUE, TRUE); // show
}
else
{
pBar->GetDockingFrame()->ShowControlBar(pBar, FALSE, TRUE); // hide
}
}
CRect rect;
m_pSizeDockBar->GetClientRect(rect);
CControlBar* pBar = GetBar(iSelected);
if (pBar != NULL)
{
COXSizeControlBar* pSizeBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pBar);
if (m_pSizeDockBar->IsBarHorizontal())
{
if (m_pLastSelectedBar != NULL)
{
pSizeBar->m_HorzDockSize.cx = m_pLastSelectedBar->m_HorzDockSize.cx;
}
m_pLastSelectedBar = pSizeBar;
}
else // vertical
{
CFrameWnd* pMF = (CFrameWnd*) GetParentFrame();//AfxGetMainWnd();
if (pMF != NULL)
{
if (pMF->GetControlBar(AFX_IDW_DOCKBAR_LEFT) == m_pSizeDockBar)
rect.right -= 3;
if (pMF->GetControlBar(AFX_IDW_DOCKBAR_RIGHT) == m_pSizeDockBar)
rect.left += 4;
}
rect.bottom -= m_pSizeDockBar->GetTabHeight();
pBar->MoveWindow(rect, TRUE);
COXSizeControlBar* pSizeBar = DYNAMIC_DOWNCAST(COXSizeControlBar, pBar);
if (pSizeBar)
{
pSizeBar->m_VertDockSize.cx = rect.Width();
pSizeBar->m_VertDockSize.cy = rect.Height() + 5;
}
}
}
}
void COXDockTabCtrl::RemoveTab(CControlBar* pBar)
{
// If there are not tabs just exit
if (GetItemCount() == 0)
return;
// If there is only one other tab left we need to remove it as well
if (m_pSizeDockBar->GetSizeControlBarCount(pBar) == 1)
{
COXSizeControlBar* pOther = m_pSizeDockBar->GetFirstDockedSizeControlBar(pBar);
int iOtherIndex = FindTab(pOther);
DeleteItem(iOtherIndex);
pOther->GetDockingFrame()->ShowControlBar(pOther, TRUE, TRUE);
}
// Remove this tab
int iIndex = FindTab(pBar);
DeleteItem(iIndex);
if (GetItemCount() > 1)
{
// Set the current selection to the previous tab
if (iIndex != 0)
SetCurSel(iIndex - 1);
else
SetCurSel(0);
ShowSelectedTab();
}
}
// This function searched the tab control for the given control bar and returns its
// index or -1 if not found.
int COXDockTabCtrl::FindTab(CControlBar* pBar)
{
for (int i = 0; i < GetItemCount(); i++)
{
TCITEM tci;
tci.mask = TCIF_PARAM;
GetItem(i, &tci);
if (tci.lParam == (LPARAM) pBar)
return i;
}
return -1;
}
// If the point is over the tab control this function returns the index where
// the new tab should be inserted. If the point is not over the tab control it
// returns -1
int COXDockTabCtrl::HitTestTabControl(CPoint point, CControlBar* /*pBar*/)
{
// Deterine the rectangle of the buttons
CRect rectTabButtons;
m_pSizeDockBar->GetWindowRect(rectTabButtons);
rectTabButtons.top = rectTabButtons.bottom - 48;
if (rectTabButtons.PtInRect(point))
{
// Determine the actual button
TCHITTESTINFO thti;
ScreenToClient(&point);
thti.pt = point;
int iIndex = HitTest(&thti);
if (iIndex == -1)
return 0;
return iIndex;
}
// If there are more when 1 tabs already the test area should cover the entire dock window
// and the new tab should be inserted at the end
// int iTabCount = GetItemCount();
// if (iTabCount > 0)
// {
// CRect rectDockBar;
// m_pSizeDockBar->GetWindowRect(rectDockBar);
// rectDockBar.InflateRect(20, 20);
// if (rectDockBar.PtInRect(point))
// return iTabCount;
// }
return -1;
}
// Moves the tab from the old position to the new position
void COXDockTabCtrl::RepositionTabs(int iOldIndex, int iNewIndex, CPoint point)
{
// To avoid flashing only reposition if the mouse cursor is behind the midpoint
// of the next or previous item
CRect rectNew;
GetItemRect(iNewIndex, rectNew);
ScreenToClient(&point);
if (iOldIndex < iNewIndex)
{
// The new tab is to the right
if (point.x < rectNew.CenterPoint().x)
return; // the mouse cursor is not far enough to the right
}
else
{
// The new tab is to the left
if (point.x > rectNew.CenterPoint().x)
return; // the mouse cursor is not far enough to the left
}
TCHAR szBuffer[256];
TCITEM tci;
tci.mask = TCIF_TEXT | TCIF_PARAM;
tci.pszText = szBuffer;
tci.cchTextMax = 256;
GetItem(iOldIndex, &tci);
DeleteItem(iOldIndex);
InsertItem(iNewIndex, &tci);
}
CControlBar* COXDockTabCtrl::GetBar(int iIndex)
{
TCITEM tci;
tci.mask = TCIF_PARAM;
GetItem(iIndex, &tci);
return (CControlBar*) tci.lParam;
}
int COXDockTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COXSkinnedTabCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
m_font.CreatePointFont(80, _T("MS Sans Serif"));
SetFont(&m_font);
SetPadding(CSize(12, 4));
return 0;
}