No MFC,Only API——菜单的创建和使用:
在使用菜单之前,值得一提的是,包含菜单的窗口必须是POPUP-UP或OVERLAPPED风格,才可能拥有菜单。
菜单的创建有三种方法:1,在WINDOWCLASS中指定菜单资源的标识符;2,在CreateWindowEx函数参数中指定菜单句柄;3,先用LoadMenu函数载入菜单资源,再用SetMenu函数把菜单加载到应用程序的菜单栏。
菜单的操作包含:向已存在菜单添加新的菜单项,删除菜单中的某一项,使菜单项呈现被选中状态,使菜单项无效,创建浮动式菜单,向Windows系统菜单中添加,删除选项等等。
定位菜单项有两种途径:1,用菜单项的唯一标识符;2,用菜单项的逻辑索引。
菜单项的逻辑索引是这样规定的,菜单栏中的项从左到右的索引依次是0,1,2...,弹出菜单中的项从上到下的索引依次是0,1,2...。
如果想获得菜单某一项的句柄,因先获得菜单条的句柄,在用该菜单项的索引取得句柄。例如:
hMenu=GetMenu(hWnd); //hWnd是窗口句柄
hPopupMenu=GetSubMenu(hMenu,0); //0表示菜单的第一个选项
范例1:演示菜单的各种操作
// begin.cpp : Defines the entry point for the application.
//
#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
#include "resource.h"
#define ID_NEWITEM 1013 //定义新菜单项的标识符
#define ID_NEWSYSITEM 60441 //定义新系统菜单项标识符
LRESULT CALLBACK MainProc(HWND,UINT,WPARAM,LPARAM); //主窗口函数
BOOL WINAPI DoDispPopupMenu(HWND,int,int); //创建弹出式菜单
VOID WINAPI DoDispMessage(int); //显示相关信息
VOID WINAPI DoInsertMenuItem(void); //向已有菜单中插入新项
VOID WINAPI DoDeleteMenuItem(void); //删除菜单中的选项
VOID WINAPI DoCheckMenuItem(void); //设置菜单项为选中标志
VOID WINAPI DoCheckRadio(void); //设置菜单项为单选标志
VOID WINAPI DoInsertSysMenu(void); //向系统菜单中插入新项
char szAppName[]="Begin";
HINSTANCE hIns;
HWND hMainWnd;
BOOL isInsert; //插入菜单标志
BOOL isCheck; //选中标志
int idRadio=2; //单选标志
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
wc.cbClsExtra =0;
wc.cbSize =sizeof(WNDCLASSEX);
wc.cbWndExtra =0;
wc.hbrBackground =(HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor =LoadCursor(NULL,IDC_ARROW);
wc.hIcon =LoadIcon(NULL,IDI_APPLICATION);
wc.hIconSm =0;
wc.hInstance =hInstance;
wc.lpfnWndProc =(WNDPROC)MainProc;
wc.lpszClassName =szAppName;
wc.lpszMenuName =MAKEINTRESOURCE(IDR_MENU1);
wc.style =CS_HREDRAW | CS_VREDRAW |
CS_DBLCLKS | CS_OWNDC;
RegisterClassEx(&wc);
hWnd=CreateWindowEx(0,szAppName,szAppName,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
hMainWnd=hWnd;
hIns=hInstance;
//在此处向系统菜单中插入菜单项
DoInsertSysMenu();
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK MainProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch(message)
{
case WM_CREATE:
return 0;
case WM_PAINT:
hdc=BeginPaint(hWnd,&ps);
//do drawing
EndPaint(hWnd,&ps);
return 0;
case WM_RBUTTONDOWN:
//鼠标在窗口中右键被按下时,弹出浮动式菜单
if(DoDispPopupMenu(hWnd,LOWORD(lParam),HIWORD(lParam)))
return 0; //函数调用成功
else
break; //函数调用失败
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_INSERT:
if(isInsert==0)
{//插入新的菜单项
DoInsertMenuItem();
//显示相关信息
DoDispMessage(4);
}
break;
case ID_NEWITEM:
DoDispMessage(3);
break;
case ID_DELETE:
if(isInsert!=0)
{//删除菜单项
DoDeleteMenuItem();
DoDispMessage(5);
}
break;
case IDEXIT:
PostQuitMessage(0);
break;
case ID_CHECK: //在菜单选项前打钩
DoCheckMenuItem();
break;
case ID_RADIO1: //在菜单选项前做一圆形标志,表明此项被选中,
//并清除旧的标志
idRadio=2;
DoCheckRadio();
break;
case ID_RADIO2: //同上
idRadio=3;
DoCheckRadio();
break;
case ID_RADIO3: //同上
idRadio=4;
DoCheckRadio();
break;
case ID_FLOAT1: //浮动菜单的选项被选中时的处理
DoDispMessage(0);
break;
case ID_FLOAT2: //同上
DoDispMessage(1);
break;
case ID_FLOAT3: //同上
DoDispMessage(2);
break;
}
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,message,wParam,lParam);
}
BOOL WINAPI DoDispPopupMenu(HWND hWnd,int x,int y)
{
HMENU hMenu;
HMENU hPopupMenu;
POINT pt={x,y};
//从资源文件中载入菜单资源
hMenu=LoadMenu(hIns,MAKEINTRESOURCE(IDR_MENU2));
//获得子菜单的句柄
hPopupMenu=GetSubMenu(hMenu,0);
//窗口坐标转化到屏幕坐标
ClientToScreen(hMainWnd,&pt);
//创建浮动菜单
if(TrackPopupMenu(hPopupMenu,TPM_LEFTALIGN | TPM_RIGHTBUTTON,
pt.x,pt.y,0,hMainWnd,NULL)==FALSE)
return FALSE;
//使用完毕,回收内存
DestroyMenu(hMenu);
return TRUE;
}
VOID WINAPI DoDispMessage(int id)
{//在菜单事件发生时,输出相应的字符串
HDC hdc;
char *mess[]={"Command Floating Menuitem 1 ",
"Command Floating Menuitem 2 ",
"Command Floating Menuitem 3 ",
"Command New Menu Item ",
"New Item Have Been Inserted ",
"New Item Have Been Deleted "};
InvalidateRect(hMainWnd,NULL,FALSE);
hdc=GetDC(hMainWnd);
TextOut(hdc,0,0,mess[id],strlen(mess[id]));
ReleaseDC(hMainWnd,hdc);
}
VOID WINAPI DoInsertMenuItem()
{//插入菜单项
HMENU hMenu;
HMENU hPopupMenu;
MENUITEMINFO info;
//每一个新插入的菜单项都必须填写MENUITEMINFO结构
info.cbSize =sizeof(MENUITEMINFO);
info.fMask =MFT_STRING | MIIM_DATA | MIIM_ID | MIIM_TYPE;
info.fType =MFT_STRING;
info.fState =0;
info.wID =ID_NEWITEM;
info.hSubMenu =NULL;
info.hbmpChecked =NULL;
info.hbmpUnchecked =NULL;
info.dwItemData =ID_NEWITEM;
info.dwTypeData ="New Item";
info.cch =8;
//获得已存在菜单的句柄
hMenu=GetMenu(hMainWnd);
//获得子菜单的句柄
hPopupMenu=GetSubMenu(hMenu,0);
//插入菜单项
InsertMenuItem(hPopupMenu,1,TRUE,&info);
//置插入标志为1
isInsert=1;
}
VOID WINAPI DoDeleteMenuItem()
{//删除菜单项
HMENU hMenu;
HMENU hPopupMenu;
hMenu=GetMenu(hMainWnd);
hPopupMenu=GetSubMenu(hMenu,0);
RemoveMenu(hPopupMenu,ID_NEWITEM,MF_BYCOMMAND);
isInsert=0;
}
VOID WINAPI DoCheckMenuItem()
{//此函数先判断菜单项是否被打钩,若没有,则做打钩标记
//若已有,则删除打钩标记
HMENU hMenu;
HMENU hPopupMenu;
hMenu=GetMenu(hMainWnd);
hPopupMenu=GetSubMenu(hMenu,1);
if(isCheck)
{
CheckMenuItem(hPopupMenu,0,MF_BYPOSITION | MF_UNCHECKED);
isCheck=0;
}
else
{
CheckMenuItem(hPopupMenu,0,MF_BYPOSITION | MF_CHECKED);
isCheck=1;
}
}
VOID WINAPI DoCheckRadio()
{
HMENU hMenu;
HMENU hPopupMenu;
hMenu=GetMenu(hMainWnd);
hPopupMenu=GetSubMenu(hMenu,1);
CheckMenuRadioItem(hPopupMenu,2,4,idRadio,MF_BYPOSITION);
}
VOID WINAPI DoInsertSysMenu()
{//在系统菜单中插入菜单项
HMENU hSysMenu;
MENUITEMINFO info;
//获得系统菜单的句柄
hSysMenu=GetSystemMenu(hMainWnd,FALSE);
info.cbSize =sizeof(MENUITEMINFO);
info.fMask =MFT_STRING | MIIM_DATA | MIIM_ID | MIIM_TYPE;
info.fType =MFT_STRING;
info.fState =MFS_DEFAULT;
info.wID =ID_NEWSYSITEM;
info.hSubMenu =NULL;
info.hbmpChecked =NULL;
info.hbmpUnchecked =NULL;
info.dwItemData =15;
info.dwTypeData ="New system Item";
info.cch =15;
InsertMenuItem(hSysMenu,6,TRUE,&info);
}
资源文件中有以下定义
IDR_MENU1 MENU DISCARDABLE
BEGIN
POPUP "Menu&1"
BEGIN
MENUITEM "InsertItem\t[I]", ID_INSERT
MENUITEM "DeleteItem\t[D]", ID_DELETE
MENUITEM "&Exit\tAlt+F4", IDEXIT
END
POPUP "Menu&2"
BEGIN
MENUITEM "CheckText", ID_CHECK
MENUITEM SEPARATOR
MENUITEM "Radio1", ID_RADIO1
MENUITEM "Radio2", ID_RADIO2
MENUITEM "Radio3", ID_RADIO3
MENUITEM SEPARATOR
MENUITEM "About", ID_ABOUT
END
END
IDR_MENU2 MENU DISCARDABLE
BEGIN
POPUP "Test"
BEGIN
MENUITEM "Floating Menu Item1", ID_FLOAT1, MENUBREAK
MENUITEM "Floating Menu Item2", ID_FLOAT2
MENUITEM "Floating Menu Item3", ID_FLOAT3
END
END
有任何意见,建议请 email:y_h_zhang@sohu.com.