在程序窗口建立之后,POORMENU得到一个系统菜单的句柄:
hMenu = GetSystemMenu (hwnd, FALSE) ;
第一次呼叫GetSystemMenu时,您应该为修改菜单作准备,将第二个参数设定为FALSE。
使用四个AppendMenu呼叫来实作对菜单的修改:
AppendMenu (hMenu, MF_SEPARATOR, 0, NULL) ;
AppendMenu (hMenu, MF_STRING, IDM_SYS_ABOUT, TEXT ("About...")) ;
AppendMenu (hMenu, MF_STRING, IDM_SYS_HELP, TEXT ("Help...")) ;
AppendMenu (hMenu, MF_STRING, IDM_SYS_REMOVE, TEXT ("Remove Additions"));
第一个AppendMenu呼叫是添加分隔条。选择「Remove Additions」菜单项将使POORMENU删除这些附加的菜单项,这只要把第二个参数设定为TRUE,再次呼叫GetSystemMenu即可:
GetSystemMenu (hwnd, TRUE) ;
标准系统菜单有下列选项:Restore、Move、Size、Minimize、Maximize和Close。它们产生wParam分别等于SC_RESTORE、SC_MOVE、SC_SIZE、SC_MINIMUM、SC_MAXIMUM和SC_CLOSE的WM_SYSCOMMAND消息。尽管Windows程序一般不这样做,但是您可以自己处理这些消息,而不把它们留给DefWindowProc。您也可以使用下面所述的方法来禁止或者除掉系统菜单的标准选项。Windows文件中还介绍了一些系统菜单的标准附加项目,这些附加项目使用标识符SC_NEXTWINDOW、SC_PREVWINDOW、SC_VSCROLL、SC_HSCROLL和SC_ARRANGE。您也许会发现,在一些应用程序中将这些命令加入系统菜单是合适的。
改变菜单
我们已经看到了如何使用AppendMenu函数为程序定义菜单以及将菜单项加入到系统菜单中。在Windows 3.0之前,您不得不被迫使用ChangeMenu函数来完成这种工作。ChangeMenu函数有很多功能,至少在当时,整个Windows中它是最复杂的函数之一。现在,许多函数都比ChangeMenu函数还要复杂,并且ChangeMenu的功能被分解为五个新的函数:
- AppendMenu在菜单尾部添加一个新的菜单项目
- DeleteMenu删除菜单中一个现有的菜单项并清除该项目
- InsertMenu在菜单中插入一个新项目
- ModifyMenu修改一个现有的菜单项目
- RemoveMenu从菜单中移走某一项目
如果菜单项是一个弹出式菜单,那么DeleteMenu和RemoveMenu之间的区别就很重要。DeleteMenu清除弹出式菜单,但RemoveMenu不清除它。
其它菜单命令
下面是在使用菜单时一些有用的函数。
当您改变顶层菜单项时,直到Windows重画菜单列时才显示所做的改变。您可以通过下列呼叫来强迫执行菜单更新:
DrawMenuBar (hwnd) ;
注意,DrawMenuBar的参数是窗口句柄而不是菜单句柄。
您可以使用下列命令来获得弹出式菜单的句柄:
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) ;
从而使菜单句柄无效。
本文详细介绍了Windows程序中菜单的使用,包括如何通过AppendMenu、DeleteMenu等函数修改系统菜单,菜单项的增删改查,以及如何强制更新菜单显示。此外,还探讨了菜单项的选中状态、禁用、高亮等属性的设置和获取。

5047

被折叠的 条评论
为什么被折叠?



