您的位置:首页 > 其它

VC 动态生成菜单

2012-07-31 16:25 281 查看
动态生成菜单

这是一段根据字符串动态生成菜单的程序,字符串的格式是这样的:一个数字+一个字符串组成一个菜单项,一项一项的排开,用逗号,分隔,组成一个大字符串。数字表示菜单的层次,0是主菜单,1是1级子菜单...n+1是离它最近的左边的n级菜单的子菜单。最多可以表示9级子菜单,这已经足够了。字符串是菜单显示的内容。举个例子,比如0a,1b,1c,0d表示主菜单是a和d,a有2个子菜单b和c。

再比如 0a,1a1,2a11,2a12,1a2,2a21,3e,2a22,0b,0c,0d,1d1,2d11 表示出的菜单是这样的:



具体做起来很简单。

在头文件里:

由于要用到vector和map,所以先include他俩:

#include

定一个结构体,存储菜单项相关信息。

struct node_t

{

int level;//菜单项的层次

CString name;//菜单项显示的字符串

int nID;//该菜单项的id,用于处理选某个菜单项

};

typedef std::vector

别忘了还得有个成员变量:

CMenu* m_pMenu;

在cpp文件:

//这是个功能函数,把输入字符串解析成结构体数组,以便后面生成菜单用。

bool CQuickmenuDlg::ParseStringToVector( CString csparse, arNode& arlist )

{

arlist.clear();

node_t node;

for (;;){

int npos = csparse.Find( _T(','));

if ( -1 == npos ){

csparse.TrimLeft();

csparse.TrimRight();

if(csparse.IsEmpty()){

return false;

}

CString cst=csparse.Left(1);

LPCTSTR tmp=LPCTSTR(cst);

node.level = _ttoi(tmp);

node.name = csparse.Mid(1);

arlist.push_back( node );

break;

}

CString csadd = csparse.Left( npos );

csadd.TrimLeft();

csadd.TrimRight();

if(csadd.IsEmpty()){

return false;

}

CString cst=csadd.Left(1);

LPCTSTR tmp=LPCTSTR(cst);

node.level = _ttoi(tmp);

node.name = csadd.Mid(1);

arlist.push_back( node );

csparse = csparse.Mid( npos + 1 );

}

return true;

}

//在对话框初始化函数里,开始生成菜单了。

BOOL CQuickmenuDlg::OnInitDialog()

{

...

//前面的省略

// TODO: Add extra initialization here

//这是生成菜单所用的字符串。他的来源可以是消息,可以是文件,这只是个例子,写个固定值。

CString cs=_T("0a,1a1,2a11,2a12,1a2,2a21,2a22,0b,0c,0d,1d1");

//分解成结构体数组

arNode menulist;

if(!ParseStringToVector(cs,menulist)){

return TRUE;

}

//创建菜单

m_pMenu=new CMenu;

if(!m_pMenu->CreatePopupMenu()){

return TRUE;

}

//这是核心代码了,根据结构体数组创建菜单项。

std::map<int,CMenu*> menumap;

std::map<int,int> levelcountmap;

levelcountmap[0]=0;

menumap[0]=m_pMenu;

int n=menulist.size();

for (int i=0;i<n-1;i++){

node_t node=menulist[i];

levelcountmap[node.level]++;

node_t nodenext=menulist[i+1];

if (nodenext.level>node.level){

HMENU hmenu=CreatePopupMenu();

menumap[node.level]->AppendMenu(MF_STRING|MF_POPUP,(long)hmenu,node.name);

menumap[nodenext.level]=menumap[node.level]->GetSubMenu(levelcountmap[node.level]-1);

}else{

if (nodenext.level<node.level){

for (int j=node.level;j>nodenext.level;j--){

levelcountmap[j]=0;

}

}

//这里的i是该菜单项的id,可以根据node.name设定,以便后面弹出菜单后选某一项时处理。

menumap[node.level]->AppendMenu(MF_STRING,i,node.name);

}

}

//最后一项,这个i也是它的id。

menumap[menulist[n-1].level]->AppendMenu(MF_STRING,i,menulist[n-1].name);

return TRUE; // return TRUE unless you set the focus to a control

}

//最后在右键响应函数里加上TrackPopupMenu弹出菜单。

void CQuickmenuDlg::OnRButtonUp(UINT nFlags, CPoint point)

{

ClientToScreen(&point);

int nID=m_pMenu->TrackPopupMenu(TPM_NONOTIFY | TPM_RETURNCMD | TPM_LEFTALIGN

| TPM_LEFTBUTTON | TPM_RIGHTBUTTON,point.x,point.y,this);

//process selection nID...

//这个nID就是创建时设的,用个switch case结构分别处理。

switch(nID)

{

case 1:

break;

//...

}

CDialog::OnRButtonUp(nFlags, point);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: