加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

做一个简单的MIB浏览器(二)

(2007-06-11 23:13:12)
 

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

做一个简单的MIB浏览器(二)

图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所示:

做一个简单的MIB浏览器(二)

当然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)
                     m_tree.SetItemImage(HCurrent,6,6);
      }

        
从这个函数可以看出,为树状控件添加相应的项的操作与上一个函数没有本质的区别,只是使用的图标换了换,理解这个程序的重点仍然是FindNode函数,也就是要把对应的父节点的句柄找出来,将这些代码添加完毕,程序的运行界面如图11所示。

做一个简单的MIB浏览器(二)

图11

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有