在Windows中的菜单编程

本文章参考<Windows游戏编程大师技巧(第二版)>

在Windows Application 中创建菜单过程如下所示:

1.      创建菜单资源

2.      应用程序装载菜单资源

3.      应用程序响应菜单事件消息

 

1.      创建菜单资源

在创建菜单资源的时候, 可以使用两种方式: 一是使用IDE编辑器来创建菜单; 二是使用人工的方式编辑.rc文件. 第一种方式在很多MFC教材中都有使用. 我在这里主要介绍人工方式来编辑菜单资源, 有助于大家了解使用IDE编程的资源.

如果你在*.rc资源脚本中创建一个菜单资源, 都必须创建一个*.H文件与之相对应, 用于解决资源的标示符的符号引用问题. 但有一种意外, 菜单名必须是符号,不能使名称字符串. 下面是在*.rc文件中常见的MEMU描述的基本语法:

MENU_NAME MENU DISCARDABLE

{

       POPUP “name”            

       {

              MENUITEM  “name”, MENU_ID

}

}

MENU_NAME可以是一个名称字符串或是一个符号, 关键字DISCARDABLE有点过时了但还是必须的. 菜单中的一级菜单定义都是以关键字POPUP开头的. 而菜单项是以MENUITEM定义的, 至于MENU_ID是在*.h文件中定义的. 如下例子:

// .RC资源文件中

MainMenu MENU DISCARDABLE

{

POPUP "File"

       {

       MENUITEM"Open",  MENU_FILE_ID_OPEN

       MENUITEM"Close", MENU_FILE_ID_CLOSE

       MENUITEM"Save",  MENU_FILE_ID_SAVE

       MENUITEM"Exit",  MENU_FILE_ID_EXIT

       } // end popup

 

POPUP "Help"

       {

       MENUITEM"About",  MENU_HELP_ABOUT

       } // end popup

 

} // end top level menu

 

// .H文件中

// defines for the top level menu FILE

#define MENU_FILE_ID_OPEN               1000

#define MENU_FILE_ID_CLOSE              1001

#define MENU_FILE_ID_SAVE               1002

#define MENU_FILE_ID_EXIT                1003

 

// defines for the top level menu HELP

#define MENU_HELP_ABOUT                 2000

在这里没有定义”MainMenu”, 这样可以通过字符串而不是ID来访问该菜单. 如果我向如下方式定义了该项的ID

#define MainMenu               100

必须使用MAKEINTRESOURCE(MainMenu)或MAKEINTRESOURCE(100)来访问该菜单资源.

如果想设置热键或者快捷键的话, 可以使用连字号(&)来达到这个功能. 例如:

MENUITEM “E&xit”, MENU_FILE_ID_EXIT

使x成为热键, 而

POPUP “&File”

使F成为通过Alt+F使用的快捷键

 

2.      装载菜单

在windows类的定义中, 定义菜单的代码是:

WNDCLASSEX wnd;

wnd.lpszMenuName = NULL;      //默认情况下

只需要将它赋值为该菜单的名称:

wnd.lpszMenuName = “MainMenu”;

wnd.lpszMenuName = MAKEINTRESOURCE(MainMenu);

这样做的话, 创建的每个窗口都会有一个相同的菜单. 要解决该问题的话,可以在创建菜单过程中通过传递菜单句柄来将一个菜单指定给一个窗口. 通过LoadMenu()装载菜单资源, 如果成功的话会返回一个HMENU句柄.

LoadMenu()原型:

HMENU LoadMenu(HINSTANCE hInstance, // handle of applicationinstance

              LPCTSTRlpMenuName); // menu name string or menu-resource identifier

通过标准的CreateWindow()函数, 将菜单”ManiMenu”装载到该菜单句柄参数中:

// create the window

hwnd = CreateWindowEx(NULL, WINDOW_CLASS_NAME, “Sound”,

WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 400, 400, NULL,

LoadMenu(hinstance, “MainMenu”), hinstance, NULL);

将菜单关联到窗口的最后一个方法是调用SetMenu()函数:

BOOL SetMenu( HWND hwnd, // handle of window to attach to

                     HMENUhMenu); // handle of menu

SetMenu()直接将该菜单关联到一个窗口上, 这个新菜单将优先于任何以前关联的菜单.例如:

// …

wnd.lpszMenuName = NULL;     

// …

hwnd = CreateWindowEx(NULL, WINDOW_CLASS_NAME, “Sound”,

WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 400, 400, NULL,

NULL,    // handle to menu ,note it’s null.

hinstance, NULL);                                                                                                        

//…

// load the menu resource

HMENU hMenu = LoadMenu(hinstance, “MainMenu”);

// attach the menu to the window

SetMenu(hwnd, hMemu);

 

3.      响应菜单事件的消息

在选中一个菜单项后放开鼠标时的消息传递,这指的是一个选择过程. 选择过程将一个WM_COMMAND消息传递到与该菜单关联的窗口的WinProc函数中. 指定的菜单项ID和其他各种数据存储在该消息的wparam和lparam中, 如下所示:

msg --- WM_COMMAND

LOWORD(lparam) ---- 发出消息的窗口句柄

wparam --- 选中的菜单项的ID

 

编译可能出现的错误:

DemoMenu.obj : error LNK2001: unresolved external symbol__imp__PlaySoundA@12

将winmm.lib添加到工程中, 过程: 工程->设置->连接->在工程选项中添加winmm.lib.


参考代码下载地址:  http://download.csdn.net/detail/sund71/4426117


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值