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

📄 xhtmltree.cpp

📁 读取XML信息
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// XHtmlTree.cpp  Version 1.6 - article available at www.codeproject.com
//
// Author:  Hans Dietrich
//          hdietrich@gmail.com
//
// History
//     Version 1.6 - 2007 December 19
//     - Bug fixes and enhancements;  see CodeProject article for details
//
//     Version 1.5 - 2007 November 7
//     - Bug fixes and enhancements;  see CodeProject article for details
//
//     Version 1.4 - 2007 November 4
//     - Bug fixes and enhancements;  see CodeProject article for details
//
//     Version 1.3 - 2007 October 16
//     - Bug fixes and enhancements;  see CodeProject article for details
//
//     Version 1.2 - 2007 October 7
//     - Bug fixes and enhancements;  see CodeProject article for details
//
//     Version 1.1 - 2007 October 6
//     - Bug fixes and enhancements;  see CodeProject article for details
//
//     Version 1.0 - 2007 August 9
//     - 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.
//
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#pragma warning(disable : 4786)
#include "XHtmlTree.h"
#include "XNamedColors.h"
#include "XHtmlDraw.h"
#include "CreateCheckboxImageList.h"

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

#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"
//=============================================================================


//=============================================================================
// REGISTERED XHTMLTREE MESSAGES
//=============================================================================
UINT WM_XHTMLTREE_CHECKBOX_CLICKED = ::RegisterWindowMessage(_T("WM_XHTMLTREE_CHECKBOX_CLICKED"));
UINT WM_XHTMLTREE_ITEM_EXPANDED    = ::RegisterWindowMessage(_T("WM_XHTMLTREE_ITEM_EXPANDED"));
UINT WM_XHTMLTREE_DISPLAY_TOOLTIP  = ::RegisterWindowMessage(_T("WM_XHTMLTREE_DISPLAY_TOOLTIP"));
UINT WM_XHTMLTREE_INIT_TOOLTIP     = ::RegisterWindowMessage(_T("WM_XHTMLTREE_INIT_TOOLTIP"));
#ifdef XHTMLDRAGDROP
UINT WM_XHTMLTREE_BEGIN_DRAG       = ::RegisterWindowMessage(_T("WM_XHTMLTREE_BEGIN_DRAG"));
UINT WM_XHTMLTREE_END_DRAG         = ::RegisterWindowMessage(_T("WM_XHTMLTREE_END_DRAG"));
UINT WM_XHTMLTREE_DROP_HOVER       = ::RegisterWindowMessage(_T("WM_XHTMLTREE_DROP_HOVER"));
#endif // XHTMLDRAGDROP
#ifdef XHTMLTREE_DEMO
UINT WM_XHTMLTREE_SCROLL_SPEED     = ::RegisterWindowMessage(_T("WM_XHTMLTREE_SCROLL_SPEED"));
#endif // XHTMLTREE_DEMO

#pragma warning(disable : 4996)	// disable bogus deprecation warning

const UINT HOT_TIMER			= 1;
const UINT LBUTTONDOWN_TIMER	= 2;
const UINT CTRL_UP_TIMER		= 3;
const UINT SHIFT_UP_TIMER		= 4;
const UINT SELECT_TIMER			= 5;
const UINT TOOLTIP_BASE_ID		= 10000;
const DWORD MIN_HOVER_TIME		= 1500;		// 1.5 seconds
const int SCROLL_ZONE			= 16;		// pixels for scrolling

int XHTMLTREEDATA::nCount		= 0;

//=============================================================================
BEGIN_MESSAGE_MAP(CXHtmlTree, CTreeCtrl)
//=============================================================================
	//{{AFX_MSG_MAP(CXHtmlTree)
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_SYSCOLORCHANGE()
	ON_WM_TIMER()
	ON_WM_LBUTTONDOWN()
	ON_WM_SIZE()
	ON_WM_RBUTTONDOWN()
	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
	ON_NOTIFY_REFLECT_EX(NM_CLICK, OnClick)
	ON_NOTIFY_REFLECT_EX(NM_DBLCLK, OnDblclk)
	ON_NOTIFY_REFLECT_EX(TVN_BEGINLABELEDIT, OnBeginlabeledit)
	ON_NOTIFY_REFLECT_EX(TVN_ENDLABELEDIT, OnEndlabeledit)
	//}}AFX_MSG_MAP

#ifdef XHTMLDRAGDROP
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)
#endif // XHTMLDRAGDROP

#ifdef XHTMLTOOLTIPS
	ON_NOTIFY(UDM_TOOLTIP_DISPLAY, NULL, OnDisplayTooltip)	
#else
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
#endif // XHTMLTOOLTIPS

	ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnSelchanged)
	ON_NOTIFY_REFLECT_EX(TVN_SELCHANGING, OnSelchanging)
END_MESSAGE_MAP()

//=============================================================================
CXHtmlTree::CXHtmlTree()
//=============================================================================
  :	m_bDestroyingTree(FALSE),
	m_bFirstTime(TRUE),
	m_bSmartCheck(FALSE),
	m_bCheckBoxes(FALSE),
	m_bSelectFollowsCheck(TRUE),
	m_bReadOnly(FALSE),
	m_bHtml(TRUE),
	m_bStripHtml(FALSE),
	m_bLogFont(FALSE),
	m_bToolTip(FALSE),
	m_bDragging(FALSE),
	m_bAutoScroll(TRUE),
	m_bImages(TRUE),
	m_pToolTip(0),
	m_hAnchorItem(0),
	m_hHotItem(0),
	m_hPreviousItem(0),
	m_hItemButtonDown(0),
	m_hPreviousDropItem(0),
	m_nPadding(0),
	m_nImageHeight(16),
	m_nToolCount(0),
	m_nDefaultTipWidth(0),
	m_nScrollTime(0),
	m_crCustomWindow(COLOR_NONE),
	m_crCustomWindowText(COLOR_NONE),
	m_nHorzPos(0),
	m_dwDropHoverTime(0),
	m_nNoDropCursor(0),
	m_nDropCopyCursor(0),
	m_nDropMoveCursor(0),
	m_hNoDropCursor(0),
	m_hDropCopyCursor(0),
	m_hDropMoveCursor(0),
	m_hPreviousCursor(0),
	m_hCurrentCursor(0),
	m_dwDragOps(XHTMLTREE_DO_DEFAULT)
{
	TRACE(_T("in CXHtmlTree::CXHtmlTree\n"));
	memset(&m_lf, 0, sizeof(m_lf));
	SetColors();

	m_hPreviousCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
}

//=============================================================================
CXHtmlTree::~CXHtmlTree()
//=============================================================================
{
	if (m_pToolTip)
		delete m_pToolTip;
	m_pToolTip = 0;

	if (m_StateImage.GetSafeHandle())
		m_StateImage.DeleteImageList();

	if (m_hNoDropCursor)
		DestroyCursor(m_hNoDropCursor);
	m_hNoDropCursor = NULL;

	if (m_hDropCopyCursor)
		DestroyCursor(m_hDropCopyCursor);
	m_hDropCopyCursor = NULL;

	if (m_hDropMoveCursor)
		DestroyCursor(m_hDropMoveCursor);
	m_hDropMoveCursor = NULL;

	TRACE(_T("XHTMLTREEDATA::nCount=%d\n"), XHTMLTREEDATA::nCount);
}

//=============================================================================
CXHtmlTree& CXHtmlTree::Initialize(BOOL bCheckBoxes /*= FALSE*/, 
								   BOOL bToolTip /*= FALSE*/)
//=============================================================================
{
	TRACE(_T("in CXHtmlTree::Initialize\n"));
	m_bDestroyingTree = TRUE;

	DeleteAllItems();

	if (m_pToolTip)
		delete m_pToolTip;
	m_pToolTip = 0;

	SetImageList(NULL, TVSIL_STATE);

	if (m_StateImage.GetSafeHandle())
		m_StateImage.DeleteImageList();

	m_bCheckBoxes         = bCheckBoxes;
	m_bToolTip            = bToolTip;
	m_bSmartCheck         = FALSE;
	m_bSelectFollowsCheck = TRUE;
	m_bHtml               = TRUE;
	m_bLogFont            = FALSE;
	m_nPadding            = 0;
	m_nImageHeight        = 16;
	m_bFirstTime          = TRUE;
	m_hAnchorItem         = 0;
	m_hHotItem            = 0;
	memset(&m_lf, 0, sizeof(m_lf));

	SetColors();

	if (m_bToolTip)
	{
		TRACE(_T("creating tooltip\n"));
#ifdef XHTMLTOOLTIPS
		m_pToolTip = new CPPToolTip;
#else
		m_pToolTip = new CToolTipCtrl;
#endif // XHTMLTOOLTIPS
		if (m_pToolTip)
		{
			m_pToolTip->Create(this);
		}
	}

	if (m_bCheckBoxes)
		CreateCheckboxImages();

	m_bDestroyingTree = FALSE;

	return *this;
}

//=============================================================================
// PreCreateWindow() is called when CXHtmlTree is used in a view.
//
BOOL CXHtmlTree::PreCreateWindow(CREATESTRUCT& cs) 
//=============================================================================
{
	TRACE(_T("in CXHtmlTree::PreCreateWindow\n"));

	// style must include "no tooltips"
	cs.style |= TVS_NOTOOLTIPS;

	return CTreeCtrl::PreCreateWindow(cs);
}

//=============================================================================
void CXHtmlTree::PreSubclassWindow()
//=============================================================================
{
	TRACE(_T("in CXHtmlTree::PreSubclassWindow\n"));
	DWORD dwStyle = GetStyle();

	if (dwStyle & TVS_CHECKBOXES)
		m_bCheckBoxes = TRUE;

	// these styles must not be set
	ModifyStyle(TVS_CHECKBOXES, TVS_NOTOOLTIPS);

#ifdef XHTMLDRAGDROP
	ModifyStyle(TVS_DISABLEDRAGDROP, 0);
#else
	ModifyStyle(0, TVS_DISABLEDRAGDROP);
#endif // XHTMLDRAGDROP

	if (m_bCheckBoxes)
		CreateCheckboxImages();

	CTreeCtrl::PreSubclassWindow();
}

//=============================================================================
BOOL CXHtmlTree::PreTranslateMessage(MSG* pMsg) 
//=============================================================================
{
	// allow edit control to receive messages, if 
	// label is being edited
	if (GetEditControl() && 
		((pMsg->message == WM_CHAR) ||
		 (pMsg->message == WM_KEYDOWN) ||
		 GetKeyState(VK_CONTROL)))
	{
		::TranslateMessage(pMsg);
		::DispatchMessage(pMsg);
		return TRUE;
	}

	if (m_pToolTip && IsWindow(m_pToolTip->m_hWnd))
	{
		m_pToolTip->RelayEvent(pMsg);
	}

	//=========================================================================
	// WM_CHAR
	//=========================================================================
	if (pMsg->message == WM_CHAR)
	{
		if ((pMsg->wParam == VK_SPACE) && m_bCheckBoxes && !m_bReadOnly)
		{
			HTREEITEM hItem = GetSelectedItem();
			
			XHTMLTREEDATA *pXTCD = GetItemDataStruct(hItem);
	
			if (pXTCD && !pXTCD->bSeparator)		//+++1.6
			{
				SetCheck(hItem, !pXTCD->bChecked);
			}

			return TRUE;
		}
	}

	//=========================================================================
	// WM_KEYDOWN
	//=========================================================================
	if (pMsg->message == WM_KEYDOWN)
	{
		TRACE(_T("WM_KEYDOWN: lParam=0x%X\n"), pMsg->lParam);

#ifdef XHTMLDRAGDROP
		//=====================================================================
		// VK_ESCAPE while dragging
		//=====================================================================
		if ((pMsg->wParam == VK_ESCAPE) && m_bDragging)
		{
			TRACE(_T("ESC seen during drag\n"));
			EndDragScroll();
			SendRegisteredMessage(WM_XHTMLTREE_END_DRAG, 0, 0);
			return TRUE;
		}

		//=====================================================================
		// VK_CONTROL while dragging
		//=====================================================================
		if ((pMsg->wParam == VK_CONTROL) && 
			(m_dwDragOps & XHTMLTREE_DO_CTRL_KEY))
		{
			// check if Ctrl key down for first time
			if ((pMsg->lParam & 0x40000000) == 0)
			{
				if (IsOverItem() && m_bDragging)
				{
					SetDragCursor();
				}

				SetTimer(CTRL_UP_TIMER, 100, NULL);
			}
		}

		//=====================================================================
		// VK_SHIFT while dragging
		//=====================================================================
		if ((pMsg->wParam == VK_SHIFT) && 
			(m_dwDragOps & XHTMLTREE_DO_SHIFT_KEY))
		{
			// check if Shift key down for first time
			if ((pMsg->lParam & 0x40000000) == 0)
			{
				HTREEITEM hItem = IsOverItem();
				if (hItem && m_bDragging)
				{
					if (IsSeparator(hItem))					//+++1.6
					{
						SelectDropTarget(NULL);
						SetInsertMark(0, 0);
						SetInsertMark(hItem, TRUE);
					}
					else
					{
						SetInsertMark(0, 0);
						SelectDropTarget(hItem);
					}
				}
				SetTimer(SHIFT_UP_TIMER, 100, NULL);
			}
		}
#endif // XHTMLDRAGDROP

		//=====================================================================
		// VK_RIGHT or VK_LEFT
		//=====================================================================
		if ((pMsg->wParam == VK_RIGHT) || (pMsg->wParam == VK_LEFT))
		{
			BOOL bRight = pMsg->wParam == VK_RIGHT;

			HTREEITEM hItem = GetSelectedItem();
			
			XHTMLTREEDATA *pXTCD = GetItemDataStruct(hItem);
		
			if (pXTCD && pXTCD->bEnabled && pXTCD->nChildren)
			{
				BOOL bExpanded = pXTCD->bExpanded;
				BOOL bOldExpanded = pXTCD->bExpanded;
				if (!bExpanded && bRight)
					bExpanded = TRUE;
				if (bExpanded && !bRight)
					bExpanded = FALSE;
				if (bOldExpanded != bExpanded)
				{
					Expand(hItem, bExpanded ? TVE_EXPAND : TVE_COLLAPSE);
					return TRUE;
				}
			}
		}

		//=====================================================================
		// VK_DOWN or VK_UP
		//=====================================================================
		if ((pMsg->wParam == VK_DOWN) || (pMsg->wParam == VK_UP))
		{
			BOOL bDown = pMsg->wParam == VK_DOWN;

			HTREEITEM hItem = GetSelectedItem();
			
			if (hItem)
			{
				HTREEITEM hItemNew = bDown ? GetNextVisibleItem(hItem) : 
											 GetPrevVisibleItem(hItem);

				XHTMLTREEDATA *pXTCD = NULL;

				while (hItemNew)
				{
					pXTCD = GetItemDataStruct(hItemNew);
			
					if (pXTCD && pXTCD->bEnabled)
						break;

					// next item is not enabled, just skip it
					hItemNew = bDown ? GetNextVisibleItem(hItemNew) : 
									   GetPrevVisibleItem(hItemNew);
				}

				if (hItemNew)
				{
					SelectItem(hItemNew);
					return TRUE;
				}
			}
		}

		//=====================================================================
		// VK_MULTIPLY
		//=====================================================================
		if (pMsg->wParam == VK_MULTIPLY)
		{
			HTREEITEM hItem = GetSelectedItem();
			
			if (hItem)
			{
				ExpandBranch(hItem);
				EnsureVisible(hItem);
				SendMessage(WM_HSCROLL, SB_LEFT);
				return TRUE;
			}
		}

		//=====================================================================
		// VK_SUBTRACT  VK_ADD
		//=====================================================================
		UINT nCode = 0;
		switch (pMsg->wParam)
		{
			default:			break;
			case VK_SUBTRACT:	nCode = TVE_COLLAPSE; break;
			case VK_ADD:		nCode = TVE_EXPAND; break;
		}
		if (nCode)
		{
			HTREEITEM hItem = GetSelectedItem();
			if (hItem)

⌨️ 快捷键说明

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