Win32开发(2):02_Win32添加菜单

用代码添加

这种方法的思路是:首先在全局范围内定义一个HMENU的变量,用来保存窗口中菜单栏的句柄,根菜单(菜单栏)可以CreateMenu函数来创建,接着可以使用AppendMenu函数或者InsertMenuItem函数来创建菜单项。

HMENU hRoot;//定义菜单的全局变量
void CreateMyMenu();//声明创建菜单的函数
//函数的实现
//创建菜单
void CreateMyMenu()
{
	hRoot = CreateMenu();//根菜单用此函数创建菜单
	if(!hRoot)
		return;

	HMENU pop1 = CreatePopupMenu();//竖立的弹出菜单,通常作为另一个菜单的子菜单或右键菜单的顶级菜单
	AppendMenu(hRoot,MF_POPUP,(UINT_PTR)pop1,TEXT("操作"));//将子菜单添加到根菜单中
	// 一种方法是使用AppendMenu函数
	HMENU pop1_1 = CreatePopupMenu();
	AppendMenu(pop1,MF_STRING,(UINT_PTR)pop1_1,TEXT("飞机"));
 
	// 另一种方法是使用InsertMenuItem函数
	HMENU pop1_2 = CreatePopupMenu();
	MENUITEMINFO mif;
	mif.cbSize = sizeof(MENUITEMINFO);
	mif.cch = 100;
	mif.dwItemData  = NULL;
	mif.dwTypeData = TEXT("机关枪");
	mif.fMask = MIIM_ID | MIIM_STRING | MIIM_STATE;
	mif.fState = MFS_ENABLED;
	mif.fType = MIIM_STRING;
	mif.wID = (UINT_PTR)pop1_2;
 
	InsertMenuItem(pop1,(UINT_PTR)pop1_2,FALSE,&mif);
 
}

在主函数中,创建窗口前先调用函数,然后在创建窗口时改变倒数第三个参数为菜单全局变量

//创建菜单
	CreateMyMenu();

	//3、 创建窗口
	HWND WINAPI hwnd = CreateWindow(wc.lpszClassName,TEXT("WINDOWS"),WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,hRoot,hINstance,NULL);

通过资源添加

在资源中编辑菜单,主要是显示的内容和ID,命名为IDM_XXX
在主函数中修改两个地方

//级别类在设计窗口时添加,不需要在CreateWindow时指定参数也能显示菜单
wc.lpszMenuName = (CHAR *)IDR_MENU1;//菜单名称
//3、 创建窗口
//窗口类,在再创建窗口时指定菜单,此时必须指定参数
	HWND WINAPI hwnd = CreateWindow(wc.lpszClassName,TEXT("WINDOWS"),WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,LoadMenu(hINstance,MAKEINTRESOURCE(IDR_MENU1 )),hINstance,NULL);

菜单响应

当用户单击某个菜单项后,窗口处理程序(WindowProc)会收到一条WM_COMMAND消息,它的两个附加参数:wParam(选中的菜单项)IParam(窗口句柄)
在WindowProc中

    case WM_COMMAND:
		{
			switch(LOWORD(wparam))
			{
			case IDM_OPEN:
				{
					MessageBox(hwnd,TEXT("按下打开菜单"),TEXT("菜单"),MB_OK);
					break;
				}
			case IDM_CLOSE:
				{
					MessageBox(hwnd,TEXT("按下关闭菜单"),TEXT("菜单"),MB_OK);
					break;
				}
			case IDM_FIND:
				{
					MessageBox(hwnd,TEXT("按下查找菜单"),TEXT("菜单"),MB_OK);
					break;
				}
			case IDM_REPALCE:
				{
					MessageBox(hwnd,TEXT("按下替换菜单"),TEXT("菜单"),MB_OK);
					break;
				}
			}
			break;
		}

单选菜单

1.菜单ID必须连续
2.在窗口过程函数中定义变量用来获取有单选范围的子菜单

auto hmm = GetMenu(hwnd);//菜单
auto hfmn = GetSubMenu(hmm,2);//水果子菜单

在选中菜单的case中写CheckMenuRadioItem函来来Check菜单

            case IDM_APPLE:
				{
					//菜单句柄,单选范围,选中项,最后一项固定用ID来标识
					CheckMenuRadioItem(hfmn,IDM_APPLE,IDM_BANANA,IDM_APPLE,MF_BYCOMMAND);
					MessageBox(hwnd,TEXT("你选择了苹果"),TEXT("提示"),MB_OK);
					break;
				}
			case IDM_PEAR:
				{
					//菜单句柄,单选范围,选中项,最后一项固定用ID来标识
					CheckMenuRadioItem(hfmn,IDM_APPLE,IDM_BANANA,IDM_PEAR,MF_BYCOMMAND);
					MessageBox(hwnd,TEXT("你选择了梨"),TEXT("提示"),MB_OK);
					break;
				}
			case IDM_BANANA:
				{
					//菜单句柄,单选范围,选中项,最后一项固定用ID来标识
					CheckMenuRadioItem(hfmn,IDM_APPLE,IDM_BANANA,IDM_BANANA,MF_BYCOMMAND);
					MessageBox(hwnd,TEXT("你选择了香蕉"),TEXT("提示"),MB_OK);
					break;
				}

创建右键菜单

  1. 用资源编辑器创建菜单
  2. 当我们在窗口上按下鼠标右键,WM_CONTEXTMENU消息,我们通过响应这条消息来决定是否弹出菜单。
case WM_CONTEXTMENU://右键
		{
			RECT rect;//矩形区
			GetClientRect(hwnd,&rect);
			//获取鼠标右键的坐标
			POINT pt;//点
			pt.x = LOWORD(lparam);
		    pt.y = HIWORD(lparam);

			//把屏幕坐标转换为客户区坐标
			ScreenToClient(hwnd, &pt);

			if(PtInRect(&rect, pt))//点是否在矩形区
			{
				//加载菜单
				auto rightmenu = LoadMenu((HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), MAKEINTRESOURCE(IDR_MENU2));
				if(rightmenu)
				{
					//获取弹出菜单
					auto shirenmenu = GetSubMenu(rightmenu,0);
					//把客户区坐标转换为屏幕坐标
					ClientToScreen(hwnd, &pt);
					//显示快捷菜单
					TrackPopupMenu(shirenmenu,
						TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
						pt.x,
						pt.y,
						0,
						hwnd,
						NULL);
					// 用完后要销毁菜单资源
					DestroyMenu(shirenmenu);
				}
			}

		
			break;
		}
  1. 计算菜单弹出的位置,一般在我们鼠标指针的右下方,该坐标是基于屏幕的,不是窗口的。
  2. 调用TrackPopupMenu函数显示快捷菜单。
  3. 因为这种菜单是不属于某个窗口的,它的内存资源不会在窗口销毁时被回收,因此,在TrackPopupMenu返回后要调用DestroyMenu来销毁菜单的资源,释放内存。
  4. 在WM_COMMAND中响应菜单项
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值