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

📄 treepainter.cpp

📁 组播密钥的批次更新算法
💻 CPP
字号:
#include "Afxwin.h"
#include "BinaryTree.h"
#include "treepainter.h"
#include ".\treepainter.h"


CTreePainter::CTreePainter(int horizontalSpace,
						   int verticalSpace,
						   int nodeLength,
						   int nodeHeight)
:m_hSpace(horizontalSpace),m_vSpace(verticalSpace),m_nodeLength(nodeLength),m_nodeHeight(nodeHeight),
m_leafColor(CTreePainter::defaultLeafColor),m_commonColor(CTreePainter::defaultCommonColor)
{
	//该版本中每个节点内部绘制两个域
	m_rowAmount=2;

	//每个域的高度等于节点高度/域数量,域宽度就是节点宽度
	m_rowHeight=m_nodeHeight / m_rowAmount;

	//节点与堆栈之间的距离
	m_gapInNodeAndStack=10;

}

CTreePainter::~CTreePainter(void)
{
}

void CTreePainter::PaintTree(CBinaryTree& btree,CDC* dc)
{
	int initialChildDistance = (m_hSpace<<(btree.GetHeight()-2));
	PaintSubTree(dc,m_origin.x,m_origin.y,initialChildDistance,btree.m_root);
}

void CTreePainter::PaintSubTree(CDC* dc, int posx, int posy, int distance, CNode* subroot)
{
	if(subroot!=0)
	{
		//绘制左触角
		if(subroot->m_leftchild!=0)
		{
			dc->MoveTo(posx,posy);
			dc->LineTo(posx-(distance>>1),posy+m_vSpace);
		}

		//绘制右触角
		if(subroot->m_rightchild!=0)
		{
			dc->MoveTo(posx,posy);
			dc->LineTo(posx+(distance>>1),posy+m_vSpace);
		}

		//绘制结点
		PaintNode(dc,posx,posy,subroot);
		
		//绘制两个子树
		this->PaintSubTree(dc, posx-(distance>>1), posy+m_vSpace, distance>>1, subroot->m_leftchild);
		this->PaintSubTree(dc, posx+(distance>>1), posy+m_vSpace, distance>>1, subroot->m_rightchild);
	}
}

void CTreePainter::SetOriginPoint(const CPoint &point)
{
	this->m_origin=point;
}

CPoint CTreePainter::GetOriginPoint(void)
{
	return this->m_origin;
}

void CTreePainter::PaintNode(CDC* pdc, int centralX, int centralY, CNode* node)
{
	if(node!=0)
	{
		int halfTotalLength=m_nodeLength>>1;
		int halfTotalHeight=m_nodeHeight>>1;

		CString Label;
		CRect entireRect(centralX-halfTotalLength,centralY-halfTotalHeight,centralX+halfTotalLength,centralY+halfTotalHeight);

		////////////////////////////////////////////////////////////////////////////
		//根据传入节点的类型设置画刷颜色
		COLORREF newColor;
		if(node->m_leftchild==0 && node->m_rightchild==0)
			newColor=this->m_leafColor;
		else
			newColor=this->m_commonColor;

		CBrush *oldBrush;
        CBrush newBrush(newColor);
		
		oldBrush=pdc->SelectObject(&newBrush);
		////////////////////////////////////////////////////////////////////////////
		
		
		//绘制外围矩形
		pdc->Rectangle(&entireRect);						

		
		////////////////////////////////////////////////////////////////////////////
		pdc->SelectObject(oldBrush);
		////////////////////////////////////////////////////////////////////////////


		//绘制第一行内容
		Label.Format("编号:%4d",node->m_nodeID);
		this->PaintRow(pdc,entireRect,Label,0);

		//绘制第二行内容
		Label.Format("密钥:%4d",node->m_key);
		this->PaintRow(pdc,entireRect,Label,1);


		//如果是叶子节点再绘制它的堆栈内容
		if(node->m_leftchild==0 && node->m_rightchild==0)
		{
			this->PaintAppendants(pdc,entireRect.left,entireRect.bottom+m_gapInNodeAndStack,node);
		}
	}
}

CSize CTreePainter::GetNodeSize(void)
{
	return CSize(m_nodeLength,m_nodeHeight);
}

void CTreePainter::PaintAppendants(CDC* pdc, int topLeftX, int topLeftY, CNode* node)
{
	if (node!=0)
	{
		CString ancestorKey;
		CRect paintRect;
		
		CFont font,*oldfont;
		font.CreatePointFont(90,"宋体");
		oldfont=pdc->SelectObject(&font);

		CPen pen(PS_INSIDEFRAME,1,RGB(0,0,0)),*oldpen;
		oldpen=pdc->SelectObject(&pen);

		CMyStack<int>::iterator it(node->m_keyList);
		
		paintRect.left=topLeftX;
		paintRect.right=paintRect.left+m_nodeLength;

		for(int index=0;it.hasNext();it.next(),index++)
		{
			ancestorKey.Format("%d",it.GetCurrentItem());
			paintRect.top=topLeftY+index*m_rowHeight;
			paintRect.bottom=paintRect.top+m_rowHeight+1;
			pdc->Rectangle(&paintRect);
			pdc->DrawText(ancestorKey,paintRect,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
		}
		
		pdc->SelectObject(oldpen);
		pdc->SelectObject(oldfont);
	}
}

void CTreePainter::PaintRow(CDC* pdc, const CRect& rect, CString& label, int index)
{
	int offsetX=0;
	int offsetY=m_rowHeight*index;
	
	//构造绘制第index个row的区域
	CRect paintRect(rect.left+offsetX,rect.top+offsetY,rect.right,rect.top+offsetY+m_rowHeight);
	
	CFont font,*oldfont;
	font.CreatePointFont(90,"宋体");
	oldfont=pdc->SelectObject(&font);
	pdc->SetBkMode(TRANSPARENT);
	
	pdc->DrawText(label,&paintRect,DT_SINGLELINE|DT_VCENTER|DT_CENTER);

	pdc->SetBkMode(OPAQUE);
	pdc->SelectObject(oldfont);
}

CPoint CTreePainter::GetViewSize(CBinaryTree& btree,CSize &size)
{
	size.SetSize(0,0);

	int treeHeight=btree.GetHeight();
	int rightSpace=(m_hSpace<<(treeHeight-2));
	int leftSpace=(m_hSpace<<(treeHeight-2));
	
	int rightLength=0;
	int leftLength=0;
	//确定视图的横向长度

	CNode* root=btree.m_root;
	//取左端距离根节点的最大距离
	while(root!=0)
	{
		if(root->m_leftchild!=0)
		{
			leftSpace=(leftSpace>>1);
			leftLength+=leftSpace;
		}
		root=root->m_leftchild;
	}

	//取右端距离根节点的最大距离
	root=btree.m_root;
	while(root!=0)
	{
		if(root->m_rightchild!=0)
		{
			rightSpace=(rightSpace>>1);
			rightLength+=rightSpace;
		}
		root=root->m_rightchild;
	}
	
	
	//视图长度=左宽度+右宽度+节点长度
	size.cx+=(leftLength+rightLength+m_nodeLength);
	
	//确定视图纵向长度
	//纵向长度=节点纵向距离*(树高-1)+节点高度+叶子节点与堆栈之间的空隙+堆栈长度
	size.cy+=(m_vSpace*(treeHeight-1))+m_nodeHeight+m_gapInNodeAndStack+m_rowHeight*(treeHeight-1);
	
	size.cx=(size.cx > 0) ? size.cx : 0;
	size.cy=(size.cy > 0) ? size.cy : 0;

	return CPoint(leftLength+(m_nodeLength>>1),(m_nodeHeight>>1));
}

⌨️ 快捷键说明

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