hur.cn - 华软网

 热门搜索

关于动态生成菜单的问题,请各位大侠指点指点

  作者:未知    来源:网络    更新时间:2018/5/16
在本论谈中有许多关于动态生成菜单的贴子,但是都是在原来菜单中添加,我是想整个菜单均由程序自动生成,请各位高手指点,这个事我已经试了好长时间,请各位帮帮忙!!!!!!!!!!!!
------华软网友回答------
气球的

http://blog.csdn.net/balloonman2002/archive/2004/06/28/28708.aspx
------华软网友回复------
为什么要创建动态菜单?我其实更倾向于创建好菜单,然后根据需要隐藏掉一部分菜单项。也就是采用类似于权限控制的手段来显示需要的部分。
动态创建菜单不外乎采用另外一种数据格式来保存菜单数据,然后用自定义的算法构造出菜单而已,这些其实都可以由pb的menu paint完成的。
我觉得唯一适用动态创建的菜单是右键弹出式的菜单,不同对象,甚至是同一个对象有不同状态的时候,可能都需要不同的弹出菜单,很难创建适用于所有对象所有状态的弹出菜单,这时候,才可能需要动态创建菜单数据、再动态创建菜单的功能。
------华软网友回复------
整个动态添加,从文件中?正好我以前做过
以下是我以前写的动态从文件中添加菜单的VC DLL源码 ,完整
//---------------------------------------------------------------------------
//参数:dest为输出的被截后的字符串,source为源传入的字符串,nFlags为要截的目标
// 参数为1:截取菜单名,参数为2:截取菜单图标;参数为3:返回菜单的索引
//            4为1则取菜单名,为2则取菜单图象string
//返回:返回该字符串左侧空格的个数
//---------------------------------------------------------------------------
int StringTok(CString& dest,const CString &source,CString &sPosition,int nFlags=1)
{
int index = 0;
for(int i=0;i<source.GetLength();i++)
{
if(0x20 == source.GetAt(i)){index++;continue;} //如果字符串左侧为空格则继续循环直到字符串左侧非空格
if(0 == index && sPosition != "00000000") //如果该字符串的空格数为0:
{
int l = atoi(sPosition.Mid(0,1));
sPosition.Format("%d%s",++l,"0000000"); //sPosition的第一位+1: "11111111" = "20000000" ,右侧全部清空
break;
}
else if(4 == index)
{
int l = atoi(sPosition.Mid(1,1));
sPosition.Format("%s%d%s",sPosition.Left(1),++l,"000000"); //第二位+1:"22222222" = "23000000"
break;
}
else if(8 == index)
{
int l = atoi(sPosition.Mid(2,1));
sPosition.Format("%s%d%s",sPosition.Left(2),++l,"00000"); //第三位+1:"33333333" = "33400000"
break;
}
else if(12 == index)
{
int l = atoi(sPosition.Mid(3,1));
sPosition.Format("%s%d%s",sPosition.Left(3),++l,"0000"); //第四位+1:"44444444" = "44450000"
break;
}
else if(16 == index)
{
int l = atoi(sPosition.Mid(4,1));
sPosition.Format("%s%d%s",sPosition.Left(4),++l,"000"); //第五位+1:"55555555" = "55556000"
break;
}
else if(20 == index)
{
int l = atoi(sPosition.Mid(5,1));
sPosition.Format("%s%d%s",sPosition.Left(5),++l,"00"); //第六位+1:"66666666" = "66666700"
break;
}
else if(24 == index)
{
int l = atoi(sPosition.Mid(6,1));
sPosition.Format("%s%d%s",sPosition.Left(6),++l,"0"); //第七位+1:"77777777" = "77777780"
break;
}
else if(28 == index)
{
int l = atoi(sPosition.Mid(7,1));
sPosition.Format("%s%d",sPosition.Left(7),++l); //第八位+1:"88888888" = "88888889"
break;
}
break;
}
if(1 == nFlags) //如果标志为截取菜单名
{
if(source.Find(',')<=0)dest = source.Mid(index);
else dest = source.Mid(index,source.Find(',') - index); //取出菜单名到第一个参数引用中
}
return index;
}

------华软网友回复------

_declspec ( dllexport )int PASCAL out_num(LPCTSTR iniFile,HWND hWnd)
{
int menuID = 1001;

//AfxMessageBox(iniFile);
//SetWindowText(hWnd,"正在创建菜单");

  CString str;
CString sCrunode[8]; //记录菜单结点
CString sPosition = "00000000"; //用于记录当前建立菜单的索引值,向下传递建立菜单
HMENU myHandle[8]; //记录当前子菜单树的8个菜单节点位置,用于返回继续
int bOverwrite[8];
//bool bOverwrite = 0; //弹出菜单之主是否创建
CMenu menu; //创建主菜单项
CMenu* pSubMenu = new CMenu(); //创建一级子菜单项
menu.CreateMenu();
pSubMenu->CreatePopupMenu();
int i;
int oldindex = -1; //用来记录上一字符串的空格数量,如果不相等则重置菜单索引
int menuindex = -1; //用来标识目前所操作的菜单是主菜单的横向第几个
CStdioFile file;
if(!file.Open(iniFile,CFile::modeRead))return FALSE; //如果菜单文件不存在则返回失败

while(file.ReadString(str))
{
CString str1;
if('/' == str.Left(1) || str.GetLength()<2)continue; //判断文件内容是否注释或空格

switch(StringTok(str1,str,sPosition)) //返回0为主菜单,4为一级子菜单,8为二级子菜单...<=28
{ //str1返回的是菜单标题,str是constr常量引入源未分割的字符串进行分割
//sPosition返回菜单自定索引,主菜单文件的新建为"10000000",打开里的第一项为"21000000",编辑里的愎复为"20000000"
case 0:
pSubMenu->DestroyMenu();
pSubMenu->CreatePopupMenu();
memset(myHandle,0x00,sizeof(myHandle));
menu.AppendMenu(MF_POPUP,(UINT)pSubMenu->m_hMenu,str1); //空格为0则加主菜单:文件、编辑、窗口...
for(i=0;i<8;i++) sCrunode[i].Empty(); //初始化子本级子菜单为空
memset(myHandle,0x00,sizeof(myHandle)); //初始化子本级子菜单为空
memset(bOverwrite,0,sizeof(bOverwrite)); //初始化子本级子菜单为空

myHandle[0] = pSubMenu->m_hMenu;
sCrunode[0] = str1;
bOverwrite[0] = 0;
break;
case 4:
if('-' == str1.GetAt(0))
CMenu::FromHandle(myHandle[0])->AppendMenu(MF_SEPARATOR,menuID++,""); //如果为'-'则添加分隔栏
else 
CMenu::FromHandle(myHandle[0])->AppendMenu(MF_STRING,menuID++,str1);

for(i=1;i<8;i++)sCrunode[i].Empty(); //初始化子本级子菜单为空
for(i=1;i<8;i++)bOverwrite[i] = 0; //初始化子本级子菜单为空
sCrunode[1] = str1;
bOverwrite[1] = 0;
break;
case 8: //先将上一级的子菜单样式改为可弹出式,然后向菜单中增加内容
if(0 == bOverwrite[1]) //创建弹出菜单
{
bOverwrite[1] = 1; //判断如果上级菜单存在则设置标志
CMenu* pNewMenu = new CMenu();
pNewMenu->DestroyMenu();
pNewMenu->CreatePopupMenu();
CMenu::FromHandle(myHandle[0])->ModifyMenu(menuID-1,MF_BYCOMMAND|MF_POPUP,(UINT)pNewMenu->m_hMenu,sCrunode[1]);
myHandle[1] = pNewMenu->m_hMenu;
pNewMenu->Detach();
delete pNewMenu;
}

if(myHandle[1]) //创建弹出菜单内容
{
CMenu::FromHandle(myHandle[1])->AppendMenu(MF_STRING,menuID++,str1);
}

for(i=2;i<8;i++)myHandle[i] = NULL; //初始化子本级子菜单为空
for(i=2;i<8;i++)sCrunode[i].Empty(); //初始化子本级子菜单为空
for(i=2;i<8;i++)bOverwrite[i] = 0; //初始化子本级子菜单为空
sCrunode[2] = str1;
bOverwrite[2] = 0;

break;
case 12:
if(0 == bOverwrite[2]) //创建弹出菜单
{
bOverwrite[2] = 1; //判断如果上级菜单存在则设置标志
CMenu* pNewMenu = new CMenu();
pNewMenu->DestroyMenu();
pNewMenu->CreatePopupMenu();
CMenu::FromHandle(myHandle[1])->ModifyMenu(menuID-1,MF_BYCOMMAND|MF_POPUP,(UINT)pNewMenu->m_hMenu,sCrunode[2]);
myHandle[2] = pNewMenu->m_hMenu;
pNewMenu->Detach();
delete pNewMenu;
}

if(myHandle[2]) //创建弹出菜单内容
{
CMenu::FromHandle(myHandle[2])->AppendMenu(MF_STRING,menuID++,str1);
}

for(i=3;i<8;i++)myHandle[i] = NULL; //初始化子本级子菜单为空
for(i=3;i<8;i++)sCrunode[i].Empty(); //初始化子本级子菜单为空
for(i=3;i<8;i++)bOverwrite[i] = 0; //初始化子本级子菜单为空
sCrunode[3] = str1;
bOverwrite[3] = 0;

break;
case 16:
if(0 == bOverwrite[3]) //创建弹出菜单
{
bOverwrite[3] = 1; //判断如果上级菜单存在则设置标志
CMenu* pNewMenu = new CMenu();
pNewMenu->DestroyMenu();
pNewMenu->CreatePopupMenu();
CMenu::FromHandle(myHandle[2])->ModifyMenu(menuID-1,MF_BYCOMMAND|MF_POPUP,(UINT)pNewMenu->m_hMenu,sCrunode[3]);
myHandle[3] = pNewMenu->m_hMenu;
pNewMenu->Detach();
delete pNewMenu;
}

if(myHandle[2]) //创建弹出菜单内容
{
CMenu::FromHandle(myHandle[3])->AppendMenu(MF_STRING,menuID++,str1);
}

for(i=4;i<8;i++)myHandle[i] = NULL; //初始化子本级子菜单为空
for(i=4;i<8;i++)sCrunode[i].Empty(); //初始化子本级子菜单为空
for(i=4;i<8;i++)bOverwrite[i] = 0; //初始化子本级子菜单为空
sCrunode[4] = str1;
bOverwrite[4] = 0;

break;
case 20:
if(0 == bOverwrite[4]) //创建弹出菜单
{
bOverwrite[4] = 1; //判断如果上级菜单存在则设置标志
CMenu* pNewMenu = new CMenu();
pNewMenu->DestroyMenu();
pNewMenu->CreatePopupMenu();
CMenu::FromHandle(myHandle[3])->ModifyMenu(menuID-1,MF_BYCOMMAND|MF_POPUP,(UINT)pNewMenu->m_hMenu,sCrunode[4]);
myHandle[4] = pNewMenu->m_hMenu;
pNewMenu->Detach();
delete pNewMenu;
}

if(myHandle[3]) //创建弹出菜单内容
{
CMenu::FromHandle(myHandle[4])->AppendMenu(MF_STRING,menuID++,str1);
}

for(i=5;i<8;i++)myHandle[i] = NULL; //初始化子本级子菜单为空
for(i=5;i<8;i++)sCrunode[i].Empty(); //初始化子本级子菜单为空
for(i=5;i<8;i++)bOverwrite[i] = 0; //初始化子本级子菜单为空
sCrunode[5] = str1;
bOverwrite[5] = 0;

break;
case 24:
if(0 == bOverwrite[5]) //创建弹出菜单
{
bOverwrite[5] = 1; //判断如果上级菜单存在则设置标志
CMenu* pNewMenu = new CMenu();
pNewMenu->DestroyMenu();
pNewMenu->CreatePopupMenu();
CMenu::FromHandle(myHandle[4])->ModifyMenu(menuID-1,MF_BYCOMMAND|MF_POPUP,(UINT)pNewMenu->m_hMenu,sCrunode[5]);
myHandle[5] = pNewMenu->m_hMenu;
pNewMenu->Detach();
delete pNewMenu;
}

if(myHandle[4]) //创建弹出菜单内容
{
CMenu::FromHandle(myHandle[5])->AppendMenu(MF_STRING,menuID++,str1);
}

for(i=6;i<8;i++)myHandle[i] = NULL; //初始化子本级子菜单为空
for(i=6;i<8;i++)sCrunode[i].Empty(); //初始化子本级子菜单为空
for(i=6;i<8;i++)bOverwrite[i] = 0; //初始化子本级子菜单为空
sCrunode[6] = str1;
bOverwrite[6] = 0;

break;
case 28:
if(0 == bOverwrite[6]) //创建弹出菜单
{
bOverwrite[6] = 1; //判断如果上级菜单存在则设置标志
CMenu* pNewMenu = new CMenu();
pNewMenu->DestroyMenu();
pNewMenu->CreatePopupMenu();
CMenu::FromHandle(myHandle[5])->ModifyMenu(menuID-1,MF_BYCOMMAND|MF_POPUP,(UINT)pNewMenu->m_hMenu,sCrunode[6]);
myHandle[6] = pNewMenu->m_hMenu;
pNewMenu->Detach();
delete pNewMenu;
}

if(myHandle[5]) //创建弹出菜单内容
{
CMenu::FromHandle(myHandle[6])->AppendMenu(MF_STRING,menuID++,str1);
}

for(i=7;i<8;i++)myHandle[i] = NULL; //初始化子本级子菜单为空
for(i=7;i<8;i++)sCrunode[i].Empty(); //初始化子本级子菜单为空
for(i=7;i<8;i++)bOverwrite[i] = 0; //初始化子本级子菜单为空
sCrunode[7] = str1;
bOverwrite[7] = 0;

break;

}
}

SetMenu(hWnd,menu);
DrawMenuBar(hWnd);
menu.Detach();
pSubMenu->Detach();
delete pSubMenu;
SendMessage(hWnd,WM_PAINT,0,0);

file.Close();

return 0;
}

------华软网友回复------
以下是.ini文件中的内容

// address,menuname,bitmapname
//索引方式排序,命令处理自动建立,注意子弹出菜单前面的是4个空格
//注意,最多可以创建8级子菜单

文件 &F,C:\image.dll-1
    新建 CTRL+N,C:\image.dll-2
    打开 CTRL+O
        打开EXE文件
        打开TXT文件
    关闭
        文档
        工程
        项目
            我的项目
            他的项目
    -
    打印
        这个
        那个
    打印预览
    -
    退出

编辑 &E,
    撤消 CTRL+Z
    愎复 CTRL+Y
    -
    剪切 CTRL+X
    复制 CTRL+C
    粘贴 CTRL+V
    删除 DEL
视图 &V,
    创建
    分割
    合并
        框架
        模块
        迭加
窗口 &W,
    2级子菜单
    2级子菜单1
        3级子菜单
        3级子菜单1
            4级子菜单
            4级子菜单1
                5级子菜单
                5级子菜单1
                    6级子菜单
                    6级子菜单1
                        7级子菜单
                        7级子菜单1
                            8级子菜单
                            8级子菜单1
帮助 &H,

------华软网友回复------
好贴
------华软网友回复------
能否全部在PB中实现,最好不要用API函数
------华软网友回复------
对xqk(夏乾坤) 汗一个。
这是vc还是pb啊?
------华软网友回复------
楼主留个地址吧,或者qq也行,给你发个动态创建菜单的例子
------华软网友回复------
总应该有一个根菜单吧只要有一个根菜单应该都可以创建出来的
动态菜单的好处就是把功能从程序中可以进行独立出来
再结合动态DATAWINDOW,有的时候加个功能就很方便不必编译程序
很爽的

------华软网友回复------
谢谢,我的EMAIL:caihbcy@163.com,QQ:34914729,请多多指教      
华软声明:本内容来自网络,如有侵犯您版权请来信指出,本站立即删除。