动态创建级联菜单

菜单是Windows的标准界面元素,几乎所有的Windows应用程序中都有它的身影。MFC中的类CMenu对它进行了封装,使其使用起来更加简便。要在程序中使用菜单也很简单,一般分以下几步:第一步先用VC的菜单编辑器创建一个菜单资源,给它赋予我们自己定义的ID,第二步在程序中构造一个CMenu类的对象,用CMenu::LoadMenu函数将菜单从资源中装入,接着调用CWnd::SetMenu函数将新菜单连到相应的窗口中,最后切记,要调用Detach成员函数把CMenu对象和菜单分离,以确保当CMenu对象生存期结束时,菜单不会被销毁。   
    
  以上是在程序中使用菜单的一般步骤,但有时候,我们在设计期是无法确定菜单包含哪些项的,这时这种事先设计好菜单资源的方法就行不通了。为了解决这个问题,必须要用到动态创建菜单的技术。通过CMenu类所提供的CreateMenu/CreatePopupMenu、AppendMenu/InsertMenu等函数,可以很方便地实现菜单的动态创建。下面简单地介绍一下这几个函数(函数原型和参数注释请查阅MSDN,这里不再赘述),然后用几个实例,讲解动态创建菜单的步骤。   
    
  CreateMenu函数用来创建一个空的菜单,并将其绑定到该CMenu对象上。要添加菜单项,可以使用CMenu的AppendMenu/InsertMenu成员函数(稍后我会介绍这两个函数有何不同)。如果这个创建出来的菜单是连到一个窗口上的,那么在窗口被销毁的时候,菜单会自动随之销毁;如果这个菜单不属于任何窗口,那么程序退出前,必须手动销毁菜单以及和它相关联的一切系统资源。销毁菜单用的是CMenu的DestroyMenu成员函数。   
    
  CreatePopupMenu和CreateMenu类似,只不过它创建的是一个空的浮动菜单(Pop-up   Menu),和普通菜单不同的是,浮动菜单既可以连到别的菜单上(连到普通菜单或者浮动菜单都可以)成为次级子菜单,也可以连接到某个窗口上;而普通菜单只能连接到某个窗口上。   
    
  AppendMenu用于在菜单的末尾追加一个菜单项,而InsertMenu可以在菜单的指定位置插入一个菜单项。这里尤其要注意的就是第一个参数,如果添加的菜单项,是要弹出另一个子菜单的(比如下图所示的“View”菜单项),那么第一个参数nFlags一定要包含MF_POPUP标志,同时第二个参数nIDNewItem设置成子菜单的句柄。具体后面会详细讲述。   
    
      
    
  Menu和Pop-up   Menu,是有区别的。普通菜单(就是用CreateMenu函数创建出来的菜单),直观地说,就是固定在标题栏下方的菜单,每Append一个菜单项,横向上就多出一列出来。让我们在OnInitDialog函数中添加如下代码:   
    
  CMenu Menu;   
    
  Menu.CreateMenu();   
    
  SetMenu(&Menu);   
    
  Menu.Detach();   
    
  编译运行,没有效果,这是显而易见的,因为这时Menu还是空的,因为我们没有添加任何菜单项。截图如下:   
    
      
    
  好,现在让我们向菜单中添加一个菜单项。在Menu.CreateMenu()语句下面插入下面的代码:   
    
  Menu.AppendMenu(MF_STRING,   ID_APP_FILE,   "&File");   
    
  好了,有效果了,出来一个菜单,但是鼠标按下去什么都没有,仔细想想也很合理,只是添加了一个菜单项而已,一个菜单项怎么会弹出另一个菜单呢?效果如下(可以看到鼠标按下去什么都没有出来)   
    
      
    
  还记得刚才我说的吗,普通菜单其实就是横向的那一条,每一个都是一个菜单项。好,现在让我们来试验一下,再在Menu中添加一个菜单项:   
    
  Menu.AppendMenu(MF_STRING,   ID_APP_EDIT,   "&Edit");   
    
  可以看到又出来一项,仍然是按下去什么都没有,但这证明了我们之前的结论——Menu就好比横过来的一个菜单,有固定的位置。   
    
      
    
  如何要让这个菜单项按下去出现另一个菜单,就要另外创建一个浮动菜单(Pop-up   Menu),因为只有浮动菜单可以连到另一个菜单中去。好,让我们修改代码成下面这个样子:   
    
  CMenu Menu,PopupMenu;   
    
    
    
  Menu.CreateMenu();   
    
  PopupMenu.CreatePopupMenu();   
    
    
    
  PopupMenu.AppendMenu(MF_STRING,IDC_POPMENU_FILE_NEW,"&New");   
    
  PopupMenu.AppendMenu(MF_STRING,IDC_POPMENU_FILE_OPEN,"&Open");   
    
  PopupMenu.AppendMenu(MF_STRING,IDC_POPMENU_FILE_CLOSE,"&Close");   
    
  PopupMenu.AppendMenu(MF_STRING,IDC_POPMENU_FILE_EXIT,"E&xit");   
    
    
    
  Menu.AppendMenu(MF_POPUP,   (UINT)PopupMenu.m_hMenu,   "&File");   //关键!   
    
  Menu.AppendMenu(MF_STRING,   ID_APP_EDIT,   "&Edit");   
    
    
    
  SetMenu(&Menu);   
    
  Menu.Detach();   
    
  PopupMenu.Detach();   
    
  然后看看效果:   
    
      
    
  现在我们来详细分析一下上面的代码。   
    
  首先,再创建一个CMenu类的对象PopupMenu,然后调用函数CreatePopupMenu创建了一个空的浮动菜单。紧接着向这个空的浮动菜单中加入我们想要的菜单项。接着是最关键的一步:   
    
  Menu.AppendMenu(MF_POPUP,   (UINT)PopupMenu.m_hMenu,   "&File");   
    
  这一步是向普通菜单Menu中追加一项。注意这里的参数和下一句有什么不同。第一个参数设成MF_POPUP,表示本菜单项(即“File”这个菜单项),是用来操纵一个浮动菜单的,第二个参数,原本应该是新菜单项的命令ID,这里设成子菜单的句柄。因为单击Fiile菜单项的时候,它的动作是弹出浮动菜单,所以它就没有必要拥有命令ID了(命令ID只是为了处理单击消息而设),最后一个参数,是这个菜单项在Menu中的标题,如果换成别的字符串,譬如Hello,那么最上面的File将变成Hello。   
    
  这里要强调一点,普通的Menu(相对Pop-up   Menu而言),就只是标题栏下面那一条,这一行上都是它的菜单项(你可以把它看成是一个横过来放的菜单);而所有在鼠标点击后才出现的菜单(不管是左键还是右键),统统都是Pop-up   Menu(也可以认为,Menu就是横排的菜单,Pop-up   Menu就是竖排的菜单)。以一个Windows   Shell窗口为例,只有最上一行才是Menu,其中诸如“文件”,“编辑”等等,每个都是Menu的一个Item,其余,都是Pop-up   Menu。   
    
      
    
  最后简单介绍一下如何实现右键弹出菜单。步骤很简单:首先,映射WM_CONTEXTMENU消息,在消息处理函数中,先通过指定要弹出的子菜单的位次,用函数GetSubMenu函数得到该子菜单的指针。这里要注意,指定位次的菜单项,必须是有MF_POPUP属性的,并且的菜单项是从上到下以0为开始计数的(对于普通Menu则是从左到右)。得到想要的菜单的指针后,就可以用函数TrackPopupMenu把菜单在指定的位置显示出来了。整个用于显示的代码只有一行即可(当然为了安全性可以增加一些ASSERT宏进行检测,这里为了突出重点而略过):   
    
  GetMenu()->GetSubMenu(0)->   
    
  TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);   
    
  这里GetMenu得到最上面的主菜单指针,GetSubMenu(0)得到File下面的Pop-up菜单指针,最后用TrackPopupMenu将其显示出来。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你可以使用 JavaScript 和 HTML 来实现级联菜单。首先,你需要创建一个包含所有选项的数组,然后使用 JavaScript 动态地创建下拉菜单。当用户选择第一个下拉菜单的选项时,使用 JavaScript 更新第二个下拉菜单的选项。具体实现方法可以参考以下代码: HTML 代码: ``` <select id="firstMenu" onchange="updateSecondMenu()"> <option value="">请选择</option> <option value="option1">选项1</option> <option value="option2">选项2</option> <option value="option3">选项3</option> </select> <select id="secondMenu"> <option value="">请选择</option> </select> ``` JavaScript 代码: ``` var menuOptions = { option1: ["子选项1", "子选项2", "子选项3"], option2: ["子选项4", "子选项5", "子选项6"], option3: ["子选项7", "子选项8", "子选项9"] }; function updateSecondMenu() { var firstMenu = document.getElementById("firstMenu"); var secondMenu = document.getElementById("secondMenu"); var selectedOption = firstMenu.options[firstMenu.selectedIndex].value; while (secondMenu.options.length) { secondMenu.remove(); } var menuItems = menuOptions[selectedOption]; if (menuItems) { var i; for (i = ; i < menuItems.length; i++) { var menuItem = new Option(menuItems[i], i); secondMenu.options.add(menuItem); } } } ``` 在这个例子,我们创建了一个名为 menuOptions 的对象,其包含了每个选项的子选项。当用户选择第一个下拉菜单的选项时,我们使用 updateSecondMenu 函数来更新第二个下拉菜单的选项。我们首先获取第一个下拉菜单和第二个下拉菜单的元素,然后获取用户选择的选项。接着,我们清空第二个下拉菜单的选项,并根据用户选择的选项更新第二个下拉菜单的选项。最后,我们将新的选项添加到第二个下拉菜单。 ### 回答2: JavaScript级联菜单的实现可以通过以下步骤进行: 1. 首先,在HTML文件创建一个容器元素,用来容纳级联菜单。例如: ``` <div id="menu"></div> ``` 2. 在JavaScript代码定义一个包含菜单选项的数据结构。这可以是一个嵌套的对象或数组,每个选项都包含一个值和一个与之关联的子选项数组,例如: ``` var menuData = [ { value: "选项1", children: [ { value: "子选项1-1" }, { value: "子选项1-2" } ] }, { value: "选项2", children: [ { value: "子选项2-1" }, { value: "子选项2-2" } ] } ]; ``` 3. 创建一个函数来动态生成级联菜单。该函数应该接受一个父级菜单选项作为参数,并在该选项下生成子菜单。例如: ``` function generateMenu(parent) { var menu = document.createElement("select"); // 为菜单添加选项 for (var i = 0; i < parent.children.length; i++) { var option = document.createElement("option"); option.text = parent.children[i].value; option.value = i; menu.appendChild(option); } // 为菜单添加事件监听器 menu.addEventListener("change", function() { var selectedIndex = menu.options[menu.selectedIndex].value; if (parent.children[selectedIndex].children) { generateMenu(parent.children[selectedIndex]); } }); // 将菜单添加到容器元素 document.getElementById("menu").appendChild(menu); } ``` 4. 最后,在JavaScript调用`generateMenu`函数来初始化级联菜单。例如: ``` generateMenu({ children: menuData }); ``` 以上就是实现JavaScript级联菜单的基本步骤。你可以根据需要自定义菜单的样和交互行为。 ### 回答3: JavaScript级联菜单的实现是通过动态改变下拉菜单选项的方法来实现的。下面是一个简单的例子,说明如何使用JavaScript来实现级联菜单。 首先,我们需要创建HTML结构,包括一个用于选择的父级下拉菜单和一个用于显示子级下拉菜单的元素。如下所示: ```html <select id="parentMenu" onchange="changeChildMenu()"> <option value="">请选择父级菜单</option> <option value="1">菜单1</option> <option value="2">菜单2</option> <option value="3">菜单3</option> </select> <div id="childMenu" style="display: none;"> <select id="childSelect"> <option value="">请选择子级菜单</option> </select> </div> ``` 接下来,我们需要编写JavaScript代码来实现级联菜单的效果。我们可以使用`change`事件来监听父级下拉菜单的变化,并根据所选值来动态改变子级下拉菜单的选项。如下所示: ```javascript function changeChildMenu() { var parentValue = document.getElementById('parentMenu').value; var childSelect = document.getElementById('childSelect'); // 清空子级下拉菜单的选项 childSelect.innerHTML = '<option value="">请选择子级菜单</option>'; // 根据所选值动态添加子级下拉菜单的选项 if (parentValue === '1') { childSelect.innerHTML += '<option value="11">子菜单1</option>'; childSelect.innerHTML += '<option value="12">子菜单2</option>'; } else if (parentValue === '2') { childSelect.innerHTML += '<option value="21">子菜单3</option>'; childSelect.innerHTML += '<option value="22">子菜单4</option>'; } else if (parentValue === '3') { childSelect.innerHTML += '<option value="31">子菜单5</option>'; childSelect.innerHTML += '<option value="32">子菜单6</option>'; } // 显示子级下拉菜单 document.getElementById('childMenu').style.display = 'block'; } ``` 在上面的代码,我们使用了`innerHTML`属性来动态改变子级下拉菜单的选项。根据所选的父级菜单的值,我们通过添加新的`option`元素来动态改变子级菜单的选项。 最后,通过调用`changeChildMenu()`函数,我们可以在父级下拉菜单的选项改变时触发级联效果。 以上就是用JavaScript实现级联菜单的基本步骤。根据实际需求,你可以修改代码来适应不同的菜单结构和选项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值