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

📄 xbreadcrumbbar.cpp

📁 读取XML信息
💻 CPP
字号:
// XBreadCrumbBar.cpp  Version 1.0 - article available at www.codeproject.com
//
// Author:  Hans Dietrich
//          hdietrich@gmail.com
//
// History
//     Version 1.0 - 2007 August 7
//     - Initial public release
//
// License:
//     This software is released into the public domain.  You are free to use
//     it in any way you like, except that you may not sell this source code.
//
//     This software is provided "as is" with no expressed or implied warranty.
//     I accept no liability for any damage or loss of business that this 
//     software may cause.
//
///////////////////////////////////////////////////////////////////////////////

// NOTE ABOUT PRECOMPILED HEADERS:
// This file does not need to be compiled with precompiled headers (.pch).
// To disable this, go to Project | Settings | C/C++ | Precompiled Headers
// and select "Not using precompiled headers".  Be sure to do this for all
// build configurations.
//#include "stdafx.h"

#include <windows.h>
#include <tchar.h>
#include <crtdbg.h>
#include "XString.h"
#include "XBreadCrumbBar.h"

#ifndef __noop
#if _MSC_VER < 1300
#define __noop ((void)0)
#endif
#endif

#undef TRACE
#define TRACE __noop

// if you want to see the TRACE output, 
// uncomment this line:
//#include "XTrace.h"

#if 0  // -----------------------------------------------------------
#ifdef _DEBUG
void* operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#define DEBUG_NEW new(THIS_FILE, __LINE__)
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif // -----------------------------------------------------------

#pragma warning(disable : 4127)	// for _ASSERTE: conditional expression is constant
#pragma warning(disable : 4291)	// no matching operator delete found
#pragma warning(disable : 4996)	// disable bogus deprecation warning

//=============================================================================
CXBreadCrumbBar::CXBreadCrumbBar() : CXHtmlDraw()
//=============================================================================
{
	m_pszSeparator = new TCHAR [16];
	_tcscpy(m_pszSeparator, _T(" >> "));
	m_pDS = 0;
	m_crumbs = 0;
	m_bBoldSeparator = TRUE;
}

//=============================================================================
CXBreadCrumbBar::~CXBreadCrumbBar()
//=============================================================================
{
	CleanUp();
	if (m_pszSeparator)
		delete [] m_pszSeparator;
	m_pszSeparator = 0;
}

//=============================================================================
void CXBreadCrumbBar::CleanUp()
//=============================================================================
{
	if (m_crumbs)
	{
		for (int i = 0; i < m_nCount; i++)
		{
			TCHAR *p = m_crumbs[i];
			if (p)
				delete [] p;
			m_crumbs[i] = 0;
		}
		delete [] m_crumbs;
	}
	m_nCount = 0;

	if (m_pDS)
		delete [] m_pDS;
	m_pDS = 0;
}

//=============================================================================
CXBreadCrumbBar& CXBreadCrumbBar::InitDrawStruct(XHTMLDRAWSTRUCT * pXHDS,
												 BOOL bBoldSeparator /*= TRUE*/)
//=============================================================================
{
	if (m_pDS)
	{
		for (int i = 0; i < m_nCount; i++)
		{
			m_pDS[i] = *pXHDS;
		}

		m_rect = pXHDS->rect;

		m_bBoldSeparator = bBoldSeparator;
	}

	return *this;
}

//=============================================================================
int CXBreadCrumbBar::Draw(HWND hWnd, BOOL bUnderlineUrl, int index /*= -1*/)
//=============================================================================
{
	int rc = 0;

	HDC hDC = GetDC(hWnd);
	if (hDC)
	{
		rc = Draw(hDC, bUnderlineUrl, index);
		ReleaseDC(hWnd, hDC);
	}

	return rc;
}

//=============================================================================
int CXBreadCrumbBar::Draw(HDC hdc, BOOL bUnderlineUrl, int index /*= -1*/)
//=============================================================================
{
	int rc = 0;

	if (!m_pDS)
		return 0;

	XHTMLDRAWSTRUCT ds;

	TCHAR * crumb = 0;

	if (index == -1)
	{
		// draw all
		for (int i = 0; i < m_nCount; i++)
		{
			if (i > 0)
			{
				// draw separator
				ds = m_pDS[i-1];
				ds.rect.left = m_pDS[i-1].nRightX + 1;
				ds.rect.right = m_rect.right;
				if (!m_bBoldSeparator)
					ds.bBold = FALSE;
				CXHtmlDraw::Draw(hdc, m_pszSeparator, &ds, FALSE);
				if ((ds.nRightX + 1) < m_rect.right)
					m_pDS[i].rect.left = ds.nRightX + 1;
			}

			// draw crumb
			crumb = m_crumbs[i];
			if (crumb)
				rc = CXHtmlDraw::Draw(hdc, crumb, &m_pDS[i], bUnderlineUrl);
			if ((m_pDS[i].nRightX + 1) < m_rect.right)
				m_pDS[i].rect.right = m_pDS[i].nRightX + 1;
		}
	}
	else
	{
		// only draw one crumb
		crumb = m_crumbs[index];
		if (crumb)
			rc = CXHtmlDraw::Draw(hdc, crumb, &m_pDS[index], bUnderlineUrl);
	}

	return rc;
}

//=============================================================================
CXBreadCrumbBar& CXBreadCrumbBar::SetSeparator(LPCTSTR lpszSep)
//=============================================================================
{
	_ASSERTE(lpszSep);

	if (lpszSep)
	{
		if (m_pszSeparator)
			delete [] m_pszSeparator;
		m_pszSeparator = _tcszdup(lpszSep);
	}

	return *this;
}

//=============================================================================
int CXBreadCrumbBar::GetCrumbs(TCHAR *** crumbs)
//=============================================================================
{
	int rc = 0;

	_ASSERTE(crumbs);

	if (crumbs)
	{
		*crumbs = m_crumbs;
		rc = m_nCount;
	}

	return rc;
}

//=============================================================================
CXBreadCrumbBar& CXBreadCrumbBar::SetCrumbs(const TCHAR * crumbs[], int count)
//=============================================================================
{
	_ASSERTE(crumbs);

	// delete everything
	CleanUp();

	if (crumbs && (count > 0))
	{
		// allocate memory for array of pointers
		m_crumbs = new TCHAR * [count];

		for (int i = 0; i < count; i++)
		{
			// allocate memory and copy crumb
			m_crumbs[i] = _tcszdup(crumbs[i]);
			TRACE(_T("m_crumbs[%d]=<%s>\n"), i, m_crumbs[i]);
		}

		m_nCount = count;

		m_pDS = new XHTMLDRAWSTRUCT [count];
	}

	return *this;
}

//=============================================================================
CXBreadCrumbBar& CXBreadCrumbBar::SetCrumbs(LPCTSTR crumbs, TCHAR sepchar)
//=============================================================================
{
	_ASSERTE(crumbs);

	TRACE("SetCrumbs: %s\n", crumbs);

	// delete everything
	CleanUp();

	if (crumbs)
	{
		int count = _tcsccnt(crumbs, sepchar) + 1;

		// allocate memory for array of pointers
		m_crumbs = new TCHAR * [count];

		const TCHAR *cp = crumbs;

		int i = 0;
		for (i = 0; i < count; i++)
		{
			if (*cp == _T('\0'))
				break;

			const TCHAR *next = _tcschr(cp, sepchar);

			if (!next)
				break;

			size_t len = next - cp;

			// allocate memory and copy crumb
			m_crumbs[i] = _tcsnzdup(cp, len);

			cp = next + 1;
		}

		// if anything left save it
		if (*cp && (i < count))
			m_crumbs[i] = _tcszdup(cp);

		m_nCount = count;

		m_pDS = new XHTMLDRAWSTRUCT [count];
	}

	return *this;
}

//=============================================================================
CXHtmlDraw::XHTMLDRAWSTRUCT * CXBreadCrumbBar::GetDrawStruct(int index)
//=============================================================================
{
	if (!m_pDS || (index < 0) || (index >= m_nCount))
		return 0;

	return &m_pDS[index];
}

//=============================================================================
size_t CXBreadCrumbBar::GetCrumb(int index, 
								 BOOL bStripHtml,
								 LPTSTR pszCrumb,
								 size_t size)		// in TCHARs
//=============================================================================
{
	size_t len = 0;

	if ((index >= 0) && (index < m_nCount))
	{
		TCHAR *cp = m_crumbs[index];
		len = _tcslen(cp);

		// if pszCrumb is NULL, just return length of crumb
		if (pszCrumb && (size != 0))
		{
			pszCrumb[0] = _T('\0');
			if (bStripHtml && (len > 3))		// minimum html string
			{
				TCHAR *s = new TCHAR [len + 16];
				CXHtmlDraw hd;
				hd.GetPlainText(cp, s, len+4);
				_tcsncpy(pszCrumb, s, size-1);
				delete [] s;
			}
			else
			{
				_tcsncpy(pszCrumb, cp, size-1);
			}
			pszCrumb[size-1] = _T('\0');
		}
	}

	return len;
}

//=============================================================================
int CXBreadCrumbBar::GetCrumb(LPCTSTR lpszCrumb, BOOL bStripHtml)
//=============================================================================
{
	_ASSERTE(lpszCrumb);

	int rc = -1;

	if (lpszCrumb)
	{
		CXHtmlDraw hd;

		for (int i = 0; i < m_nCount; i++)
		{
			TCHAR *crumb = m_crumbs[i];
			size_t len = _tcslen(crumb);
			TCHAR *s = _tcszdup(crumb);

			if (bStripHtml && (len > 3))		// minimum html string
				hd.GetPlainText(crumb, s, len+4);

			int ret = _tcsicmp(s, lpszCrumb);
			delete [] s;

			if (ret == 0)
			{
				rc = i;
				break;
			}
		}
	}

	return rc;
}

//=============================================================================
CXBreadCrumbBar& CXBreadCrumbBar::SetAppCommands(
							CXHtmlDraw::XHTMLDRAW_APP_COMMAND * paAppCommands, 
							int nAppCommands)
//=============================================================================
{
	m_Links.SetAppCommands(paAppCommands, nAppCommands);
	return *this;
}

//=============================================================================
int CXBreadCrumbBar::IsOverAnchor(HWND hWnd)
//=============================================================================
{
	int rc = -1;

	if (m_pDS)
	{
		for (int i = 0; i < m_nCount; i++)
		{
			if (CXHtmlDraw::IsOverAnchor(hWnd, &m_pDS[i]))
			{
				rc = i;
				break;
			}
		}
	}

	return rc;
}

//=============================================================================
int CXBreadCrumbBar::IsAnchorUnderlined()
//=============================================================================
{
	int rc = -1;

	if (m_pDS)
	{
		for (int i = 0; i < m_nCount; i++)
		{
			if (m_pDS[i].bAnchorIsUnderlined)
			{
				rc = i;
				break;
			}
		}
	}

	return rc;
}

//=============================================================================
BOOL CXBreadCrumbBar::RelayClick(HWND hWnd)
//=============================================================================
{
	BOOL rc = FALSE;

	if (m_pDS && hWnd && ::IsWindow(hWnd))
	{
		int index = IsOverAnchor(hWnd);

		if ((index >= 0) && (index < m_nCount))
		{
			XHTMLDRAWSTRUCT * pDS = &m_pDS[index];

			TRACE(_T("over crumb %d [%s]\n"), index, pDS->pszAnchor);

			if (pDS->pszAnchor)
			{
				HDC hDC = GetDC(hWnd);
				if (hDC)
				{
					Draw(hDC, FALSE, index);	// erase underline
					ReleaseDC(hWnd, hDC);
				}
				rc = m_Links.GotoURL(pDS->pszAnchor, SW_SHOW, pDS->nID);
			}
		}
	}

	return rc;
}

//=============================================================================
void CXBreadCrumbBar::RelayMouseMove(HWND hWnd)
//=============================================================================
{
	if (m_pDS && hWnd && ::IsWindow(hWnd))
	{
		int index_over = IsOverAnchor(hWnd);
		int index_underlined = IsAnchorUnderlined();

		if (index_over >= 0)
		{
			m_Links.SetLinkCursor();		// set cursor to hand

			// mouse is over a crumb
			if (index_underlined != index_over)
			{
				// mouse is over a different crumb
				if (index_underlined >= 0)
				{
					// remove any existing underlining
					Draw(hWnd, FALSE, index_underlined);
				}

				Draw(hWnd, TRUE, index_over);	// underline crumb
			}
		}
		else
		{
			// mouse is not over a crumb -- remove any existing underlining
			if (index_underlined >= 0)
				Draw(hWnd, FALSE, index_underlined);
		}
	}
}

⌨️ 快捷键说明

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