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

📄 treeview.cpp

📁 visual c++ 实例编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
	JumpToIt - PC Magazine password utility

	Copyright (c) 1999 Ziff-Davis Publishing Company.  All rights reserved.
	First published in PC Magazine, US Edition.

	Written by Steven E. Sipe


	This file implements the group tree class.
*/

#include "stdafx.h"

#include "jumptoit.h"
#include "mainfrm.h"
#include "Doc.h"
#include "listview.h"
#include "treeview.h"
#include "grpprdlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CJTITreeView

IMPLEMENT_DYNCREATE(CJTITreeView, CTreeView)

BEGIN_MESSAGE_MAP(CJTITreeView, CTreeView)
	//{{AFX_MSG_MAP(CJTITreeView)
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)
	ON_WM_LBUTTONUP()
	ON_WM_TIMER()
	ON_WM_MOUSEMOVE()
	ON_WM_KEYDOWN()
	ON_COMMAND(ID_ADD_GROUP, OnAddItem)
	ON_COMMAND(ID_DELETE_GROUP, OnDeleteItem)
	ON_COMMAND(ID_GROUP_PROPERTIES, OnItemProperties)
	ON_UPDATE_COMMAND_UI(ID_GROUP_PROPERTIES, OnUpdateItemProperties)
	ON_UPDATE_COMMAND_UI(ID_DELETE_GROUP, OnUpdateDeleteItem)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
	ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_COMMAND(ID_PASTE_DEFAULT, OnPasteDefault)
	ON_UPDATE_COMMAND_UI(ID_PASTE_DEFAULT, OnUpdatePasteDefault)
	ON_COMMAND(ID_MOVE_DOWN, OnMoveDown)
	ON_UPDATE_COMMAND_UI(ID_MOVE_DOWN, OnUpdateMoveDown)
	ON_COMMAND(ID_MOVE_UP, OnMoveUp)
	ON_UPDATE_COMMAND_UI(ID_MOVE_UP, OnUpdateMoveUp)
	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged)
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
	//}}AFX_MSG_MAP
	ON_COMMAND(ID_TOOL_ADD, OnAddItem)
	ON_COMMAND(ID_TOOL_DELETE, OnDeleteItem)
	ON_COMMAND(ID_TOOL_PROPERTIES, OnItemProperties)
	ON_UPDATE_COMMAND_UI(ID_TOOL_PROPERTIES, OnUpdateItemProperties)
	ON_UPDATE_COMMAND_UI(ID_TOOL_DELETE, OnUpdateDeleteItem)
END_MESSAGE_MAP()

// Constructor
CJTITreeView::CJTITreeView()
{
	CTreeCtrl& tree = GetTreeCtrl();
	m_pTree = &tree;

	m_bDragging = FALSE;
	m_nLevel = 0;
	m_pMap = NULL;
}

// Destructor
CJTITreeView::~CJTITreeView()
{
}

// Called when the tree is created
BOOL CJTITreeView::PreCreateWindow(CREATESTRUCT& cs)
{
	return CTreeView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CJTITreeView drawing

void CJTITreeView::OnDraw(CDC* pDC)
{
	CJTIDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
}

// Called when the view is initialized
void CJTITreeView::OnInitialUpdate()
{
	static BOOL bFirstTime = TRUE;

	if(bFirstTime)
	{
		// Set the tree style to have links and expand/contract buttons
		m_pTree->ModifyStyle(0,TVS_HASLINES|TVS_HASBUTTONS|TVS_SHOWSELALWAYS);
		m_ImageList.Create(IDB_GROUPS,16,1,RGB(255,0,255));

		// Setup the image list
		m_pTree->SetImageList(&m_ImageList, TVSIL_NORMAL);

		// Make sure the at least have the initial Groups item
		if(m_pTree->GetRootItem() == NULL)
		{
			m_pTree->InsertItem("Groups",0,0);

			GROUPS& arrGroups = GetDocument()->GetGroups();
			CGroup group;
			arrGroups.Add(group);
			m_nGroupCount = 1;
		}

		bFirstTime = FALSE;
	}

	CTreeView::OnInitialUpdate();
}

/////////////////////////////////////////////////////////////////////////////
// CJTITreeView diagnostics

#ifdef _DEBUG
void CJTITreeView::AssertValid() const
{
	CTreeView::AssertValid();
}

void CJTITreeView::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}

CJTIDoc* CJTITreeView::GetDocument()
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CJTIDoc)));
	return (CJTIDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CJTITreeView message handlers

// Called when the drag operation is beginning
void CJTITreeView::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	UINT nFlags;

	m_htreeItemDrag = m_pTree->HitTest(pNMTreeView->ptDrag,&nFlags);
	m_htreeItemDrop = NULL;

	// Can't drag the root item
	if(m_htreeItemDrag && (m_htreeItemDrag != m_pTree->GetRootItem()))
	{
		m_bDragging = TRUE;

		// Create drag image and begin dragging
		m_pImageList = m_pTree->CreateDragImage(m_htreeItemDrag); 
		m_pImageList->BeginDrag(0,CPoint(0,0));

		// Setup the image list for dragging and grab control of the mouse
		m_pImageList->DragEnter(GetDesktopWindow(),pNMTreeView->ptDrag);
		SetCapture();

		// Setup a scroll timer in case we need auto-scrolling
		SetTimer(1,75,NULL);

		// Save the location where the drag began
		CRect rect;
		GetClientRect(&rect);
		ClientToScreen(&rect);
		m_cyTop = rect.top;
		m_cyBottom = rect.bottom;
	}

	*pResult = 0;
}

// Handles dropping of dragged tree items
void CJTITreeView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// Transfer data if the need be and release capture.
	if(m_bDragging)
	{
		// End the drag operation for the image list
		m_pImageList->DragLeave(this);
		m_pImageList->EndDrag();

		// Make sure we can drop this item in the specified location
		if(m_htreeItemDrop && m_htreeItemDrag != m_htreeItemDrop &&
			!IsChild(m_htreeItemDrop,m_htreeItemDrag))
		{
			// Move the item and all of its children, the delete the original item
			MoveNode(m_htreeItemDrag,m_htreeItemDrop);
			m_pTree->DeleteItem(m_htreeItemDrag);

			GetDocument()->SetModifiedFlag(TRUE);
			GetDocument()->SaveModified();
		}
		else ::MessageBeep(0);

		// Let go of the mouse
		ReleaseCapture();

		// Kill the scroll timer
		KillTimer(1);
		
		// Reset the flags
		m_bDragging = FALSE;
		m_pTree->SelectDropTarget(NULL);

		AfxGetMainWnd()->Invalidate();
	}

	CTreeView::OnLButtonUp(nFlags, point);
}

// Handles auto-scrolling during drag operation
void CJTITreeView::OnTimer(UINT nIDEvent) 
{
	if(nIDEvent == 1)
	{
		// Get the current message
		const MSG* pMessage = GetCurrentMessage();

		// Move the drag image
		m_pImageList->DragMove(pMessage->pt);

		// Should we scroll the tree
		if(pMessage->pt.y < m_cyTop || pMessage->pt.y > m_cyBottom)
		{
			// Figure out how we should scroll the tree
			int nScrollType = GetScrollType(pMessage->pt);

			// Scroll the window
			SendMessage(WM_VSCROLL,nScrollType);

			// Select the drop target
			m_pImageList->DragLeave(this);
			HTREEITEM htreeItem = m_pTree->GetFirstVisibleItem();

			// Determine the type of scrolling we're doing
			switch(nScrollType)
			{
				case SB_LINEUP:
					if(htreeItem != m_pTree->GetRootItem())
					{
						m_pTree->EnsureVisible(htreeItem);
						m_htreeItemDrop = NULL;
					}
					break;

				case SB_LINEDOWN:
					int nCount = m_pTree->GetVisibleCount();

					for(int i = 0; i < nCount; i++)
						htreeItem = m_pTree->GetNextVisibleItem(htreeItem);

					m_pTree->EnsureVisible(htreeItem);
					m_htreeItemDrop = NULL;
					break;
			}

			m_pImageList->DragEnter(this,pMessage->pt);

			AfxGetMainWnd()->Invalidate();
		}
	}
	
	CTreeView::OnTimer(nIDEvent);
}

// Handles moving the mouse during a drag operation
void CJTITreeView::OnMouseMove(UINT nFlags, CPoint point) 
{
	if(m_bDragging)
	{
		CPoint ptScreen(point);
		ClientToScreen(&ptScreen);

		CRect rc;
		GetClientRect(&rc);

		// Is the mouse inside the tree control?
		if(rc.PtInRect(point))
		{
			UINT nFlags;

			// Yes, select the drop target and display the drop cursor
			::SetCursor(::LoadCursor(NULL,IDC_ARROW));
			m_pImageList->DragMove(ptScreen);
			m_pImageList->DragShowNolock(FALSE);
			m_htreeItemDrop = m_pTree->HitTest(point,&nFlags);
			m_pTree->SelectDropTarget(m_htreeItemDrop);
			m_pImageList->DragShowNolock(TRUE);
		}
		else
		{
			m_htreeItemDrop = NULL;  

			// No...select the no-drop cursor
			m_pTree->SelectDropTarget(NULL);
			::SetCursor(::LoadCursor(NULL,IDC_NO));
		}
	}
	
	CTreeView::OnMouseMove(nFlags, point);
}

// Determines if the specified item is a child of the specified parent item
BOOL CJTITreeView::IsChild(HTREEITEM htreeItemChild, HTREEITEM htreeItemParent)
{
	do
	{
		if(htreeItemChild == htreeItemParent)
			break;
	}
	while((htreeItemChild = m_pTree->GetParentItem(htreeItemChild)) != NULL);

	return(htreeItemChild != NULL);
}

// Recursively moves an item along with all of its child items
HTREEITEM CJTITreeView::MoveNode(HTREEITEM htreeItem, HTREEITEM htreeItemParent,
									HTREEITEM htreeItemSibling)
{
	TV_INSERTSTRUCT tvInsert;
	HTREEITEM htreeNewItem, htreeChild;

	// Get information about the dragged item
	tvInsert.item.hItem = htreeItem;
	tvInsert.item.cchTextMax = sizeof(m_szBuffer);
	tvInsert.item.pszText = m_szBuffer;
	tvInsert.item.mask = TVIF_HANDLE|TVIF_SELECTEDIMAGE|TVIF_IMAGE|TVIF_TEXT|TVIF_CHILDREN|TVIF_PARAM;
	m_pTree->GetItem(&tvInsert.item);  

	// Set the new parent and insert the item
	tvInsert.hParent = htreeItemParent;
	tvInsert.hInsertAfter = (htreeItemSibling?htreeItemSibling:TVI_FIRST);  
	tvInsert.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM;
	htreeNewItem = m_pTree->InsertItem(&tvInsert);

	// Recursively handle child items
	while((htreeChild = m_pTree->GetChildItem(htreeItem)) != NULL)
	{
		// Move each item's children
		MoveNode(htreeChild,htreeNewItem);  

		// Remove the original item
		m_pTree->DeleteItem(htreeChild);		
	}

	return(htreeNewItem);
}

// Determines whether scrolling up or down is required
int CJTITreeView::GetScrollType(CPoint pt)
{
	int nRet;

	if(pt.y > m_cyBottom)
		nRet = SB_LINEDOWN;
	else if(pt.y < m_cyTop)
		nRet = SB_LINEUP;

	return(nRet);
}

//// Storing and loading support

// Recursively saves the tree's items using the specified callback routine
BOOL CJTITreeView::RecurseItem(HTREEITEM hitem, BOOL (CJTITreeView::*lpfnCallback)(void))
{
	HTREEITEM hFirstChild;

	m_tvItem.hItem = hitem;
	m_tvItem.cchTextMax = sizeof(m_szBuffer);
	m_tvItem.pszText = m_szBuffer;
	m_tvItem.mask = TVIF_TEXT|TVIF_IMAGE;

	// Call the callback routine
	if(m_pTree->GetItem(&m_tvItem))
	{
		if((this->*lpfnCallback)())
			return(TRUE);
	}

	// Get the first child
	hFirstChild = m_pTree->GetNextItem(hitem,TVGN_CHILD);

	// Keep going until we have all of them
	while(hFirstChild)
	{
		// Save the current indention level
		m_nLevel++;

		// Recusively save all of the child items
		RecurseItem(hFirstChild,lpfnCallback);  
		hFirstChild = m_pTree->GetNextItem(hFirstChild,TVGN_NEXT);
	}

	// Finished with this node, so move back an indention level
	m_nLevel--;

	return TRUE;
}

// Writes the current item to an archive object (m_pArchive)
BOOL CJTITreeView::ArchiveItem()
{
	CString strData;
	BYTE byCount = strlen(m_tvItem.pszText);
	BYTE byImage = m_tvItem.iImage;
	int nType = 0;

	// Write the item's data
	m_pArchive->Write(&m_nLevel,sizeof(m_nLevel));
	m_pArchive->Write(&byImage,sizeof(byImage));
	m_pArchive->Write(&byCount,sizeof(byCount));
	m_pArchive->Write(m_tvItem.pszText,byCount);

	// Map the old group number to the new one.  This assures that the 
	// group's items get associated with the "new" group number when the 
	// items are saved.
	if(m_pMap)
	{
		int nGroup = m_tvItem.lParam;
		m_pMap[m_nIndex] = nGroup;
	}

	m_nIndex++;

	return(0);
}

⌨️ 快捷键说明

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