www.pudn.com > 20040716141459_combotree.rar > TreeDropList.cpp


/* Standard Disclaimer:  
Copyright (C) 2000  Dennis Howard 
This file is free software; you can redistribute it and/or 
modify it without any conditions. There is no warranty, 
implied or expressed, as to validity or fitness for a particular purpose. 
*/ 
 
// TreeDropList.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "TreeDropList.h" 
#include "TreeCombo.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CTreeDropList 
 
CTreeDropList::CTreeDropList()  : m_pCombo (NULL) 
{ 
	m_Delimiter = _T('/'); 
	m_CloseReason = e_KillFocus; 
	m_bDropped = FALSE; 
} 
 
CTreeDropList::~CTreeDropList() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CTreeDropList, CTreeCtrl) 
	//{{AFX_MSG_MAP(CTreeDropList) 
	ON_NOTIFY_REFLECT(NM_KILLFOCUS, OnKillfocus) 
	ON_WM_CHAR() 
	ON_WM_LBUTTONDBLCLK() 
	ON_NOTIFY_REFLECT(NM_SETFOCUS, OnSetfocus) 
	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CTreeDropList message handlers 
 
void CTreeDropList::OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	if (m_pCombo) 
	{ 
		//Focus will be on the drop down button focus lost because of 
		//mouse click to dialog client area. Check cursor position to 
		//find where mouse click was. 
		BOOL bClickedOnButton = m_pCombo->IsMouseOnButton (); 
		BOOL bClickedOnEdit =  m_pCombo->IsMouseOnEdit (); 
			 
		ShowWindow (SW_HIDE);	 
 
		//Treat click on dropdown box the same as a selection 
		if (bClickedOnButton) 
		{ 
			m_CloseReason = e_Select; 
			OnSelection (); 
			//Don't clear the DroppedState flag yet to prevent 
			//the mouse click on the button from popping up the tree again. 
		} 
		else if (bClickedOnEdit) 
		{ 
			m_CloseReason = e_Select; 
			OnSelection (); 
			m_pCombo->SetDroppedState (FALSE); 
		} 
		else 
		{ 
			m_pCombo->SetDroppedState (FALSE); 
		} 
 
		if (m_CloseReason == e_KillFocus) 
		{ 
			SelectString (m_pCombo->m_BeginPath); 
		} 
 
		m_pCombo->SendParentComboMessage (CBN_KILLFOCUS); 
 
	} 
	*pResult = 0; 
} 
 
 
void CTreeDropList::OnSetfocus(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	if (m_pCombo) 
	{ 
		m_pCombo->SendParentComboMessage (CBN_SETFOCUS); 
	} 
	*pResult = 0; 
} 
 
 
void CTreeDropList::OnSelection () 
{ 
	HTREEITEM hItem = GetSelectedItem (); 
	if (m_pCombo) 
	{ 
		CString Text; 
		Text = GetItemText (hItem); 
		m_pCombo->SetWindowText(Text); 
 
		m_pCombo->SendParentComboMessage (CBN_SELENDOK); 
		m_CloseReason = e_Select; 
	} 
	ShowWindow (SW_HIDE); 
} 
 
 
void CTreeDropList::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; 
 
	HTREEITEM hItem = GetSelectedItem (); 
	if (m_pCombo && hItem) 
	{ 
		m_pCombo->SendParentComboMessage (CBN_SELCHANGE); 
	} 
	*pResult = 0; 
} 
 
 
void CTreeDropList::OnCancel () 
{ 
	if (m_pCombo) 
	{ 
		m_pCombo->OnCancel (); 
		m_CloseReason = e_Cancel; 
	} 
	ShowWindow (SW_HIDE); 
} 
 
 
void CTreeDropList::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
	if (nChar == VK_RETURN) 
	{ 
	   OnSelection (); 
	   return; 
	} 
	else if (nChar == VK_ESCAPE) 
	{ 
		OnCancel (); 
		return; 
	} 
	else if (nChar == VK_TAB) 
	{ 
		if (m_pCombo) 
		{ 
			OnSelection (); 
 
			BOOL bShift = (GetKeyState(VK_SHIFT) < 0); 
 
			CWnd* pComboParent = m_pCombo->GetParent (); 
			if (pComboParent && pComboParent->GetSafeHwnd ()) 
			{ 
				CWnd* pNext = pComboParent->GetNextDlgTabItem (m_pCombo, bShift); 
				if (pNext && pNext->GetSafeHwnd ()) 
				{ 
					pNext->SetFocus (); 
				} 
			} 
			return; 
		} 
	} 
	CTreeCtrl::OnChar(nChar, nRepCnt, nFlags); 
} 
 
void CTreeDropList::OnLButtonDblClk(UINT nFlags, CPoint point)  
{ 
	CTreeCtrl::OnLButtonDblClk(nFlags, point); 
 
	if (m_pCombo) 
	{ 
		m_pCombo->SendParentComboMessage (CBN_DBLCLK); 
	} 
 
	OnSelection (); 
} 
 
HTREEITEM CTreeDropList::AddString ( LPCTSTR lpszString) 
{ 
	HTREEITEM hRoot = NULL; 
	if (!lpszString ||  (_tcsclen (lpszString) == 0) ) 
	{ 
		return NULL; 
	} 
 
	CString strTreeBranch = lpszString; 
	HTREEITEM hEndNode = DropListAddItem (hRoot, strTreeBranch); 
 
	return hEndNode; 
} 
 
 
void CTreeDropList::SplitPath (const CString& strTreeBranch, CString& strRoot, CString& strRemainder) 
{  
    int DelimiterPos = strTreeBranch.Find (m_Delimiter); 
	int LastDelimiterPos = 0; 
 
	strRoot      = _T(""); 
	strRemainder = _T(""); 
 
	if (DelimiterPos == -1) 
	{ 
		strRoot = strTreeBranch; 
		return; 
	} 
 
	//Separate root substring 
	if (DelimiterPos > 0) 
	{ 
		strRoot = strTreeBranch.Mid (0, DelimiterPos); 
	} 
 
	//Separate remainder substring 
	if (DelimiterPos < strTreeBranch.GetLength ()) 
	{ 
	   strRemainder = strTreeBranch.Mid (DelimiterPos + 1); 
	} 
 
} 
 
HTREEITEM CTreeDropList::MatchSibling (HTREEITEM hItem, CString& strMatch) 
{ 
	CString NodeText; 
	HTREEITEM hSibling = NULL; 
	if (hItem) 
	{ 
		hSibling = hItem; 
		while (hSibling) 
		{ 
			NodeText = GetItemText (hSibling); 
			if (NodeText == strMatch) 
			{ 
				break; 
			} 
			else 
			{ 
				hSibling = GetNextSiblingItem (hSibling); 
			} 
		} 
	} 
	return hSibling; 
} 
 
HTREEITEM CTreeDropList::SelectString( LPCTSTR lpszString, HTREEITEM hParent /*= NULL*/) 
{ 
	HTREEITEM hMatch = FindString (lpszString, hParent); 
	if (hMatch) 
	{ 
		SelectItem (hMatch); 
	} 
	return hMatch; 
} 
 
 
HTREEITEM CTreeDropList::FindString (CString strTreeBranch, HTREEITEM hParent /*=NULL*/ ) 
{ 
	HTREEITEM hPreviousMatch; 
	HTREEITEM hMatch; 
	CString strRoot; 
	CString strRemainder; 
 
	hMatch = FindString (hParent, strTreeBranch, hPreviousMatch, strRoot, strRemainder); 
 
	if (!strRemainder.IsEmpty ()) 
	{ 
		hMatch = NULL; 
	} 
 
	return hMatch; 
} 
 
HTREEITEM CTreeDropList::FindString (HTREEITEM hParent, CString strTreeBranch, 
								   HTREEITEM& hPreviousMatch, CString& strRoot, CString& strRemainder ) 
{ 
	HTREEITEM hItem = hParent; 
	HTREEITEM hMatch = NULL; 
 
	hPreviousMatch = hParent; 
 
 
	SplitPath (strTreeBranch, strRoot, strRemainder); 
	if (strRoot.IsEmpty ()) 
	{ 
		//Nothing to search for 
		return NULL; 
	} 
 
	 //special case when the tree is empty 
	 if (hParent == NULL) 
	 { 
		 hItem = GetChildItem (hParent); 
	 } 
 
	 //try to find a child item that matches the substring text 
	 //at the corresponding level 
 
	 //Match tree nodes until a node is encountered that doesn't match 
	 hMatch = MatchSibling (hItem, strRoot); 
	 while (hMatch && !strRemainder.IsEmpty()) 
	 { 
 		hPreviousMatch = hMatch; 
		strTreeBranch = strRemainder; 
		SplitPath (strTreeBranch, strRoot, strRemainder); 
		hItem = GetChildItem (hMatch); 
		hMatch = MatchSibling (hItem, strRoot); 
	 } 
 
    return hMatch; 
} 
 
 
 
HTREEITEM CTreeDropList::DropListAddItem (HTREEITEM hParent, CString strTreeBranch) 
{ 
 	HTREEITEM hAddedItem = NULL; 
	HTREEITEM hItem = hParent; 
	HTREEITEM hPreviousMatch = hParent; 
	HTREEITEM hMatch = NULL; 
 
	CString strRemainder; 
	CString strRoot; 
 
	hMatch = FindString (hParent, strTreeBranch, hPreviousMatch, strRoot, strRemainder); 
 
	//Add nodes until the remainder is gone 
	while (!strRemainder.IsEmpty()) 
	{ 
		hPreviousMatch = InsertItem (strRoot, hPreviousMatch); 
		strTreeBranch = strRemainder; 
		SplitPath (strTreeBranch, strRoot, strRemainder); 
	} 
	 
	//add only if the node doesn't match an existing node 
	if (!hMatch) 
	{ 
		hAddedItem = InsertItem (strRoot, hPreviousMatch); 
	} 
 
	return hAddedItem; 
} 
 
 
 
CString CTreeDropList::GetTreePath (HTREEITEM hItem) 
{ 
	CString ItemText; 
	CString PathText; 
	if (hItem) 
	{ 
		PathText = GetItemText (hItem); 
		HTREEITEM hParent = GetParentItem (hItem); 
		while (hParent) 
		{ 
			ItemText = GetItemText (hParent); 
			PathText = ItemText + m_Delimiter + PathText; 
			hParent = GetParentItem (hParent); 
		} 
	} 
	return PathText; 
} 
 
CString CTreeDropList::GetCurrentTreePath () 
{ 
	HTREEITEM hItem = GetSelectedItem (); 
	 
	return GetTreePath (hItem); 
}