经过这几天的学习及编程实践,我把最后的结果做出来,界面如图9所示:

图9
但是我不打算象上一部分那样,从头到尾描述编程实现的过程,而是想用模块化的方式将这个问题讲明白。我觉得比较好理解的是实现system、interfaces、at、ip、icmp、tcp这一个层次。
bool CMibbrower0608View::LoadMib(CString &filename)
{
MibNode*
pNode;
if
(MibFile.Open((LPCTSTR)filename,CFile::modeRead)==false)
{
AfxMessageBox("打开MIB-II文件时失败");
return false;
}
IndexString=' ';
//逐行读入并处理;
while (MibFile.ReadString(Line))
{
//预处理读入的行;
//空行,直接读下一行;
if (Line.GetLength()==0)
continue;
//注释行,直接读下一行;
if (Line.Find("--")==0)
continue;
//行的后面包含注释部分,去掉注释部分;
if (Line.Find("--")>0)
Line=Line.Left(Line.Find("--"));
//除去行两端的空白字符;
Line.TrimLeft();
Line.TrimRight();
//MIB模块名定义行;
/* if (Line.Find("DEFINITIONS
::=")>0)
{
Line=Line.Left(Line.Find("DEFINITIONS ::="));
HSecond= m_tree.InsertItem(LPCTSTR(Line) ,1,2,HRoot);
continue;
};*/
//辅助节点定义行;
if (Line.Find("OBJECT
IDENTIFIER ::=")>2)
if
((Line.Find('{')>10)&&(Line.Find('}')>10))
{
CString
ParentName,NodeName,Pos;
NodeName=Line.Left(Line.Find("OBJECT
IDENTIFIER ::="));
int
n1=Line.Find('{');
int
n2=Line.Find('}')-n1-1;
Line=Line.Mid(n1+1,n2);
Line.TrimLeft();
Line.TrimRight();
ParentName=Line.Left(Line.Find('
'));
Pos=Line.Mid(Line.Find('
')+1);
AddPlaceHolder(HRoot,ParentName,NodeName,Pos);
continue;
}
这一部分调用了一个函数AddPlaceHolder,里面调用了HRoot,ParentName,NodeName,Pos四个,其中HRoot的定义为
HRoot= m_tree.InsertItem("MIB",0,0,NULL);
//插入根节点,根节点为MIB
这是在程序初始化部分就定义的,没有什么问题,取ParentName,NodeName,Pos这三个参数我们以前利用一个小程序也解决了这个问题,因此这四个参数没有问题,难就难在AddPlaceHolder这个函数的实现上。
我们首先需要在头文件中声明这个函数
void AddPlaceHolder(HTREEITEM ht,CString &Parent_name,
CString
&Child_name,CString &num);
这也没什么问题,这个函数在cpp文件中是这样写的
void CMibbrower0608View::AddPlaceHolder(HTREEITEM ht,CString
&Parent_name,
CString &Child_name,CString &num)
{
CString OidStr;
Parent_name.TrimLeft();
Parent_name.TrimRight();
//对父节点进行了一次清空两边空白字符的操作
Child_name.TrimLeft();
Child_name.TrimRight();
//对子节点进行了一次清空两边空白字符的操作
//查找父节点;
HTREEITEM hParent=FindNode(ht,Parent_name);
//这里又调用了一个FindNode的函数
if (hParent==NULL)
{
//父节点不存在;
AfxMessageBox("请确认是否注册了顶端节点!");
return;
}
else
{
//父节点存在,只增加子节点;
HCurrent=m_tree.InsertItem(LPCTSTR(Child_name),1,1,hParent);
//HCurrent已经在头文件中定义了,是一个句柄
MibNode*
P_node=(MibNode*)m_tree.GetItemData(hParent);
OidStr=P_node->POid;
OidStr=OidStr+'.'+num;
P_node=new MibNode;
InitNodeData(P_node);
P_node->POid=OidStr;
m_tree.SetItemData(HCurrent,(DWORD)P_node);
}
}
对于出现的FindNode函数实现如下所示:这个函数主要是为了返回父节点的句柄,这个函数不长,但是理解起来挺难的,难就难在里面使用了三个跟树状控件有关的项:GetItemText、.GetChildItem、GetNextSiblingItem。掌握了三项,这个函数实现的功能也就掌握了,我会在下一篇文章中介绍这三个选项的用法,现在先理解这个函数的作用是查找父节点的句柄,也就是说子节点不能放错位置,需要正确的放到相应的父结点的下面。
HTREEITEM CMibbrower0608View::FindNode(HTREEITEM hSubRoot,const
CString &text)
{
if
(hSubRoot==NULL)
return NULL;
//判断是否符合条件,如是,返回该节点的举柄;
if
(m_tree.GetItemText(hSubRoot)==text)
/*
CTreeCtrl::GetItemText
CString GetItemText( HTREEITEM hItem )
const;
Return Value
A CString object containing the item's
text.
Parameters
hItem
Handle of the item whose text is to be
retrieved.
Remarks
Returns the text of the item specified by
hItem.
Example
See the example for CTreeCtrl::GetNextItem.
*/
return hSubRoot;
hSubRoot=m_tree.GetChildItem(hSubRoot);
/*
CTreeCtrl::GetChildItem
HTREEITEM GetChildItem( HTREEITEM hItem );
Return Value
The handle of the child item if successful; otherwise NULL.
Parameters
hItem
Handle of a tree item.
Remarks
Call this function to retrieve the tree view item that is the child
of the item specified by hItem.
Example
// The pointer to my tree control.
extern CTreeCtrl* pmyTreeCtrl;
// The item whose children will be deleted.
extern HTREEITEM hmyItem;
// Delete all of the children of hmyItem.
if (pmyTreeCtrl->ItemHasChildren(hmyItem))
{
HTREEITEM hNextItem;
HTREEITEM hChildItem =
pmyTreeCtrl->GetChildItem(hmyItem);
while (hChildItem !=
NULL)
{
hNextItem = pmyTreeCtrl->GetNextItem(hChildItem,
TVGN_NEXT);
pmyTreeCtrl->DeleteItem(hChildItem);
hChildItem = hNextItem;
}
}
CTreeCtrl Overview | Class Members
| Hierarchy Chart
See Also CTreeCtrl::GetItem,
CTreeCtrl::GetParentItem, CTreeCtrl::SortChildren
*/
do
{
HTREEITEM ht;
//递归调用FindNode;
if
((ht=FindNode(hSubRoot,text)) !=NULL)
return ht;
} while
((hSubRoot=m_tree.GetNextSiblingItem(hSubRoot)) !=NULL);
return
NULL;
}
这一步做完,界面就会如图10所示:

当然system前面是没有那个加号的。下面就是要实现system等之类的下面的项。下面的项有一个关键值“OBJECT-TYPE”,具体编码代码实现如下:
if
((Line.Find("OBJECT-TYPE")>2)&&(Line.Find(',')==-1))
{
CString
ParentName,NodeName,Pos;
NodeName=Line.Left(Line.Find("OBJECT-TYPE"));
NodeName.TrimLeft();
NodeName.TrimRight();
pNode=new
MibNode;
//
pNode->PInteger=new CStringList();
//
if (pNode->PInteger==NULL) AfxMessageBox(" 1
Bad pointer!!");
InitNodeData(pNode);
while
(MibFile.ReadString(Line))
{
if
(Line.GetLength()==0) continue;
if
(Line.Find("--")==0) continue;
if
(Line.Find("--")>0)
Line=Line.Left(Line.Find("--"));
Line.TrimLeft();
Line.TrimRight();
if
((Line.Find("::=")==0)&&(Line.Find('}')>3)&&(Line.Find('{')>1))
{
int
n1=Line.Find('{');
int
n2=Line.Find('}')-n1-1;
Line=Line.Mid(n1+1,n2);
Line.TrimLeft();
Line.TrimRight();
ParentName=Line.Left(Line.Find('
'));
Pos=Line.Mid(Line.Find('
')+1);
AddObject(HRoot,ParentName,NodeName,Pos,pNode);
break;
}
}// while
(MibFile.ReadString(Line))
continue;
}
}//while (MibFile.ReadString(Line))
MibFile.Close();
return true;
先说一下,代码的最后一行return
true;如果没有这一行,程序也是可以运行,只是会出一个错误提示,“打开文件失败”,然后再看代码,它同样的是通过调用一个函数AddObject(HRoot,ParentName,NodeName,Pos,pNode);来实现的树状控件新节点的插入。这个函数需要传递五个参数HRoot,ParentName,NodeName,Pos,pNode,前四个都没有问题,那么第五个参数呢,是在初始化函数中定义的
MibNode* pNode;
是一个结构体,那么我们重点看这个AddObject函数,在头文件中肯定要定义:
void AddObject(HTREEITEM ht,CString &Parent_name,
CString &Child_name,CString &num,MibNode* p);
在cpp文件中是这样实现的:
void CMibbrower0608View::AddObject(HTREEITEM ht,CString
&Parent_name,
CString &Child_name,CString &num,MibNode *p)
{
CString OidStr;
Parent_name.TrimLeft();
Parent_name.TrimRight();
Child_name.TrimLeft();
Child_name.TrimRight();
// AfxMessageBox("addobject起作用了!");
//查找父节点位置;
HTREEITEM hParent=FindNode(ht,Parent_name);
if (hParent!=NULL)
{
//增加新节点;
HCurrent=m_tree.InsertItem(LPCTSTR(Child_name),3,3,hParent);
//获取父节点OID;
MibNode* P_node=(MibNode*)m_tree.GetItemData(hParent);
OidStr=P_node->POid;
//生成子节点OID;
OidStr=OidStr+'.'+num;
p->POid=OidStr;
//设置子节点data属性;
m_tree.SetItemData(HCurrent,(DWORD)p);
//根据不同节点设置不同发图标;
if (IndexString.Find((LPCTSTR)Child_name)>0)
m_tree.SetItemImage(HCurrent,4,4);
if (Child_name.Find("Entry")>1)
m_tree.SetItemImage(HCurrent,5,5);
if (Child_name.Find("Table")>1)