当前位置:C++技术网 > 精选软件 > Windows零基础入门:3.4 菜单使用1-Win32菜单添加详细分析

Windows零基础入门:3.4 菜单使用1-Win32菜单添加详细分析

更新时间:2015-09-30 10:56:09浏览次数:1+次

    前面两节讲了应用程序图标和窗口上的图标的设置方法,现在来点菜单咯。
    那么什么是菜单呢?菜单就是一个功能列表的意思。根据功能的分类,划分到不同的菜单组中。通过菜单,我们可以将大量的功能,都放在菜单里。这样使用功能时,就可以轻松快速的找到。
    因为菜单的使用,我们将会专门讲,不过在此,就讲解一些最基本的操作,搭建起使用菜单的流程套路。
    菜单和应用程序图标、光标一样,都是资源。所以,要使用的话,需要提前准备好。我们就在VS的“资源视图”界面中,添加一个菜单。新建一个就可以了。添加好菜单之后,系统自动给菜单指定了一个菜单ID。这个ID默认定义于Resource.h头文件中。所以,如果你要使用菜单,要么就要包含这个头文件,要么就将这个菜单的ID定义于你的cpp文件中,最后还有一招,就是你直接修改菜单的ID为字符串。单击“资源视图”下的“Menu”下的菜单,然后在属性面板中,将ID条目的内容添加上双引号即可。后面就可以直接根据菜单的名称来使用菜单了。菜单面板如下图所示:
   
    然后给菜单添加一系列菜单项。我建立了两个弹出菜单“菜单A”和“菜单B”,然后在下面分别建立了菜单项“菜单1”和“菜单2”.如下图所示:

   
    “菜单A”、“菜单B”是主菜单的两个菜单项,单击“菜单A”或者“菜单B”后,会弹出一个列表,这个列表就是子菜单。单击之后会弹出子菜单的菜单项,就是弹出式菜单项,这个菜单项不会执行我们的代码的,用于连接子菜单用的。所以,我们无法对这个添加单击的执行代码。那么点击菜单后会执行代码的菜单项,就是最普通的菜单项咯。单击这个普通的菜单项后,就会执行我们设定好的菜单响应代码。
    弹出式菜单项无法设置菜单的ID,它的Popup属性是True。也就是说,只要你把一个菜单项的Popup属性设置为True,它就是弹出式菜单项了。这样你就可以给这个菜单项添加子菜单,那么它被单击或者鼠标滑过的时候,会显示子菜单。
    在VS菜单编辑器中,只要你给一个菜单项添加了子菜单,那么这个菜单项就自动变成了弹出式菜单项,那么它的Popup属性就被设置为了True。在属性面板中,你可以看到Popup这个选项,可以自己修改。当你从Popup=True改为False时,那么这个菜单项的子菜单就要被删除。
    好了,说了一些背景知识,够了。更详细的,见后面的章节。添加了菜单项之后,VS自动给菜单项定了一个ID。这个ID在消息响应时候需要。
    那么在窗口类结构体变量赋值时,给菜单名称赋值一个菜单的名称即可。代码如下:

WNDCLASS wndclass;
wndclass.lpszMenuName =L"MY_MENU";
...
     这样运行之后,就可以看到这个菜单在窗口中了。如下图所示:
   
    我们很可能在菜单的名字上翻船。很多人还搞不清楚,这里特别解释一下。
    我们添加菜单的时候,系统会自动在资源头文件resource.h中给菜单资源定义一个ID,以后就可以使用ID来引用菜单了。不过,你自己将ID改为带双引号的,就表示,这个菜单就使用字符串来引用。字符串不需要在哪定义,就是一个常量字符串而已。使用字符串来引用菜单,不需要包含资源头文件了。就和上面的代码一样使用即可。而使用数字ID来引用,反而麻烦。因为窗口类结构体变量的菜单成员类型是字符串类型,所以使用字符串引用菜单当然是最便捷的。如果用数字ID,那么就要使用MAKEINTRESOURCE(数字资源ID),返回一个字符串类型的值。
    那么你只需要去掉菜单ID中的双引号即可。这样VS自动在资源头文件中给这个ID定义一个整型的数字宏。那么使用这样的菜单,方法如下:
WNDCLASS wndclass;
wndclass.lpszMenuName = MAKEINTRESOURCE(MY_MENU);
...
     在rc资源定义文件中,只要资源编译器找不到rc中提到的符号的宏定义,那么就会将提到的标识符当做字符串来处理。所以,这也是为什么我们只要将菜单ID改成双引号,就可以不需要资源头文件的原因。
    我们看看资源定义文件.rc文件中的菜单定义,如下:
MY_MENU MENU
BEGIN
    POPUP "菜单A"
    BEGIN
        MENUITEM "菜单1",IDM_1
    END
    POPUP "菜单B"
    BEGIN
        MENUITEM "菜单2",ID_40003
    END
END
     定义语法我们不需要管,我们可以看到,MY_MENU、IDM_1和ID_40003,都是一个ID,如果它们没有被定义为数字宏,就会被看成是一个字符串,而不需要我们在这个符号上加上双引号。否则如果我们加上双引号,如"IDM_1",那么在资源视图中看到的就是多了一层双引号的,因为这个双引号也被当做一个字符而已。了解这个机制后,你就知道了,不用乱加了。
    那么资源编译器要识别这些标识符有没有被定义为一个数字,再决定编译的类型。比如:
#define IDM_1 1000
     被定义后,就会被当做一个数字的别名,就是一个数字宏。这个定义一般放在资源头文件中。不过你依然可以放在资源定义文件中。只要在这个标识符出现之前就好,不过不要重复定义哦。资源编译器也是从rc资源文件的开始扫描到最后。
    对于菜单的各方面的基础知识,也介绍了不少,添加菜单使用菜单是不成问题的了。下一节介绍菜单的事件响应,单击菜单项可以执行我们的代码,这样才有意思。