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);
}