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

📄 ftab.cpp

📁 这是过于VC制作带有tab选现视图的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////
// 1999 Microsoft Systems Journal
// If this program works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//
//  05/09/02  Lynn McGuire  updated with new code from Paul for arrow controls
//                             http://msdn.microsoft.com/msdnmag/issues/02/10/CQA/
//  09/22/03  Lynn McGuire  converted the selected tab font to the same as the 
//                            tab list (made bold also)
//  09/25/03  Lynn McGuire  added user editing to the sheet name tabs
//  09/29/03  Lynn McGuire  added a right mouse click popup menu
//  09/30/03  Lynn McGuire  added first and last arrow controls


#include "stdafx.h"
#include "ftab.h"


// #include "resource.h"
#define ID_EDIT_SHEETS                  34069
#define ID_EDIT_ADDSHEET                34071
#define ID_EDIT_DELETESHEET             34072
#define ID_EDIT_RENAMESHEET             34073

#define  EditBoxId  5555


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

//////////////////
// Private class to represent one folder tab
//
class CFolderTab {
private:
	CString	m_sText; // tab text
	CRect		m_rect;			// bounding rect
	CRgn		m_rgn;			// polygon region to fill (trapezoid)

	int		ComputeRgn(CDC& dc, int x);
	int		Draw(CDC& dc, CFont& font, BOOL bSelected);
	BOOL		HitTest(CPoint pt)			{ return m_rgn.PtInRegion(pt); }
	CRect		GetRect() const				{ return m_rect; }
	void		GetTrapezoid(const CRect& rc, CPoint* pts) const;

	friend class CFolderTabCtrl;

public:
	CFolderTab(LPCTSTR lpszText) : m_sText(lpszText) { }
	LPCTSTR	GetText() const				{ return m_sText; }
	void  	SetText(LPCTSTR lpszText)	{ m_sText = lpszText; }
};


const CXOFFSET = 8;		// defined pitch of trapezoid slant
const CXMARGIN = 2;		// left/right text margin
const CYMARGIN = 1;		// top/bottom text margin
const CYBORDER = 1;		// top border thickness
const CXBUTTON = GetSystemMetrics(SM_CXVSCROLL);


//////////////////
// Compute the the points, rect and region for a tab.
// Input x is starting x pos.
//
int CFolderTab::ComputeRgn(CDC& dc, int x)
{
	m_rgn.DeleteObject();

	CRect& rc = m_rect;
	rc.SetRectEmpty();

	// calculate desired text rectangle
	dc.DrawText(m_sText, &rc, DT_CALCRECT);
	rc.right += 2 * CXOFFSET + 3 * CXMARGIN;	  // add margins
	rc.bottom = rc.top + GetSystemMetrics(SM_CYHSCROLL);	// ht = scrollbar height
	rc += CPoint(x,0);							// shift right

	// create trapezoid region
	CPoint pts[4];
	GetTrapezoid(rc, pts);
	m_rgn.CreatePolygonRgn(pts, 4, WINDING);

	return rc.Width();
}

//////////////////
// Given the boundint rect, compute trapezoid region.
// Note that the right and bottom edges not included in rect or
// trapezoid; these are normal rules of geometry. 
//
void CFolderTab::GetTrapezoid(const CRect& rc, CPoint* pts) const
{
	pts[0] = rc.TopLeft();
	pts[1] = CPoint(rc.left + CXOFFSET,   rc.bottom);
	pts[2] = CPoint(rc.right- CXOFFSET-1, rc.bottom);
	pts[3] = CPoint(rc.right-1, rc.top);
}


//////////////////
// Draw tab in normal or highlighted state
//
int CFolderTab::Draw(CDC& dc, CFont& font, BOOL bSelected)
{
	COLORREF bgColor = GetSysColor(bSelected ? COLOR_WINDOW     : COLOR_3DFACE);
	COLORREF fgColor = GetSysColor(bSelected ? COLOR_WINDOWTEXT : COLOR_BTNTEXT);

	CBrush brush(bgColor);					 // background brush
	dc.SetBkColor(bgColor);					 // text background
	dc.SetTextColor(fgColor);				 // text color = fg color

	CPen blackPen(PS_SOLID, 1, RGB(0,0,0));	// black
	CPen shadowPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));

	// Fill trapezoid
	CPoint pts[4];
	CRect rc = m_rect;
	GetTrapezoid(rc, pts);
	CPen* pOldPen = dc.SelectObject(&blackPen);
	dc.FillRgn(&m_rgn, &brush);

	// Draw edges. This is requires two corrections:
	// 1) Trapezoid dimensions don't include the right and bottom edges,
	// so must use one pixel less on bottom (cybottom)
	// 2) the endpoint of LineTo is not included when drawing the line, so
	// must add one pixel (cytop)
	//
	pts[1].y--;			// correction #1: true bottom edge y-coord
	pts[2].y--;			// ...ditto
	pts[3].y--;			// correction #2:	extend final LineTo
	dc.MoveTo(pts[0]);						// upper left
	dc.LineTo(pts[1]);						// bottom left
	dc.SelectObject(&shadowPen);			// bottom line is shadow color
	dc.MoveTo(pts[1]);						// line is inside trapezoid bottom
	dc.LineTo(pts[2]);						// ...
	dc.SelectObject(&blackPen);			// upstroke is black
	dc.LineTo(pts[3]);						// y-1 to include endpoint
	if (!bSelected) 
	{
		// if not highlighted, upstroke has a 3D shadow, one pixel inside
		pts[2].x--;		// offset left one pixel
		pts[3].x--;		// ...ditto
		dc.SelectObject(&shadowPen);
		dc.MoveTo(pts[2]);
		dc.LineTo(pts[3]);
	}
	dc.SelectObject(pOldPen);

	// draw text
	rc.DeflateRect(CXOFFSET + CXMARGIN, CYMARGIN);
	CFont* pOldFont = dc.SelectObject(&font);
	dc.DrawText(m_sText, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
	dc.SelectObject(pOldFont);

	return m_rect.right;
}


//////////////////////////////////////////////////////////////////
// CFolderTabCtrl

IMPLEMENT_DYNAMIC(CFolderTabCtrl, CWnd)
BEGIN_MESSAGE_MAP(CFolderTabCtrl, CWnd)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
	ON_BN_CLICKED(FTBFIRST,OnFirstTab)
	ON_BN_CLICKED(FTBPREV,OnPrevTab)
	ON_BN_CLICKED(FTBNEXT,OnNextTab)
	ON_BN_CLICKED(FTBLAST,OnLastTab)
	ON_EN_KILLFOCUS(EditBoxId,OnEditBoxKillFocus)
	ON_COMMAND(ID_EDIT_SHEETS,OnEditProperties)
	ON_COMMAND(ID_EDIT_ADDSHEET,OnEditAddSheet)
	ON_COMMAND(ID_EDIT_DELETESHEET,OnEditDeleteSheet)
	ON_COMMAND(ID_EDIT_RENAMESHEET,OnEditRenameSheet)
END_MESSAGE_MAP()


CFolderTabCtrl::CFolderTabCtrl()
{
	m_iCurItem =
	m_dwFtabStyle =
	m_cxDesired =
	m_cxButtons =
	m_iFirstTab = 0;
	m_editBox = NULL;
}


CFolderTabCtrl::~CFolderTabCtrl()
{
	while (!m_lsTabs.IsEmpty())
		delete (CFolderTab*)m_lsTabs.RemoveHead();

	if (m_editBox) 
		delete m_editBox;
}


//////////////////
// Create folder tab control from static control.
// Destroys the static control. This is convenient for dialogs
//
BOOL CFolderTabCtrl::CreateFromStatic(UINT nID, CWnd* pParent)
{
	CStatic wndStatic;
	if (!wndStatic.SubclassDlgItem(nID, pParent))
		return FALSE;
	CRect rc;
	wndStatic.GetWindowRect(&rc);
	pParent->ScreenToClient(&rc);
	wndStatic.DestroyWindow();
	rc.bottom = rc.top + GetDesiredHeight();
	return Create(WS_CHILD|WS_VISIBLE, rc, pParent, nID);
}


//////////////////
// Create folder tab control.
//
BOOL CFolderTabCtrl::Create(DWORD dwStyle, const RECT& rc,
	CWnd* pParent, UINT nID, DWORD dwFtabStyle)
{
	ASSERT(pParent);
	ASSERT(dwStyle & WS_CHILD);

	m_dwFtabStyle = dwFtabStyle;

	static LPCTSTR lpClassName = _T("PDFolderTab");
	static BOOL bRegistered = FALSE; // registered?
	if (!bRegistered) 
	{
		WNDCLASS wc;
		memset(&wc, 0, sizeof(wc));
		wc.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_DBLCLKS;
		wc.lpfnWndProc = (WNDPROC)::DefWindowProc; // will get hooked by MFC
		wc.hInstance = AfxGetInstanceHandle();
		wc.hCursor = LoadCursor(NULL, IDC_ARROW);
		wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
		wc.lpszMenuName = NULL;
		wc.lpszClassName = lpClassName;
		if (!AfxRegisterClass(&wc)) 
		{
			TRACE("*** CFolderTabCtrl::AfxRegisterClass failed!\n");
			return FALSE;
		}
		bRegistered = TRUE;
	}
	if (!CWnd::CreateEx(0, lpClassName, NULL, dwStyle, rc, pParent, nID))
		return FALSE;

	// initialize fonts
	LOGFONT lf;
	memset(&lf, 0, sizeof(lf));
	lf.lfHeight = GetSystemMetrics(SM_CYHSCROLL)-CYMARGIN;
	lf.lfWeight = FW_NORMAL;
	lf.lfCharSet = DEFAULT_CHARSET;
	_tcscpy(lf.lfFaceName, _T("Arial"));
	m_fontNormal.CreateFontIndirect(&lf);
	//      Lynn McGuire  9/19/03  dont make the selected font smaller
	//  lf.lfHeight -= 2;
	//      Lynn McGuire  9/19/03  make the selected font bold like Excel
	lf.lfWeight = FW_BOLD;
	m_fontSelected.CreateFontIndirect(&lf);

	return TRUE;
}


LPCTSTR CFolderTabCtrl::GetItemText(int iItem)
{
	CFolderTab* pft = GetTab(iItem);
	return pft ? pft->GetText() : NULL;
}


void CFolderTabCtrl::SetItemText(int iItem, LPCTSTR lpText)
{
	CFolderTab* pft = GetTab(iItem);
	if (pft) {
		pft->SetText(lpText);
	}
}


//////////////////
// copy a font
//
static void CopyFont(CFont& dst, CFont& src)
{
	dst.DeleteObject();
	LOGFONT lf;
	VERIFY(src.GetLogFont(&lf));
	dst.CreateFontIndirect(&lf);
}


//////////////////
// Set normal, selected fonts
//
void CFolderTabCtrl::SetFonts(CFont& fontNormal, CFont& fontSelected)
{
	CopyFont(m_fontNormal, fontNormal);
	CopyFont(m_fontSelected, fontSelected);
}


//////////////////
// Paint function
//
void CFolderTabCtrl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	CFolderTab* firstTab = GetTab(m_iFirstTab);
	int xOrigin = m_cxButtons;
	if (firstTab) 
		xOrigin -= firstTab->GetRect().left;
	dc.SetViewportOrg(xOrigin,0);

	CRect rc;
	GetClientRect(&rc);

	CFolderTab* pCurTab = NULL;

	// draw all the normal (non-selected) tabs
	int n = GetItemCount();
	for (int i=0; i<n; i++) 
	{
		CFolderTab* pTab = GetTab(i);
		ASSERT(pTab);
		if (i==m_iCurItem) {
			pCurTab = pTab;
		} else {
			pTab->Draw(dc, m_fontNormal, FALSE);
		}
	}
	// draw selected tab last so it will be "on top" of the others
	if (pCurTab)
		pCurTab->Draw(dc, m_fontSelected, TRUE);

	// draw border: line along the top edge, excluding selected tab
	CRect rcCurTab(0,0,0,0);
	if (pCurTab)
		rcCurTab = pCurTab->GetRect();

	rc.right -= xOrigin;
	CPen blackPen(PS_SOLID, 1, RGB(0,0,0));	// black
	CPen* pOldPen = dc.SelectObject(&blackPen);
	dc.MoveTo(rcCurTab.right, rcCurTab.top);
	dc.LineTo(rc.right, rc.top);
	if (m_dwFtabStyle & FTS_FULLBORDER) 
	{
		dc.MoveTo(rc.right-1, rc.top);
		dc.LineTo(rc.right-1, rc.bottom-1);
		dc.LineTo(rc.left,  rc.bottom-1);
		dc.LineTo(rc.left,  rc.top);
	} else {
		dc.MoveTo(rc.left, rc.top);
	}
	dc.LineTo(rcCurTab.TopLeft());
	dc.SelectObject(pOldPen);
}


//////////////////
// Handle mouse click: select new tab, if any. Notify parent, of course
//
void CFolderTabCtrl::OnLButtonDown(UINT nFlags, CPoint pt)
{
	int iTab = HitTest(pt);
	if (iTab>=0 && iTab!=m_iCurItem) 
	{
		SelectItem(iTab);
		NMFOLDERTAB nm;
		nm.hwndFrom = m_hWnd;
		nm.idFrom = GetDlgCtrlID();
		nm.code = FTN_TABCHANGED;
		nm.iItem = iTab;
		CWnd* pParent = GetParent();
		pParent->SendMessage(WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
	}
}


WNDPROC DefEditBoxProc = NULL; 

int UserPressedEnterOnTheEditBox = false;

HWND EditBoxHandle = 0;


LRESULT CALLBACK MyEditBoxProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{
    switch (message) 
	{
         case WM_CHAR:
              if ( VK_RETURN == wParam ) 
			  {
                  // User pressed ENTER -- do what you want here
				  UserPressedEnterOnTheEditBox = true;
				  // HWND editBoxHandle = GetDlgItem (hDlg, EditBoxId);
				  SendMessage (EditBoxHandle, WM_CLOSE, 0, 0);
                  return 0;
              }
              else if ( VK_ESCAPE == wParam ) 
			  {
                  // User pressed ESCAPE -- do what you want here
				  UserPressedEnterOnTheEditBox = false;
				  // HWND editBoxHandle = GetDlgItem (hDlg, EditBoxId);
				  SendMessage (EditBoxHandle, WM_CLOSE, 0, 0);
                  return 0;
              }
              else 
				  return (LRESULT) CallWindowProc 
							(DefEditBoxProc, hDlg, message, wParam, lParam);
         break;
         default:
              return (LRESULT) CallWindowProc 
						(DefEditBoxProc, hDlg, message, wParam, lParam);
         break;
    }
    return(0);
}


//////////////////
// Handle mouse click: select new tab, if any. Notify parent, of course
//
void CFolderTabCtrl::OnLButtonDblClk(UINT nFlags, CPoint pt)
{
	int iTab = HitTest(pt);
	if (iTab >= 0) 
	{
		SelectItem (iTab);
		OnEditRenameSheet ();
	}
}


void CFolderTabCtrl::OnEditBoxKillFocus()
{
	//MessageBox ("CFolderTabCtrl::OnEditBoxKillFocus - got here !");
	if (m_editBox)
	{
		if (UserPressedEnterOnTheEditBox)
		{
			char buffer [4096];
			m_editBox -> GetWindowText (buffer, sizeof (buffer) - 1);
			CFolderTab * pTab = GetTab (m_iCurItem);
			pTab -> SetText (buffer);
			Invalidate ();
			RecomputeLayout ();
			NMFOLDERTAB nm;
			nm.hwndFrom = m_hWnd;
			nm.idFrom = GetDlgCtrlID ();
			nm.code = FTN_TABNAMECHANGED;
			nm.iItem = m_iCurItem;
			nm.lpText = buffer;
			CWnd* pParent = GetParent ();
			pParent -> Invalidate ();

⌨️ 快捷键说明

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