- glutCreateMenu 创建一个弹出式菜单
- glutAddMenuEntry 在当前菜单底部增加一个菜单条目
- glutAttachMenu 将当前的一个鼠标按键与当前菜单联系起来
- glutAddSubMenu 在当前菜单底部增加一个子菜单
- glutDetachMenu 释放当前窗口的一个鼠标按键
- 获取、设置标识符,删除、更改菜单
在电脑上点击一下鼠标右键,会出现一个菜单。通过本页内容,可以制作出一个这样的菜单(真实网站中不知道用的是什么库)。
示例结果如下图所示。
本节内容所用示例代码(建议先跳过,本节其它内容看完后再看该代码):
#include<windows.h>
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int menu=0,submenu1=0,submenu2;
//画一个绿色多边形
void draw(){
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0,1,0);
glOrtho(-1,1,-1,1,-1,1);
glBegin(GL_POLYGON);
glVertex2f(-0.5,-0.5);
glVertex2f(-0.5,0.5);
glVertex2f(0.5,0.5);
glVertex2f(0.5,-0.5);
glEnd();
glutSwapBuffers();
}
//点击某个条目时,输出该条目属于哪个菜单
void getcurrentmenu(){
int nmenu;
nmenu = glutGetMenu();
if(nmenu == menu)
printf("current is main menu.\n");
else if(nmenu == submenu1)
printf("current is sub menu 1.\n");
else if(nmenu == submenu2)
printf("current is sub menu 2.\n");
}
//第一个子菜单
void submenufunc1(int data){
getcurrentmenu();
switch(data){
case 1:
printf("sub menu 1's item 1 is triggered.\n");
break;
case 2:
printf("sub menu 1's item 2 is triggered.\n");
break;
case 3:
printf("sub menu 1's item 3 is triggered.\n");
break;
}
}
//第二个子菜单
void submenufunc2(int data){
getcurrentmenu();
switch(data){
case 1:
printf("sub menu 2's item 1 is triggered.\n");
break;
case 2:
printf("sub menu 2's item 2 is triggered.\n");
break;
case 3:
printf("sub menu 2's item 3 is triggered.\n");
break;
}
}
//主菜单
void menufunc(int data){
getcurrentmenu();
switch(data){
case 1:
printf("menu's item 1 is triggered.\n");
break;
case 2:
printf("menu's item 2 is triggered.\n");
break;
case 3:
printf("menu's item 3 is triggered.\n");
break;
}
}
int main(int argc,char *argv[]){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(0,0);
glutInitWindowSize(512,512);
glutCreateWindow("test");
glutDisplayFunc(draw);
//构建子菜单1的内容
submenu1 = glutCreateMenu(submenufunc1);
glutAddMenuEntry("1's item 1",1);
glutAddMenuEntry("1's item 2",2);
glutAddMenuEntry("1's item 3",3);
glutAttachMenu(GLUT_LEFT_BUTTON);
//构建子菜单2的内容
submenu2 = glutCreateMenu(submenufunc2);
glutAddMenuEntry("2's item 1",1);
glutAddMenuEntry("2's item 2",2);
glutAddMenuEntry("2's item 3",3);
glutAttachMenu(GLUT_RIGHT_BUTTON);
//构建主菜单的内容
menu = glutCreateMenu(menufunc);
glutAddMenuEntry("item 1",1);
glutAddMenuEntry("item 2",2);
glutAddMenuEntry("item 3",3);
//将两个菜单变为另一个菜单的子菜单
glutAddSubMenu("sub1",submenu1);
glutAddSubMenu("sub2",submenu2);
//点击鼠标右键时显示菜单
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
return 0;
}
名词解释:
菜单:
菜单条目:菜单中的某一选项。
和 都是菜单条目。
1. glutCreateMenu 创建一个弹出式菜单
int glutCreateMenu( void (* func) (int value) )
参数说明:func 与将要创建的这个菜单相关联的函数。这个函数的作用:点击菜单中的某一选项时,控制系统做出对应的反应。
value 传递给回调函数func的数值,由所选择的菜单条目对应的整型数值确定。
通俗点说,在创建每一个菜单条目时,都会被赋予一个唯一的值。点击某个条目时,该条目对应的值就会被传递给func函数,func函数根据传入的值得知用户点击了哪个条目,然后进行对应的操作。
下面的代码应该对你理解这个函数会有一点帮助。
void menufunc(int data){
getcurrentmenu();
switch(data){
case 1:
printf("menu's item 1 is triggered.\n");
break;
case 2:
printf("menu's item 2 is triggered.\n");
break;
case 3:
printf("menu's item 3 is triggered.\n");
break;
}
}
int main(){
menu = glutCreateMenu(menufunc);
//构建菜单内容
glutAddMenuEntry("item 1",1);
glutAddMenuEntry("item 2",2);
glutAddMenuEntry("item 3",3);
}
2. glutAddMenuEntry 在当前菜单底部增加一个菜单条目
void glutAddMenuEntry(char * name, int value)
参数说明:char *name 菜单条目的内容,比如示例结果图中的item 1和item 2.(这里的name没理解错的话,是地址指针)。
value,菜单条目的值(索引 )。在一个菜单中,每个条目都有唯一的数值用以区分。
该函数在上面已经有过初次见面了。
glutAddMenuEntry("item 1",1);
glutAddMenuEntry("item 2",2);
glutAddMenuEntry("item 3",3);
3. glutAttachMenu 将当前的一个鼠标按键与当前菜单联系起来
void glutAttachMenu(int button)
参数说明:button 指明在窗口中按哪种按键会使得菜单出现。可选择的符号常数为:GLUT_LEFT_BUTTON、GLUT_MIDDLE_BUTTON和 GLUT_RIGHT_BUTTON,分别表示鼠标左、中、右键。
示例代码的最后一行表示单机鼠标右键时会出现菜单。(键盘按键下一节会讲)
4. glutAddSubMenu 在当前菜单底部增加一个子菜单
void glutAddSubMenu(char * name, int menu)
参数说明: name 与glutAddMenuEntry中的name类似,这里是子菜单的名称,比如实际结果图中的 sub1和sub2。
代码示例:
本文开头示例代码的main函数里最后几行。
5. glutDetachMenu 释放当前窗口的一个鼠标按键
void glutDetachMenu(int button)
参数说明:button 与上一个相同
使用该代码后,会断开鼠标按键和菜单间的联系。点击鼠标按键,对应的菜单将不会再出现(就像游戏里已经被你放生的宠物)。
6. 获取、设置标识符,删除、更改菜单等
6.1 int glutGetMenu(void) 获取当前菜单的标识符
6.2 void glutSetMenu(int menu) 将菜单标识符对应的菜单设置为当前菜单 menu为菜单标识符
6.3 void glutDestroyMenu(int menu) 删除指定菜单 menu为菜单标识符
6.4 void glutChangeToMenuEntry(int entry, char * name, int value)
参数说明:entry 菜单条目的索引,最顶层的为1,向下依次递增。比如示例中item1,item2, item3,sub1,sub2条目的索引分别为1、2、3、4、5.
name 新的字符串
value 新的值,也就是glutAddMenuEntry(char *name, int value)中的value
这里可以理解为改变当前菜单条目的名字。
比如在示例代码的最后加上一行代码:
menu = glutCreateMenu(menufunc);
glutAddMenuEntry("item 1",1);
glutAddMenuEntry("item 2",2);
glutAddMenuEntry("item 3",3);
glutChangeToMenuEntry(1,"item",1);//增加的代码
glutAddSubMenu("sub1",submenu1);
glutAddSubMenu("sub2",submenu2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutMainLoop();
return 0;
}
运行结果如下:
item1 被改变为 item
不仅菜单条目可以改变,子菜单条目也可以改变,也就是示例中的sub1和sub2
6.5 void glutChangeToSubMenu(int entry, char *name, int menu)
将当前菜单指定的菜单条目更改为子菜单触发条目
参数说明:entry 与6.4的entry相同,为菜单项的索引
name,menu 与glutAddSubMenu(char *name, int menu)中的参数对应相同
6.6 void glutRemoveMenuItem(int entry)删除指定的菜单项
entry与6.4的entry相同,为菜单项的索引。