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

📄 treecombobox.cpp

📁 hao code hao code hao code hao code hao code
💻 CPP
字号:
/****************************************************************/
/*																*/
/*  TreeComboBox.cpp											*/
/*																*/
/*  Implementation of the CTreeComboBox class					*/
/*																*/
/*  Author: John Melas											*/
/*	http://www.cc.ece.ntua.gr/~jmelas							*/
/*	jmelas@cc.ece.ntua.gr										*/
/*																*/
/*  Last updated: August 5, 2004								*/
/*																*/
/****************************************************************/


#include "stdafx.h"
#include "TreeComboBox.h"

#define BUTTON_SIZE 16
#define ICON_SIZE 16


WNDPROC CTreeComboBox::m_parentWndProc = NULL;
CTreeComboBox* CTreeComboBox::m_pActiveCombo = NULL;


IMPLEMENT_DYNAMIC(CTreeComboBox, CButton)


int compare( const void *arg1, const void *arg2 )
{
	return _stricmp( * ( char** ) arg1, * ( char** ) arg2 );
}

void Sort(CString &str)
{
	char seps[] = "\r\n";
	CString items[256];
	char *token;
	int i;
	for (i=0, token = strtok(str.GetBuffer(256), seps);	i<256 && token!=NULL; i++, token = strtok(NULL, seps))
		items[i] = token;
	int max = i;
	
	qsort( (void *)items, (size_t)max, sizeof( char * ), compare );
	
	str = "";
	for (i=0; i<max; i++)
		str += items[i] + "\r\n";
	str.TrimRight("\r\n");
}




void CTreeComboBox::PreSubclassWindow() 
{
	CButton::PreSubclassWindow();

	//create m_edit
	CRect rect;
	GetClientRect(&rect);
	m_multiline = (rect.Height()>(BUTTON_SIZE*2));
	if (m_multiline)
		rect.DeflateRect(2,2,BUTTON_SIZE+2,2);
	else
		rect.DeflateRect(ICON_SIZE+6,4,BUTTON_SIZE+2,4);
	DWORD plus = 0;
	if (m_multiline)
		plus = WS_VSCROLL|ES_MULTILINE|ES_WANTRETURN;
	m_edit.Create(WS_CHILD|WS_VISIBLE
		|ES_AUTOHSCROLL|ES_AUTOVSCROLL|plus,
		rect,this,IDC_TEXTCOMBO); //0x401
	m_font.CreatePointFont(8,"MS Sans Serif");
	m_edit.SetFont(&m_font);
	m_edit.SetCombo((CComboBox*)this);
	m_edit.SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
	m_edit.ModifyStyle(0,WS_TABSTOP);

	CString text;
	GetWindowText(text);
	text.Replace(", ","\r\n");
	m_edit.SetWindowText(text);
	m_edit.UpdateTooltip();
	
	
	//create m_tree
	
	//m_tree.Create(
	m_tree.Create(WS_BORDER|
	TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_DISABLEDRAGDROP, 
	CRect(0,0,0,0),
	GetParent(),
	0);
	DWORD dwStyle = GetWindowLong(m_tree.m_hWnd, GWL_STYLE);
	SetWindowLong(m_tree.m_hWnd, GWL_STYLE, (dwStyle | WS_POPUP));
	m_tree.SetParent(NULL);

	m_tree.SetCombo((CComboBox*)this);
	//m_tree.ModifyStyleEx(0,WS_EX_TOOLWINDOW);
	if (m_multiline)
		m_tree.AllowFolders(FALSE);

	InterceptParentWndProc();
}

void CTreeComboBox::InterceptParentWndProc()
{
	// ASSERT
	CWnd *pwndParent = GetParent();
	if (!pwndParent) return;
	if (!pwndParent->GetSafeHwnd()) return;

	// GET Parent WinProc & SET our function
	if (m_parentWndProc)
		return;
	m_parentWndProc = (WNDPROC)::SetWindowLong(
		pwndParent->GetSafeHwnd(), 
		GWL_WNDPROC, 
		(long)(WNDPROC)ParentWindowProc);
}

void CTreeComboBox::UnInterceptParentWndProc()
{
	// ASSERT
	CWnd *pwndParent = GetParent();
	if (!pwndParent) return;
	if (!pwndParent->GetSafeHwnd()) return;

	// SET Parent WinProc = UNINTERCEPT
	(WNDPROC)::SetWindowLong(
		pwndParent->GetSafeHwnd(), 
		GWL_WNDPROC, 
		(long)(WNDPROC)m_parentWndProc);
}


void CTreeComboBox::OnDestroy() 
{
	// CALL Parent
	CButton::OnDestroy();
	
	// UNINTERCEPT
	UnInterceptParentWndProc();
}

BEGIN_MESSAGE_MAP(CTreeComboBox, CButton)
	//{{AFX_MSG_MAP(CTreeComboBox)
	ON_WM_DESTROY()
	ON_WM_LBUTTONDOWN()
	ON_WM_KILLFOCUS()
	ON_WM_SETFOCUS()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


void CTreeComboBox::OnLButtonDown(UINT nFlags, CPoint point)
{
	// CALL Parent
	CButton::OnLButtonDown(nFlags, point);

	m_pressed = TRUE;

	// SHOW Tree
	ShowDropDown();
}


LRESULT CTreeComboBox::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
	
	// CATCH DropDown Keys
	switch (message){
		case WM_KEYDOWN:
		case WM_SYSKEYDOWN:
			switch ((int) wParam){
				case VK_DOWN:
				case VK_UP:
					ShowDropDown();
					return NULL;	// INTERCEPT
				case VK_SPACE:
					return NULL;	// INTERCEPT
			}
	}		


	// CALL Parent
	return CButton::WindowProc(message, wParam, lParam);
}
HTREEITEM CTreeComboBox::GetNextTreeItem(HTREEITEM hItem)
{
	// we return the next HTEEITEM for a tree such as:
	// Root (1)
	//		Child1 (2)
	//			xxxx (3)
	//			yyyy (4)
	//		Chiled2 (5)
	// Item (6)
	
	// has this item got any children
	if (m_tree.ItemHasChildren(hItem))
	{
		return m_tree.GetNextItem(hItem, TVGN_CHILD);
	}
	else if (m_tree.GetNextItem(hItem, TVGN_NEXT) != NULL)
	{
		// the next item at this level
		return m_tree.GetNextItem(hItem, TVGN_NEXT);
	}
	else
	{
		// return the next item after our parent
		hItem = m_tree.GetParentItem(hItem);
		if (hItem == NULL)
		{
			// no parent
			return NULL;
		}
		while (m_tree.GetNextItem(hItem, TVGN_NEXT) == NULL)
		{
			if (!hItem)
				return NULL;
			else
				hItem = m_tree.GetParentItem(hItem);
		}
		// next item that follows our parent
		return m_tree.GetNextItem(hItem, TVGN_NEXT);
	}
}
BOOL CTreeComboBox::FindItemByText(CString strfind)
{
	HTREEITEM hItem = m_tree.GetRootItem();
	while (hItem != NULL)
	{
		CString str = m_tree.GetItemText(hItem);
		if (str == strfind)
		{
			m_tree.SelectItem(hItem);
			//updateimage
			int pos = -1;
			int dummy;
			m_tree.GetItemImage(hItem,pos,dummy);
			if (m_tree.GetImageList(TVSIL_NORMAL)!=NULL)
				UpdateIcon(m_tree.GetImageList(TVSIL_NORMAL)->ExtractIcon(pos));
			return TRUE;
		}
		hItem = GetNextTreeItem(hItem);
	}
	/*CString str;
	m_edit.GetWindowTextA(str);
	if (str != "")*/
	
	return FALSE;
}

void CTreeComboBox::Accept()
{
	HTREEITEM item = m_tree.GetSelectedItem();
	if (item!=NULL)
	{
		CString str = m_tree.GetItemText(item);
		int strpos = -1;
		if (m_multiline)
		{
			CString cur;
			m_edit.GetWindowText(cur);
			strpos = cur.Find(str);
			if (strpos==-1)
			{
				cur.TrimRight("\r\n ");
				cur+="\r\n"+str;
				cur.TrimLeft("\r\n");
				if (m_sort)
					Sort(cur);
				strpos = cur.Find(str);
			}
			str = cur;
		}
		
		//update string
		SetText(str);
		
		//updateimage
		int pos = -1;
		int dummy;
		m_tree.GetItemImage(item,pos,dummy);
		if (m_tree.GetImageList(TVSIL_NORMAL)!=NULL)
			UpdateIcon(m_tree.GetImageList(TVSIL_NORMAL)->ExtractIcon(pos));
		HideDropDown();
		m_edit.SelectText(m_multiline,strpos);
		m_edit.SetFocus();
	}
}

void CTreeComboBox::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{

	//get dc and rect
	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
	

	CRect rc = lpDrawItemStruct->rcItem;

	//draw frame
	pDC->DrawEdge(rc, EDGE_SUNKEN, BF_RECT);

	//draw bg
	rc.DeflateRect(2, 2);
	//if (m_multiline)
	//{
	//	int scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
	//  rc.DeflateRect(scrollbar_width,0,0,0);
	//}
	if (!m_multiline)
		pDC->FillSolidRect(&rc, GetSysColor(COLOR_WINDOW));

	//calc button rect
	CRect rcButton = rc;
	rcButton.left = rcButton.right - BUTTON_SIZE;
	if (rcButton.left < rc.left) 
		rcButton.left = rc.left;

	//calc image rect
	CRect rcImage = rc;
	rcImage.right = rcButton.left - 1;
	if (rcImage.right < rcImage.left) 
		rcImage.right = rcImage.left;

	//draw image
	if (!m_multiline && m_icon!=NULL)
	{
		pDC->DrawState(CPoint(rcImage.left+1,rcImage.top),CSize(ICON_SIZE,ICON_SIZE),m_icon,DST_ICON,HBRUSH(0));
		rcImage.DeflateRect(ICON_SIZE+2,0,0,0);
	}


	//draw focus
	/*rcImage.DeflateRect(1,1,0,1);
	if (lpDrawItemStruct->itemState & ODS_FOCUS) 
	{
		COLORREF c=GetSysColor(COLOR_HIGHLIGHT);
		pDC->FillSolidRect(rcImage,RGB(255-GetRValue(c),255-GetGValue(c),255-GetBValue(c)));
		pDC->DrawFocusRect(rcImage);
	}
	rcImage.DeflateRect(1,1,1,1);

	// GET Caption
	CString strText;
	GetWindowText(strText);

	// DRAW Caption
	if (lpDrawItemStruct->itemState & ODS_FOCUS)
	{
		pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
		pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
		pDC->FillSolidRect(rcImage,GetSysColor(COLOR_HIGHLIGHT));
		rcImage.DeflateRect(1,0,0,0);
		pDC->DrawText(strText, &rcImage, DT_SINGLELINE | DT_VCENTER );
		
	}
	else
	{
		pDC->SetBkColor( GetSysColor(COLOR_WINDOW) );
		pDC->SetTextColor(RGB(0, 0, 0));
		rcImage.DeflateRect(1,0,0,0);
		pDC->DrawText(strText, &rcImage, DT_SINGLELINE | DT_VCENTER );
	}*/

	//draw button
	//pDC->FillSolidRect(rcButton,RGB(234,232,228));
	if (m_multiline)
	{
	//	rcButton.OffsetRect(0,rcButton.Height()-rcButton.Width());
	//	rcButton.bottom=rcButton.top+rcButton.Width();
	}
	CRect frect = rcButton;
	CBrush brBtnShadow(GetSysColor(COLOR_BTNSHADOW));
	CBrush brBtnFace(GetSysColor(COLOR_BTNFACE));
	//if (lpDrawItemStruct->itemState & ODS_SELECTED)
	if (m_pressed && m_pActiveCombo!=NULL)
	{
		pDC->FrameRect(frect, &brBtnShadow);
		frect.DeflateRect(1, 1);
		pDC->FillRect(&frect, &brBtnFace);
		frect.DeflateRect(1, 3, 0, 0);
	}
	else
	{
		pDC->FrameRect(frect, &brBtnFace);
		//frect.DeflateRect(1, 1, 0, 0);
		//DrawFrameControl(lpDrawItemStruct->hDC, &frect, DFC_BUTTON, uStyle);
		pDC->Draw3dRect(frect,GetSysColor(COLOR_BTNFACE),GetSysColor(COLOR_3DDKSHADOW));
		frect.DeflateRect(1, 1, 1, 1);
		pDC->Draw3dRect(frect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
		frect.DeflateRect(1, 1, 1, 1);
		pDC->FillRect(&frect, &brBtnFace);
	}

	//draw arrow
	//if (lpDrawItemStruct->itemState & ODS_SELECTED)
	if (m_pressed && m_pActiveCombo!=NULL)
		rcButton.DeflateRect(1,1,0,0);
	CPen penBlack(PS_SOLID, 1, RGB(0, 0, 0));
	CPen* ppenOld = pDC->SelectObject(&penBlack);
	for(long i=0; i<4; i++){
		pDC->MoveTo( rcButton.left + 4 + i, rcButton.top + rcButton.Height()/2 - 2 + i);
		pDC->LineTo( rcButton.left + 4 + 7 - i, rcButton.top + rcButton.Height()/2 - 2 + i);
	}
	pDC->SelectObject(ppenOld);

	m_edit.Invalidate();
}




void CTreeComboBox::ShowDropDown()
{

	if (m_pActiveCombo!=NULL)
	{
		HideDropDown();
		//m_edit.SelectText(m_multiline);
		m_edit.SetFocus();
		return;
	}

	

	CRect rc;
	GetWindowRect(&rc);
	m_tree.SetWindowPos(&wndTopMost,rc.left, rc.bottom, rc.Width(), 220,SWP_SHOWWINDOW);

	CWnd* pTopParent = GetParent()->GetParentOwner();
    if (pTopParent != NULL)
	{  
		pTopParent->SendMessage( WM_NCACTIVATE, TRUE );
		pTopParent->SetRedraw( TRUE );
	}

			
	m_pActiveCombo = this;
}

void CTreeComboBox::HideDropDown()
{
	if (m_pActiveCombo!=NULL) 
	{	
		m_pActiveCombo->GetTree()->ShowWindow( SW_HIDE );
		m_pActiveCombo = NULL;
	}
}

LRESULT CALLBACK CTreeComboBox::ParentWindowProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	// CHECK Message
	if (nMsg==WM_COMMAND || 
        nMsg==WM_SYSCOMMAND ||
		nMsg==WM_SYSKEYDOWN ||
		nMsg==WM_LBUTTONDOWN ||
		nMsg==WM_NCLBUTTONDOWN)
	{
		// FILTER Messages
		if (!IsMsgOK(hWnd, nMsg, lParam))
			m_pActiveCombo->HideDropDown();
	}
	
	// CALL Parent
	if (!m_parentWndProc) 
		return NULL;
	
	return CallWindowProc( m_parentWndProc, hWnd, nMsg, wParam, lParam );
}

BOOL CTreeComboBox::IsMsgOK(HWND hWnd, UINT nMsg, /*WPARAM wParam,*/ LPARAM lParam)
{
	// ASSERT
	if (!hWnd) 
		return FALSE;
	if (nMsg != WM_COMMAND) 
		return FALSE;
	if (!m_pActiveCombo) 
		return FALSE;
	if ((HWND)lParam != m_pActiveCombo->GetSafeHwnd()) 
		return FALSE;

	//check if mouse pos is in drop down rect
	CRect rc;
	m_pActiveCombo->GetWindowRect(rc);
	CPoint pt;
	GetCursorPos(&pt);
	if (!rc.PtInRect(pt))
		return FALSE;
	
	return TRUE;
}

void CTreeComboBox::OnKillFocus(CWnd* pNewWnd) 
{
	// CALL Parent
	CButton::OnKillFocus(pNewWnd);

	// HIDE Active DropDown
	if (pNewWnd != &m_edit)
		HideDropDown();
}



void CTreeComboBox::OnSetFocus(CWnd* pOldWnd) 
{
	CButton::OnSetFocus(pOldWnd);

	if (!m_pressed)
		m_edit.SetFocus();	
}

void CTreeComboBox::LoadXmlSubTree(CXmlElement *pElement, HTREEITEM hItem)
{
	CXmlElement *pChild = m_xmlDocument.GetFirstChild(pElement);
	while (pChild != NULL)
	{
		CString name = pChild->GetValue("name");
		if (name=="")
			name = pChild->m_strData;
		if (name=="")
			name = pChild->m_strName;
		
		int image = (pChild->m_ChildElements.GetCount()!=0)?0:2;

		HTREEITEM hChildItem = m_tree.InsertItem(name, image, image, hItem);

		// save data
		m_tree.SetItemData(hChildItem, (DWORD)pChild);

		LoadXmlSubTree(pChild, hChildItem);
		
		pChild = m_xmlDocument.GetNextSibling(pElement);
	}
}

void CTreeComboBox::LoadXml(CString filename, int bmp)
{
	//m_imagelist.Create(bmp,16,1,RGB(255,0,0));
	m_imagelist.Create(bmp,16,1,RGB(255,0,0));
	m_tree.SetImageList(&m_imagelist,TVSIL_NORMAL);

	m_xmlDocument.DeleteContents();
	if (m_xmlDocument.Load(filename))
	{
		m_tree.DeleteAllItems();
		LoadXmlSubTree(m_xmlDocument.GetRootElement(), TVI_ROOT);
	}
}
void CTreeComboBox::LoadString(CString info, int bmp)
{
	if (!m_imagelist)
	{
		m_imagelist.Create(bmp,16,1,RGB(255,255,255));
		m_tree.SetImageList(&m_imagelist,TVSIL_NORMAL);
	}
	
	m_xmlDocument.DeleteContents();
	if (m_xmlDocument.LoadString(info))
	{
		m_tree.DeleteAllItems();
		LoadXmlSubTree(m_xmlDocument.GetRootElement(), TVI_ROOT);
	}
}

void CTreeComboBox::OnLButtonUp(UINT nFlags, CPoint point) 
{
	m_pressed = FALSE;
	if (m_pActiveCombo)
		Invalidate();

	CButton::OnLButtonUp(nFlags, point);
}

void CTreeComboBox::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	OnLButtonDown(nFlags, point);
}

⌨️ 快捷键说明

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