treectrlhelper.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 739 行 · 第 1/2 页

CPP
739
字号
	m_tree.SetItemState(hti, nCheckState, TVIS_STATEIMAGEMASK);
}

void CTreeCtrlHelper::SetItemChecked(HTREEITEM hti, BOOL bChecked)
{
	SetItemChecked(hti, bChecked ? TCHC_CHECKED : TCHC_UNCHECKED);
}

TCH_CHECK CTreeCtrlHelper::GetItemCheckState(HTREEITEM hti)
{
	int nCheckState = m_tree.GetItemState(hti, TVIS_STATEIMAGEMASK);
	return (TCH_CHECK)((nCheckState  >> 12) - 1);
}

CString CTreeCtrlHelper::GetItemPath(HTREEITEM hti, int nMaxElementLen) const
{ 
	CString sPath;
	
	HTREEITEM htiParent = m_tree.GetParentItem(hti);
	
	while (htiParent)
	{
		CString sParent = m_tree.GetItemText(htiParent);
		
		if (nMaxElementLen != -1 && sParent.GetLength() > nMaxElementLen)
			sParent = sParent.Left(nMaxElementLen) + "...";
		
		sParent.TrimLeft();
		sParent.TrimRight();
		
		sPath = sParent + " / "+ sPath;
		htiParent = m_tree.GetParentItem(htiParent);
	}
	
	return sPath;
}

HTREEITEM CTreeCtrlHelper::GetTopLevelParentItem(HTREEITEM hti) const
{
	if (!hti)
		return NULL;
	
	HTREEITEM htiParent = m_tree.GetParentItem(hti);
	
	while (htiParent)
	{
		hti = htiParent; // cache this because the next parent might be the root
		htiParent = m_tree.GetParentItem(hti);
	}
	
	return hti; // return the one before the root
}

HTREEITEM CTreeCtrlHelper::GetNextTopLevelItem(HTREEITEM hti, BOOL bNext) const
{
	HTREEITEM htiParent = GetTopLevelParentItem(hti);
	HTREEITEM htiGoto = NULL;
	
	if (htiParent)
	{
		if (bNext)
			htiGoto = m_tree.GetNextItem(htiParent, TVGN_NEXT);
		else
		{
			// if the item is not htiParent then jump to it first
			if (hti != htiParent)
				htiGoto = htiParent;
			else
				htiGoto = m_tree.GetNextItem(htiParent, TVGN_PREVIOUS);

			if (htiGoto == hti)
				htiGoto = NULL; // nowhere to go
		}
	}
		
	return htiGoto;
}

int CTreeCtrlHelper::GetDistanceToEdge(HTREEITEM htiFrom, TCH_EDGE nToEdge)
{
	CRect rClient, rItem;

	if (m_tree.GetItemRect(htiFrom, rItem, FALSE))
	{
		m_tree.GetClientRect(rClient);
		int nItemHeight = m_tree.GetItemHeight();

		switch (nToEdge)
		{
		case TCHE_TOP:
			return (rItem.top - rClient.top) / nItemHeight;

		case TCHE_BOTTOM:
			return (rClient.bottom - rItem.bottom) / nItemHeight;
		}
	}

	return 0;
}

void CTreeCtrlHelper::SetMinDistanceToEdge(HTREEITEM htiFrom, TCH_EDGE nToEdge, int nItems)
{
	switch (nToEdge)
	{
	case TCHE_BOTTOM:
		{
			int nBorder = GetDistanceToEdge(htiFrom, TCHE_BOTTOM);

			while (nBorder < nItems)
			{
				m_tree.SendMessage(WM_VSCROLL, SB_LINEDOWN);
				nBorder++;
			}
		}
		break;

	case TCHE_TOP:
		{
			int nBorder = GetDistanceToEdge(htiFrom, TCHE_TOP);

			while (nBorder < nItems)
			{
				m_tree.SendMessage(WM_VSCROLL, SB_LINEUP);
				nBorder++;
			}
		}
		break;
	}
}

HTREEITEM CTreeCtrlHelper::GetNextPageVisibleItem(HTREEITEM hti) const
{
	// if we're the last visible item then its just the page count
	// figure out how many items to step
	HTREEITEM htiNext = m_tree.GetNextVisibleItem(hti);

	if (!htiNext || !IsFullyVisible(htiNext))
	{
		int nCount = m_tree.GetVisibleCount();

		// keep going until we get NULL and then return
		// the previous item
		while (hti && nCount--)
		{
			hti = GetNextVisibleItem(hti);

			if (hti)
				htiNext = hti;
		}
	}
	else // we keep going until we're the last visible item
	{
		// keep going until we get NULL and then return
		// the previous item
		while (hti)
		{
			hti = m_tree.GetNextVisibleItem(hti);
			
			if (hti && IsFullyVisible(hti))
				htiNext = hti;
			else
				hti = NULL;
		}
	}

	return htiNext;
}

HTREEITEM CTreeCtrlHelper::GetPrevPageVisibleItem(HTREEITEM hti) const
{
	// if we're the first visible item then its just the page count
	// figure out how many items to step
	HTREEITEM htiPrev = m_tree.GetPrevVisibleItem(hti);

	if (!htiPrev || !IsFullyVisible(htiPrev))
	{
		int nCount = m_tree.GetVisibleCount();

		// keep going until we get NULL and then return
		// the previous item
		while (hti && nCount--)
		{
			hti = GetPrevVisibleItem(hti);

			if (hti)
				htiPrev = hti;
		}
	}
	else // we keep going until we're the first visible item
	{
		// keep going until we get NULL and then return
		// the previous item
		while (hti)
		{
			hti = m_tree.GetPrevVisibleItem(hti);
			
			if (hti && IsFullyVisible(hti))
				htiPrev = hti;
			else
				hti = NULL;
		}
	}

	return htiPrev;
}

HTREEITEM CTreeCtrlHelper::GetNextVisibleItem(HTREEITEM hti, BOOL bAllowChildren) const
{
	HTREEITEM htiNext = NULL;
	
	// try our first child if we're expanded
	if (bAllowChildren && m_tree.ItemHasChildren(hti) && IsItemExpanded(hti))
		htiNext = m_tree.GetChildItem(hti);
	else
	{
		// try next sibling
		htiNext = m_tree.GetNextItem(hti, TVGN_NEXT);
		
		// finally look up the parent chain as far as we can
		if (!htiNext)
		{
			HTREEITEM htiParent = hti;

			while (htiParent && !htiNext)
			{
				htiParent = m_tree.GetParentItem(htiParent);

				if (htiParent)
					htiNext = m_tree.GetNextItem(htiParent, TVGN_NEXT);
			}
		}
	}

	return htiNext == TVI_ROOT ? NULL : htiNext;
}

HTREEITEM CTreeCtrlHelper::GetPrevVisibleItem(HTREEITEM hti, BOOL bAllowChildren) const
{
	// try our prior sibling
	HTREEITEM htiPrev = m_tree.GetNextItem(hti, TVGN_PREVIOUS);
	
	// if we have one then first try its last child
	if (htiPrev)
	{
		if (bAllowChildren && m_tree.ItemHasChildren(htiPrev) && IsItemExpanded(htiPrev))
		{
			HTREEITEM htiChild = m_tree.GetChildItem(htiPrev);
			
			while (htiChild)
			{
				htiPrev = htiChild;
				htiChild = m_tree.GetNextItem(htiChild, TVGN_NEXT);
			}
		}
		// else we settle for htiPrev as-is
	}
	else // get parent
		htiPrev = m_tree.GetParentItem(hti);

	return htiPrev == TVI_ROOT ? NULL : htiPrev;
}

BOOL CTreeCtrlHelper::IsFullyVisible(HTREEITEM hti) const
{
	CRect rClient, rItem, rIntersect;

	m_tree.GetClientRect(rClient);
	m_tree.GetItemRect(hti, rItem, FALSE);

	return (rIntersect.IntersectRect(rItem, rClient) && rIntersect == rItem);
}

int CTreeCtrlHelper::FindItem(HTREEITEM htiFind, HTREEITEM htiStart)
{
	// try same first
	if (htiFind == htiStart)
		return 0;

	// then try up
	HTREEITEM htiPrev = GetPrevVisibleItem(htiStart);

	while (htiPrev)
	{
		if (htiPrev == htiFind)
			return -1;

		htiPrev = GetPrevVisibleItem(htiPrev);
	}

	// else try down
	HTREEITEM htiNext = GetNextVisibleItem(htiStart);

	while (htiNext)
	{
		if (htiNext == htiFind)
			return 1;

		htiNext = GetNextVisibleItem(htiNext);
	}

	// else
	return 0;
}

BOOL CTreeCtrlHelper::IsItemBold(HTREEITEM hti)
{
	return (m_tree.GetItemState(hti, TVIS_BOLD) & TVIS_BOLD);
}

void CTreeCtrlHelper::SetItemBold(HTREEITEM hti, BOOL bBold)
{
	m_tree.SetItemState(hti, bBold ? TVIS_BOLD : 0, TVIS_BOLD);
}

void CTreeCtrlHelper::SetItemStateEx(HTREEITEM hti, UINT nState, UINT nMask, BOOL bChildren)
{
	if (hti)
		m_tree.SetItemState(hti, nState, nMask);

	if (bChildren)
	{
		HTREEITEM htiChild = m_tree.GetChildItem(hti);
		
		while (htiChild)
		{
			SetItemStateEx(htiChild, nState, nMask, TRUE);
			htiChild = m_tree.GetNextItem(htiChild, TVGN_NEXT);
		}
	}
}

void CTreeCtrlHelper::SetTopLevelItemsBold(BOOL bBold)
{
	// clear all bold states
	SetItemStateEx(NULL, 0, TVIS_BOLD, TRUE);

	// set top items bold
	if (bBold)
	{
		HTREEITEM hti = m_tree.GetChildItem(NULL);
		
		while (hti)
		{
			SetItemBold(hti, TRUE);
			hti = m_tree.GetNextItem(hti, TVGN_NEXT);
		}
	}
}

HTREEITEM CTreeCtrlHelper::FindItem(DWORD dwID, HTREEITEM htiStart) const
{
	// try htiStart first
	if (htiStart && m_tree.GetItemData(htiStart) == dwID)
		return htiStart;
	
	// else try htiStart's children
	HTREEITEM htiFound = NULL;
	HTREEITEM htiChild = m_tree.GetChildItem(htiStart);
	
	while (htiChild && !htiFound)
	{
		htiFound = FindItem(dwID, htiChild);
		htiChild = m_tree.GetNextItem(htiChild, TVGN_NEXT);
	}
	
	return htiFound;
}

⌨️ 快捷键说明

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