win32学习10.菜单

菜单的分类

窗口顶层菜单,弹出式菜单,系统菜单。句柄类型为HMENU,根据这三类还会细分,但是代码里是一样的。

窗口顶层菜单

HMENU hMain = CreateMenu();//创建菜单,成功则返回句柄

HMENU hFile = CreatePopupMenu();//弹出式菜单
AppendMenu(hFile,MF_STRING|MF_CHECKED,1003,"新建");//勾选
AppendMenu(hFile,MF_SEPARATOR,0,""); //分割线
AppendMenu(hFile,MF_STRING|MF_MENUBARBREAK,1004,"退出"); //换列

HMENU hHelp = CreatePopupMenu();
AppendMenu(hHelp,MF_STRING|MF_GRAYED,1005,"关于");//变灰

AppendMenu(hMain,MF_POPUP,(UINT)hFile,"文件");
AppendMenu(hMain,MF_POPUP,(UINT)hHelp,"帮助");
SetMenu(hwnd,hMain);//将菜单添加到窗口中

/**********************
BOOL AppendMenu(
    HMENU hMenu,         // handle to menu,菜单句柄
    UINT uFlags,         // menu-item options,菜单项风格
    UINT_PTR uIDNewItem, // identifier, menu, or submenu,菜单ID 
    LPCTSTR lpNewItem    // menu-item content,菜单项名称
);
菜单项常用风格:
弹出下拉菜单,MF_POPUP,就是点一下弹出一列菜单。
点击执行,MF_STRING,点击后执行具体操作。
分隔线,MF_SEPARATOR,注意算索引的时候它算一个。
勾选,MF_CHECKED,MF_UNCHECKED。
不可用,MF_DISABLED,MF_GRAYED,后一个还会表示为灰色,等于前面的加强版。
换列,MF_MENUBARBREAK,显示到另一列,和开始菜单一样。感觉和下拉菜单差不多,只是方向变了。
***********************/

添加消息:

case WM_COMMAND:
        OnCommand(hwnd,wParam);
        break;
//WM_COMMAND是个很复杂的消息,对于菜单来说,只需要处理wParam的低八位字节,即菜单项ID。

添加消息处理:

//CheckMenuItem更改勾选状态,EnableMenuItem更改是否可用。
BOOL bState = TRUE;
void OnCommand(HWND hwnd,WPARAM wParam)
{
    switch(LOWORD(wParam))
    {
    case 1003:
        {
            if (bState)
            {
                CheckMenuItem(hFile,1003,MF_BYCOMMAND|MF_CHECKED);//MF_BYCOMMAND要跟ID
            } 
            else
            {
                CheckMenuItem(hFile,0,MF_BYPOSITION|MF_UNCHECKED);//MF_BYPOSITION不用跟ID
            }
            bState = !bState;
        }
        break;
    case 1004:
        PostMessage(hwnd,WM_QUIT,0,0);
        break;
    case 1005:
        MessageBox(NULL,"关于","Test",MB_OK);
        break;
    }
}
//MF_BYCOMMAND和MF_BYPOSITION在菜单里面很常见,一个是指定ID,一个是指定位置。自己定义的时候可能用ID多点,如果是系统菜单,不知道ID,则更多使用位置索引,从0开始。

窗口顶层菜单的初始化:

/**********************
WM_INITMENUPOPUP,菜单初始化,被激活但未显示的菜单。
LRESULT CALLBACK WindowProc(
    HWND hwnd,       // handle to window
    UINT uMsg,       // WM_INITMENUPOPUP
    WPARAM wParam,   // handle to menu (HMENU),被激活菜单的句柄。
    LPARAM lParam    // item position and indicator,低八位:被激活菜单项的顶层菜单索引。高八位:窗口菜单标识。
);
窗口菜单:系统菜单和顶层菜单。弹出式菜单不属于。
***********************/

系统菜单

HMENU hSys = GetSystemMenu(hwnd,FALSE); //获取某窗口的系统菜单。
//第二个参数表示重置选项,TRUR表示删除旧菜单,恢复到默认的系统菜单;False表示返回当前的系统菜单句柄。
for (int i=0;i<8;i++)//有多少个删多少次
{
    DeleteMenu(hSys,0,MF_BYPOSITION);//根据索引删除,参数也是MF_BYCOMMAND和MF_BYPOSITION.
}

通过AppendMenu添加菜单,通过WM_SYSCOMMAND响应,和窗口顶层菜单一样,wParam的低八位字节即菜单项ID。

弹出式菜单

用的比较多的比如右键菜单。通常鼠标右键弹起触发。
如果是鼠标右键弹起触发:WM_RBUTTONUP:

//鼠标传过来的光标位置是窗口坐标系的坐标。
/*************
BOOL ClientToScreen( //窗口坐标转换为屏幕坐标
  HWND hWnd,       // handle to window
  LPPOINT lpPoint  // screen coordinates,窗口点,输入和输出都是这个参数
  );
typedef struct tagPOINT { 
  LONG x; 
  LONG y; 
} POINT, *PPOINT; 
//对应的还有个ScreenToClient
***************/
HMENU hPopup = CreatePopupMenu();//创建
AppendMenu(hPopup,MF_STRING,1003,"新建");
AppendMenu(hPopup,MF_SEPARATOR,0,""); 
AppendMenu(hPopup,MF_STRING,1004,"退出"); 

POINT pt = {0};
pt.x = LOWORD(lParam);
pt.x = HIWORD(lParam);
ClientToScreen(hwnd,&pt);

TrackPopupMenu(hPopup,TPM_CENTERALIGN|TPM_VCENTERALIGN,pt.x,pt.x,0,hwnd,NULL);//显示

//阻塞函数,点击任何可用项返回
/********************
BOOL TrackPopupMenu(
    HMENU hMenu,         // handle to shortcut menu,菜单句柄
    UINT uFlags,         // options,显示方式
    int x,               // horizontal position,x坐标,屏幕坐标系
    int y,               // vertical position,y坐标
    int nReserved,       // reserved, must be zero,保留,必须为0
    HWND hWnd,           // handle to owner window,处理菜单消息的窗口句柄
    CONST RECT *prcRect  // ignored,忽略
);
显示方式:
TPM_CENTERALIGN 鼠标光标处于右键菜单居中 
TPM_LEFTALIGN 左边,最常用
TPM_RIGHTALIGN 右边
TPM_BOTTOMALIGN 底部
TPM_TOPALIGN 顶部
TPM_VCENTERALIGN 垂直方向居中

TPM_NONOTIFY 
TPM_RETURNCMD  返回的是用户选择的菜单项的ID,用于消息处理

TPM_LEFTBUTTON 用鼠标左键选择菜单项
TPM_RIGHTBUTTON 用左键右键都可以
***********************/

消息处理和前面的菜单处理一样,都是通过ID判断,但是如果加入了TPM_RETURNCMD显示方式,则直接返回ID,在创建的函数里面即可做处理。等于消息直接自己送了,不进消息队列了。

除了鼠标右键弹起,对于右键菜单还有个专门的消息:WM_CONTEXTMENU,WPARAM返回右键点击的窗口句柄,LPARAM返回屏幕坐标,不需要做转换。
WM_CONTEXTMENU在WM_RBUTTONUP之后产生。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐的提千万

江山父老能容我,不使人间造孽钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值