菜单是最为重要的用户界面
菜单从编程的角度来进行分类:静态菜单,动态菜单,快捷菜单。
静态菜单:在菜单资源编译器预先进行编辑好的
动态菜单:在程序运行过程中通过代码生成
快捷菜单:快捷菜单是静态菜单和动态菜单的集合,在编译器中预先编辑好,然后在程序运行过程中动态显示。(在Win32编程中使用较多)
而在我们设计菜单时可以将菜单理解为一个二维数组,每一个二维数组的元素可以理解为一个可以嵌套的子菜单,菜单里面的每一个菜单项都有两个基本要素:菜单项名字,该菜单项唯一的标识id。
静态菜单
第一种静态菜单加载方式:
在窗口注册进行添加
当加载静态菜单时先在菜单编辑栏中的对菜单进行编辑,同时在窗口注册前将窗口名字(lpszMenuName)修改成你所编辑的id,如程序默认给我的是wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MY);这里我想要加载一个新编辑的ID为IDR_MENU1资源则修改成wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
第二种静态菜单加载方式:
在窗口创建进行添加
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
HMENU hmenu1 = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT,0 , NULL, hmenu1, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
动态菜单(这里贴一下代码)
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
//动态菜单加载
HMENU hMenu = NULL;//创建一个空菜单
hMenu = CreateMenu();//创建一个空菜单
HMENU hMenu_1 = CreateMenu();
AppendMenu(hMenu_1, MF_CHECKED, 5001, _T("新建(&N)"));//MF_CHECKED指的是对话框的标签显示对勾
AppendMenu(hMenu_1, 0, 5002, _T("打开(&O)"));// 按住alt + O键可打开快捷键
AppendMenu(hMenu_1, 0, 5003, _T("添加到源代码管理"));
//把hMenu菜单理解为一个二维数组,hMenu_1理解为其中一个一维数组
//把hMenu_1当成一个菜单项嵌套进hMenu里面
//注意:在弹出式菜单里面不需要id号,把一个菜单句柄当id来使用,那么这个弹出之后就是该菜单句柄指的菜单
AppendMenu(hMenu, MF_POPUP, (UINT)hMenu_1, _T("文件(&F)"));// MF_POPUP
HMENU hMenu_2 = CreateMenu();
AppendMenu(hMenu_2, MF_BYPOSITION | MF_CHECKED, 6004, _T("剪切"));
AppendMenu(hMenu_2, MF_BYPOSITION, 6001, _T("撤销"));
AppendMenu(hMenu_2, MF_BYCOMMAND, 6002, _T("复制"));
InsertMenu(hMenu_2, 6003, MF_BYCOMMAND | MF_SEPARATOR, 6004, _T("-"));
//MF_POPUP 下拉式菜单 MF_BYCOMMAND 基于id MF_BYPOSITION基于下标
//第二个参数受到第三个参数的影响
//DeleteMenu(hMenu_2,6001,MF_BYCOMMAND);
//一般情况下不会去删除,让菜单变灰即可
EnableMenuItem(hMenu_2, 6001, MF_BYCOMMAND | MF_GRAYED);//菜单变灰,非激活状态
EnableMenuItem(hMenu_2, 6001, MF_BYCOMMAND | MF_ENABLED);//激活状态
//SetMenu(hWnd, hMenu);//在hwnd这个窗口里面重新更新一个菜单
AppendMenu(hMenu, MF_POPUP, (UINT)hMenu_2, _T("编辑(&E)"));
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, hMenu, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
快捷菜单的创建(动态的加载已经在菜单编辑栏中创建好的静态菜单)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
//快捷菜单
case WM_CREATE:
g_hRMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU2));
break;
case WM_RBUTTONDOWN:
{
POINT pt;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
//把客户区坐标转换为屏幕坐标
ClientToScreen(hWnd, &pt);
HMENU h1 = GetSubMenu(g_hRMenu, 0);//得到子菜单句柄
//弹出右键菜单
TrackPopupMenu(h1,//哪一个菜单
TPM_LEFTALIGN | TPM_TOPALIGN,//菜单风格,对齐方式
pt.x, pt.y,//鼠标点击的位置
0,
hWnd,
nullptr);
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
初次接触Win32编程,文章当中如有不当之处,还请看到的人多多指教。