.菜单项

菜单中的每一项都有三个特性第一个特性是菜单中显示什么,它可以是字符串或位图。第二个特性是WM_COMMAND消息中Windows发送给程序的菜单ID,或者是在使用者选择菜单项时Windows显示的弹出式菜单的句柄。第三个特性是菜单项的属性,包括是否被禁用、无效化或被选中

虽然存取菜单资源的最常用方法是在窗口类别中指定菜单,您也可以使用其它方法。Windows应用程序可以使用LoadMenu函数将菜单资源加载内存中,如同LoadIcon和LoadCursor函数一样。LoadMenu传回一个菜单句柄。如果您在资源描述档中为菜单使用了名称,叙述如下:

hMenu = LoadMenu (hInstance, TEXT ("MyMenu")) ;  

如果使用了数值,那么LoadMenu呼叫采用如下的形式:

hMenu = LoadMenu (hInstance, MAKEINTRESOURCE (ID_MENU)) ;  

您也可以在窗口类别中指定NULL菜单,并且在CreateWindow呼叫中也指定NULL菜单,然后在窗口被建立后再给窗口指定一个菜单:

SetMenu (hwnd, hMenu) ;  

菜单和消息

当使用者选择一个菜单项时,Windows通常向窗口消息处理程序发送几个不同的消息。在大多数情况下, 您的程序可以忽略大部分消息,只需把它们传递给DefWindowProc即可。WM_INITMENU就是这一类的消息,它具有下列参数:

wParam: 主菜单句柄

lParam: 0

wParam值是您的主菜单句柄,即使使用者选择的是系统菜单中的项目。Windows程序通常忽略WM_INITMENU消息。尽管在选中该项之前的消息已经给程序提供了修改菜单的机会,但是我们觉得此刻改变顶层菜单是会扰乱使用者的。

程序也会接收到WM_MENUSELECT消息。随着使用者在菜单项中移动光标或者鼠标,程序会收到许多WM_MENUSELECT消息。这对实作那些包含对菜单项的文字描述的状态列是很有帮助的。WM_MENUSELECT的参数如下所示:

LOWORD (wParam):被选中项目:菜单ID或者弹出式菜单句柄

HIWORD (wParam):选择旗标

lParam: 包含被选中项目的菜单句柄

WM_MENUSELECT是一个菜单追踪消息,wParam的值告诉您目前选择的是菜单中的哪一项(加高亮度显示的那个),wParam的高字组中的「选择旗标」可以是下列这些旗标的组合:MF_GRAYED、MF_DISABLED、MF_CHECKED、MF_BITMAP、MF_POPUP、MF_HELP、MF_SYSMENU和MF_MOUSESELECT。如果您需要根据对菜单项的选择来改变窗口显示区域的内容,那么您可以使用WM_MENUSELECT消息。许多程序把该消息发送给DefWindowProc。

当Windows准备显示一个弹出式菜单时,它给窗口消息处理程序发送一个WM_INITMENUPOPUP消息,参数如下:

wParam: 弹出式菜单句柄

LOWORD (lParam):弹出式菜单索引

HIWORD (lParam): 系统菜单为1,其它为0

为此,首先要得到菜单句柄:

hMenu = GetMenu (hwnd) ;
CheckMenuItem函数用来取消目前被选中的项目:
CheckMenuItem (hMenu, iSelection, MF_UNCHECKED) ;

iSelection的值被设定为wParam的值,新的背景颜色被选中:

iSelection = wParam ;        CheckMenuItem (hMenu, iSelection, MF_CHECKED) ;  MenuItem (hMenu, IDM_TIMER_START, MF_GRAYED) ;  

改变菜单

我们已经看到了如何使用AppendMenu函数为程序定义菜单以及将菜单项加入到系统菜单中。在Windows 3.0之前,您不得不被迫使用ChangeMenu函数来完成这种工作。ChangeMenu函数有很多功能,至少在当时,整个Windows中它是最复杂的函数之一。现在,许多函数都比ChangeMenu函数还要复杂,并且ChangeMenu的功能被分解为五个新的函数:

  • AppendMenu在菜单尾部添加一个新的菜单项目
     
  • DeleteMenu删除菜单中一个现有的菜单项并清除该项目
     
  • InsertMenu在菜单中插入一个新项目
     
  • ModifyMenu修改一个现有的菜单项目
     
  • RemoveMenu从菜单中移走某一项目

您可以使用下列命令来获得弹出式菜单的句柄:


 

hMenuPopup = GetSubMenu (hMenu, iPosition) ;   


 

其中iPosition是hMenu指示的顶层菜单中弹出式菜单项的索引(开始为0)。然后您可以在其它函数中使用弹出式菜单句柄(例如在AppendMenu函数中)。

您可以使用下列命令获得顶层菜单或者弹出式菜单中目前的项数:


 

iCount = GetMenuItemCount (hMenu) ;          


 

您可以取得弹出式菜单项的菜单ID:


 

id = GetMenuItemID (hMenuPopup, iPosition) ;          


 

其中iPosition是菜单项在弹出式菜单中的位置(以0开始)。

在MENUDEMO中您已经看到如何选中、或者取消选中弹出式菜单中的某一项:


 

CheckMenuItem (hMenu, id, iCheck) ;          


 

在MENUDEMO中,hMenu是顶层菜单的句柄,id是菜单ID,而iCheck的值是MF_CHECKED或MF_UNCHECKED。如果hMenu是弹出式菜单句柄,那么参数id是位置索引而不是菜单ID。如果使用索引会更方便的话,那么您可以在第三个参数中包含MF_BYPOSITION,例如:


 

CheckMenuItem (hMenu, iPosition, MF_CHECKED | MF_BYPOSITION) ;          


 

除了第三个参数是MF_ENABLED、MF_DISABLED或MF_GRAYED外,EnableMenuItem函数与CheckMenuItem函数所完成的工作类似。如果您在具有弹出式菜单的顶层菜单项上使用EnableMenuItem,那么必须在第三个参数中使用MF_BYPOSITION标识符,因为菜单项没有菜单ID。我们将在本章后面所示的POPPAD2程序中看到EnableMenuItem的一个例子。 HiliteMenuItem也类似于CheckMenuItem和EnableMenuItem,但是它使用的是MF_HILITE和MF_UNHILITE。当您在菜单项之间移动时,Windows使用反白显示方式加亮显示菜单项。您通常不需要使用HiliteMenuItem。

您还需要对您的菜单做些什么呢?还记得我们在菜单中使用了哪些字符串吗?您可以透过下面的呼叫来回顾一下:


 

iCharCount = GetMenuString (hMenu, id, pString, iMaxCount, iFlag) ;          


 

iFlag可以是MF_BYCOMMAND(其中id是菜单ID),也可以是MF_BYPOSITION(其中的id是位置索引)。函数将字符串的iMaxCount个字节复制到pString中,并传回复制的字节数。

或许您也想知道菜单项目前的属性是什么:


 

iFlags = GetMenuState (hMenu, id, iFlag) ;          


 

同样地,iFlag可以是MF_BYCOMMAND或MF_BYPOSITION。传回值iFlags是目前所有属性的组合,您可以通过对MF_DISABLED、MF_GRAYED、MF_CHECKED、MF_MENUBREAK、MF_MENUBARBREAK和MF_SEPARATOR标识符的检测来决定目前的属性。

也许现在您对菜单有了一些了解。这时您可能想知道,如果您不再需要菜单时又应该如何处理。您可以使用下面的命令来清除菜单:


 

DestroyMenu (hMenu) ;          



原文地址:https://www.cnblogs.com/tianlangshu/p/1989546.html