⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bcgtabwnd.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This source code is a part of BCGControlBar library.
// You may use, compile or redistribute it as part of your application 
// for free. You cannot redistribute it as a part of a software development 
// library without the agreement of the author. If the sources are 
// distributed along with the application, you should leave the original 
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES on your own risk.
// 
// Stas Levin <stas@iet.co.il>
//*******************************************************************************

// bcgtabwnd.cpp : implementation file
//

#include "stdafx.h"
#include "bcgtabwnd.h"
#include "globals.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

UINT BCGM_CHANGE_ACTIVE_TAB = ::RegisterWindowMessage (_T("BCGM_ONCHANGE_ACTIVE_TAB"));
UINT BCGM_ON_HSCROLL		= ::RegisterWindowMessage (_T("BCGM_ON_HSCROLL"));

/////////////////////////////////////////////////////////////////////////////
// CBCGTabInfo

class CBCGTabInfo : public CObject
{
	friend class CBCGTabWnd;

	CBCGTabInfo(const CString&	strText,
				const UINT		uiIcon,
				CWnd*			pWnd) :
		m_pWnd (pWnd),
		m_uiIcon (uiIcon)
	{
		m_strText = m_strDisplayedText = strText;
		m_rect.SetRectEmpty ();
		m_nFullWidth = 0;
	}

	CString		m_strText;
	CString		m_strDisplayedText;
	const UINT	m_uiIcon;
	CRect		m_rect;
	CWnd*		m_pWnd;
	int			m_nFullWidth;
};

/////////////////////////////////////////////////////////////////////////////
// CBCGTabWnd

#define TAB_BORDER_SIZE	3
#define TEXT_MARGIN		4
#define IMAGE_MARGIN	4
#define MIN_SROLL_WIDTH (::GetSystemMetrics (SM_CXHSCROLL) * 2)
#define SPLITTER_WIDTH	5
#define TABS_FONT		_T("Arial")

CBCGTabWnd::CBCGTabWnd()
{
	m_iTabsNum = 0;
	m_iActiveTab = -1;
	m_sizeImage = CSize (0, 0);
	m_bFlat = FALSE;
	m_bSharedScroll = FALSE;
	m_rectTabsArea.SetRectEmpty ();
	m_rectWndArea.SetRectEmpty ();
	m_nTabsHorzOffset = 0;
	m_nTabsHorzOffsetMax = 0;
	m_nTabsTotalWidth = 0;
	m_nHorzScrollWidth = 0;
	m_nScrollBarRight = 0;
	m_rectTabSplitter.SetRectEmpty ();
	m_bTrackSplitter = FALSE;

	m_clrActiveTabBk = (COLORREF) -1;
	m_clrActiveTabFg = (COLORREF) -1;
	
	m_nTabsHeight = 0;
}
//***************************************************************************************
CBCGTabWnd::~CBCGTabWnd()
{
}

BEGIN_MESSAGE_MAP(CBCGTabWnd, CWnd)
	//{{AFX_MSG_MAP(CBCGTabWnd)
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	ON_WM_CREATE()
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_HSCROLL()
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_CANCELMODE()
	ON_WM_SYSCOLORCHANGE()
	ON_WM_SETTINGCHANGE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CBCGTabWnd::Create (Style style, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
	m_bFlat = (style == STYLE_FLAT) || (style == STYLE_FLAT_SHARED_HORZ_SCROLL);
	m_bSharedScroll = style == STYLE_FLAT_SHARED_HORZ_SCROLL;

	if (!m_bFlat && m_bSharedScroll)
	{
		//--------------------------------------
		// Only flat tab has a shared scrollbar!
		//--------------------------------------
		ASSERT (FALSE);
		m_bSharedScroll = FALSE;
	}

	return CWnd::Create (NULL, _T(""), WS_CHILD | WS_VISIBLE, rect,
		pParentWnd, nID);
}

/////////////////////////////////////////////////////////////////////////////
// CBCGTabWnd message handlers

void CBCGTabWnd::OnDestroy() 
{
	for (int i = 0; i < m_iTabsNum; i ++)
	{
		CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [i];
		ASSERT_VALID (pTab);

		pTab->m_pWnd->DestroyWindow ();
		delete pTab;
	}

	CWnd::OnDestroy();
}
//***************************************************************************************
void CBCGTabWnd::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	CRect rectClient;
	GetClientRect (&rectClient);

	CBrush* pOldBrush = dc.SelectObject (&globalData.brBtnFace);
	ASSERT (pOldBrush != NULL);

	CPen penDrak (PS_SOLID, 1, globalData.clrBtnDkShadow);
	CPen* pOldPen = (CPen*) dc.SelectObject (&penDrak);
	ASSERT(pOldPen != NULL);

	CRect rectTabs = rectClient;
	rectTabs.top = m_rectTabsArea.top - TAB_BORDER_SIZE;
	dc.FillRect (rectTabs, &globalData.brBtnFace);

	CRect rectFrame = rectClient;

	if (m_bFlat)
	{
		//---------------------------
		// Draw line bellow the tabs:
		//---------------------------
		dc.MoveTo (rectFrame.left, m_rectTabsArea.top);
		dc.LineTo (rectFrame.right, m_rectTabsArea.top);
	}
	else
	{
		rectFrame.bottom = m_rectTabsArea.top;
	}

	//-----------------------------------------------------
	// Draw wide 3-dimensional frame around the Tabs area:
	//-----------------------------------------------------
	dc.Draw3dRect (&rectFrame, globalData.clrBtnHilite, globalData.clrBtnDkShadow);
	
	rectFrame.DeflateRect (1, 1);
	dc.Draw3dRect (&rectFrame,
				globalData.clrBtnLight, globalData.clrBtnShadow);

	rectFrame.DeflateRect (1, 1);

	if (rectFrame.Width () > 0 && rectFrame.Height () > 0)
	{
		dc.PatBlt (rectFrame.left, rectFrame.top, TAB_BORDER_SIZE, rectFrame.Height (), PATCOPY);
		dc.PatBlt (rectFrame.left, rectFrame.top, rectFrame.Width (), TAB_BORDER_SIZE, PATCOPY);
		dc.PatBlt (rectFrame.right - TAB_BORDER_SIZE, rectFrame.top, TAB_BORDER_SIZE, rectFrame.Height (), PATCOPY);
		dc.PatBlt (rectFrame.left, rectFrame.bottom - TAB_BORDER_SIZE, rectFrame.Width (), TAB_BORDER_SIZE, PATCOPY);

		rectFrame.DeflateRect (TAB_BORDER_SIZE - 2, TAB_BORDER_SIZE - 2);

		if (rectFrame.Width () > 0 && rectFrame.Height () > 0)
		{
			dc.Draw3dRect (&rectFrame,
						globalData.clrBtnDkShadow, globalData.clrBtnHilite);
		}
	}

	CFont* pOldFont = dc.SelectObject (m_bFlat ?	&m_fntTabs : 
													&globalData.fontRegular);
	ASSERT(pOldFont != NULL);

	dc.SetBkMode (TRANSPARENT);
	dc.SetTextColor (globalData.clrBtnText);

	if (m_rectTabsArea.Width () > 2 * TAB_BORDER_SIZE + 1 &&
		m_rectTabsArea.Height () > 2 * TAB_BORDER_SIZE + 1)
	{
		//-----------
		// Draw tabs:
		//-----------
		if (m_bFlat)
		{
			CRgn rgn;
			rgn.CreateRectRgnIndirect (m_rectTabsArea);

			dc.SelectClipRgn (&rgn);
		}

		for (int i = 0; i < m_iTabsNum; i ++)
		{
			CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [i];
			ASSERT_VALID (pTab);

			if (m_bFlat)
			{
				if (i != m_iActiveTab)	// Draw active button last
				{
					DrawFlatTab (&dc, pTab, FALSE);
				}
			}
			else
			{
				Draw3DTab (&dc, pTab, i == m_iActiveTab);
			}
		}

		if (m_bFlat && m_iActiveTab >= 0)
		{
			//-----------------
			// Draw active tab:
			//-----------------
			CBCGTabInfo* pTabActive = (CBCGTabInfo*) m_arTabs [m_iActiveTab];
			ASSERT_VALID (pTabActive);

			dc.SelectObject (&m_brActiveTab);
			dc.SelectObject (&m_fntTabsBold);
			dc.SetTextColor (GetActiveTabTextColor ());

			DrawFlatTab (&dc, pTabActive, TRUE);

			//---------------------------------
			// Draw line bellow the active tab:
			//---------------------------------
			CPen penLight (PS_SOLID, 1, GetActiveTabColor ());
			dc.SelectObject (&penLight);

			dc.MoveTo (pTabActive->m_rect.left + 1, pTabActive->m_rect.top);
			dc.LineTo (pTabActive->m_rect.right, pTabActive->m_rect.top);
		}

		if (m_bFlat)
		{
			dc.SelectClipRgn (NULL);
		}
	}

	if (!m_rectTabSplitter.IsRectEmpty ())
	{
		dc.FillRect (m_rectTabSplitter, &globalData.brBtnFace);

		CRect rectTabSplitter = m_rectTabSplitter;

		dc.Draw3dRect (rectTabSplitter,
			globalData.clrBtnDkShadow, globalData.clrBtnShadow);
		rectTabSplitter.DeflateRect (1, 1);
		dc.Draw3dRect (rectTabSplitter,
			globalData.clrBtnHilite, globalData.clrBtnShadow);
	}
	
	dc.SelectObject (pOldFont);
	dc.SelectObject (pOldBrush);
	dc.SelectObject (pOldPen);
}
//***************************************************************************************
void CBCGTabWnd::OnSize(UINT nType, int cx, int cy) 
{
	CWnd::OnSize(nType, cx, cy);

	int nTabsAreaWidth = cx - 4 * ::GetSystemMetrics (SM_CXVSCROLL) 
							- 2 * TAB_BORDER_SIZE;

	if (nTabsAreaWidth <= MIN_SROLL_WIDTH)
	{
		m_nHorzScrollWidth = 0;
	}
	else if (nTabsAreaWidth / 2 > MIN_SROLL_WIDTH)
	{
		m_nHorzScrollWidth = nTabsAreaWidth / 2;
	}
	else
	{
		m_nHorzScrollWidth = nTabsAreaWidth; 
	}

	RecalcLayout ();
	SynchronizeScrollBar ();
}
//***************************************************************************************
void CBCGTabWnd::AddTab (CWnd* pNewWnd, LPCTSTR lpszName, UINT uiImageId)
{
	ASSERT_VALID (this);
	ASSERT_VALID (pNewWnd);
	ASSERT (pNewWnd->GetParent()->GetSafeHwnd () == GetSafeHwnd ());
	ASSERT (lpszName != NULL);

	if (m_bFlat)
	{
		ASSERT (uiImageId == -1);
		uiImageId = (UINT) -1;
	}
	else if (m_sizeImage != CSize (0, 0))
	{
		ASSERT (uiImageId != (UINT) -1);
	}

	m_arTabs.SetAtGrow (m_iTabsNum ++, 
		new CBCGTabInfo (lpszName, uiImageId, pNewWnd));

	if (!m_bFlat)
	{
		CRect rectEmpty (0, 0, 0, 0);
		m_ToolTip.AddTool (this, lpszName, &rectEmpty, m_iTabsNum);
	}

	RecalcLayout ();

	if (m_iTabsNum == 1)
	{
		//----------------------------------------
		// First tab automatically becames active:
		//----------------------------------------
		SetActiveTab (0);
	}

	if (GetActiveWnd () != pNewWnd)
	{
		pNewWnd->ShowWindow (SW_HIDE);
	}
}
//***************************************************************************************
BOOL CBCGTabWnd::RemoveTab (int iTab)
{
	if (iTab < 0 || iTab >= m_iTabsNum)
	{
		TRACE(_T("RemoveTab: illegal tab number %d\n"), iTab);
		return FALSE;
	}

	if (m_iTabsNum == 1)
	{
		RemoveAllTabs ();
		return TRUE;
	}

	CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [iTab];
	ASSERT_VALID (pTab);

	//----------------------------
	// Detach tab from collection:
	//----------------------------
	m_arTabs.RemoveAt (iTab);
	m_iTabsNum --;

	//-----------------------------------
	// Destroy tab window and delete tab:
	//-----------------------------------
	ASSERT_VALID (pTab->m_pWnd);
	pTab->m_pWnd->DestroyWindow ();
	delete pTab;

	int iActiveTab = -1;
	if (m_iActiveTab >= iTab)
	{
		iActiveTab = max (0, min (m_iTabsNum, m_iActiveTab - 1));
		m_iActiveTab = -1;
	}

	RecalcLayout ();
	SetActiveTab (iActiveTab);
	GetParent ()->SendMessage (BCGM_CHANGE_ACTIVE_TAB, m_iActiveTab);

	return TRUE;
}
//***************************************************************************************
void CBCGTabWnd::RemoveAllTabs ()
{
	for (int i = 0; i < m_iTabsNum; i ++)
	{
		CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [i];
		ASSERT_VALID (pTab);

		pTab->m_pWnd->DestroyWindow ();
		delete pTab;
	}

	m_arTabs.RemoveAll ();

	m_iTabsNum = 0;
	m_iActiveTab = -1;

	RecalcLayout ();
}
//***************************************************************************************
BOOL CBCGTabWnd::SetActiveTab (int iTab)
{
	if (iTab < 0 || iTab >= m_iTabsNum)
	{
		TRACE(_T("SetActiveTab: illegal tab number %d\n"), iTab);
		return FALSE;
	}

	if (m_iActiveTab == iTab)	// Already active, do nothing
	{
		return TRUE;
	}

	if (m_iActiveTab != -1)
	{
		//--------------------
		// Hide active window:
		//--------------------
		GetActiveWnd()->ShowWindow (SW_HIDE);
	}

	m_iActiveTab = iTab;
	
	//------------------------
	// Show new active window:
	//------------------------
	HideActiveWindowHorzScrollBar ();
	GetActiveWnd ()->ShowWindow (SW_SHOW);

	//----------------------------------------------------------------------
	// Small trick: to adjust active window scroll sizes, I should change an
	// active window size twice (+1 pixel and -1 pixel):
	//----------------------------------------------------------------------
	GetActiveWnd ()->SetWindowPos (NULL,
			-1, -1,
			m_rectWndArea.Width (), m_rectWndArea.Height (),
			SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
	GetActiveWnd ()->SetWindowPos (NULL,
			-1, -1,
			m_rectWndArea.Width () - 1, m_rectWndArea.Height (),
			SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);

	EnsureVisible (m_iActiveTab);

	if (m_bFlat)
	{
		SynchronizeScrollBar ();
	}

	//-------------
	// Redraw tabs:
	//-------------
	Invalidate ();
	UpdateWindow ();

	return TRUE;
}
//***************************************************************************************
void CBCGTabWnd::AdjustTabs ()
{
	m_nTabsTotalWidth = 0;

	if (m_iTabsNum == 0)
	{
		return;
	}

	//-------------------------
	// Define tab's full width:
	//-------------------------
	CClientDC dc (this);

	CFont* pOldFont = dc.SelectObject (m_bFlat ? 
		&m_fntTabsBold : &globalData.fontRegular);
	ASSERT(pOldFont != NULL);

	CRect rectClient;
	GetClientRect (&rectClient);

	//----------------------------------------------
	// First, try set all tabs in its original size:
	//----------------------------------------------
	int x = m_rectTabsArea.left - m_nTabsHorzOffset;
	for (int i = 0; i < m_iTabsNum; i ++)
	{
		CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [i];
		ASSERT_VALID (pTab);

		pTab->m_nFullWidth = m_sizeImage.cx + IMAGE_MARGIN +
				dc.GetTextExtent (pTab->m_strText).cx + 2 * TEXT_MARGIN;

		pTab->m_rect = CRect (CPoint (x, m_rectTabsArea.top),
						CSize (pTab->m_nFullWidth, m_rectTabsArea.Height () - 2));

		if (!m_bFlat)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -