📄 treepainter.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 + -