Windows c++界面开发初学(三)win32

参考博客:
win32(5)–Windows菜单
win32学习10.菜单
跟我一起玩Win32开发(5):具有单选标记的菜单

菜单添加

菜单添加有两种方式,一种是利用代码创建菜单资源,一种是利用资源文件获取资源。

1、代码创建

利用CreateMenu()、CreatePopupMenu()、GetSystemMenu()函数创建顶层菜单、弹出式菜单,获取系统菜单;
利用AppendMenu()、InsertMenuItem()、InsertMenu()函数插入菜单项。

  • 各函数代码原型及说明如下:(建议直接戳链接看文档,还有示例代码)

    • 1、HMENU CreateMenu();

      Parameters
      This function has no parameters.

      Return Value
      Type: HMENU
      If the function succeeds, the return value is a handle to the newly created menu.
      If the function fails, the return value is NULL. To get extended error information, call GetLastError.

      Remarks
      Resources associated with a menu that is assigned to a window are freed automatically. If the menu is not assigned to a window, an application must free system resources associated with the menu before closing.
      An application frees menu resources by calling the DestroyMenu function.

    • 2、HMENU CreatePopupMenu();

      Parameters
      This function has no parameters.
      Return Value
      Type: HMENU
      If the function succeeds, the return value is a handle to the newly created menu.
      If the function fails, the return value is NULL. To get extended error information, call GetLastError.
      Remarks
      The application can add the new menu to an existing menu, or it can display a shortcut menu by calling the TrackPopupMenuEx or TrackPopupMenu functions.
      Also remember to free the resources if not assgined to a window.

    • 3、HMENU GetSystemMenu(
      HWND hWnd,
      BOOL bRevert
      );

      Parameters
      hWnd
      Type: HWND
      A handle to the window that will own a copy of the window menu.
      bRevert
      Type: BOOL
      The action to be taken. If this parameter is FALSE, GetSystemMenu returns a handle to the copy of the window menu currently in use. The copy is initially identical to the window menu, but it can be modified. If this parameter is TRUE, GetSystemMenu resets the window menu back to the default state. The previous window menu, if any, is destroyed.

      Return Value
      Type: HMENU
      If the bRevert parameter is FALSE, the return value is a handle to a copy of the window menu. If the bRevert parameter is TRUE, the return value is NULL.

      Remarks
      Any window that does not use the GetSystemMenu function to make its own copy of the window menu receives the standard window menu.
      The window menu initially contains items with various identifier values, such as SC_CLOSE, SC_MOVE, and SC_SIZE.
      Menu items on the window menu send WM_SYSCOMMAND messages.
      All predefined window menu items have identifier numbers greater than 0xF000. If an application adds commands to the window menu, it should use identifier numbers less than 0xF000.
      The system automatically grays items on the standard window menu, depending on the situation. The application can perform its own checking or graying by responding to the WM_INITMENU message that is sent before any menu is displayed.

    • 4、BOOL AppendMenu(
      HMENU hMenu,
      UINT uFlags,
      UINT_PTR uIDNewItem,
      LPCWSTR lpNewItem
      );

      Parameters
      hMenu
      Type: HMENU
      A handle to the menu bar, drop-down menu, submenu, or shortcut menu to be changed.
      uFlags
      Type: UINT
      Controls the appearance and behavior of the new menu item.
      uIDNewItem
      Type: UINT_PTR
      The identifier of the new menu item or, if the uFlags parameter is set to MF_POPUP, a handle to the drop-down menu or submenu.
      lpNewItem
      Type: LPCTSTR
      The content of the new menu item.

      Return Value
      Type: BOOL
      If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError.

      Remarks
      The following groups of flags cannot be used together:
      MF_BITMAP, MF_STRING, and MF_OWNERDRAW
      MF_CHECKED and MF_UNCHECKED
      MF_DISABLED, MF_ENABLED, and MF_GRAYED
      MF_MENUBARBREAK and MF_MENUBREAK

    • 5、BOOL InsertMenuItem(
      HMENU hmenu,
      UINT item,
      BOOL fByPosition,
      LPCMENUITEMINFO lpmi
      );

      Parameters
      hmenu
      TBD(To Be Determined ,什么鬼…)
      item
      TBD
      fByPosition
      Type: BOOL
      Controls the meaning of uItem. If this parameter is FALSE, uItem is a menu item identifier. Otherwise, it is a menu item position.
      lpmi
      TBD

      Return Value
      Type: BOOL
      If the function succeeds, the return value is nonzero.
      If the function fails, the return value is zero. To get extended error information, use the GetLastError function.

      Remarks
      The application must call the DrawMenuBar function whenever a menu changes, whether the menu is in a displayed window.
      In order for keyboard accelerators to work with bitmap or owner-drawn menu items, the owner of the menu must process the WM_MENUCHAR message. See Owner-Drawn Menus and the WM_MENUCHAR Message for more information.

    • 6、BOOL InsertMenu(
      HMENU hMenu,
      UINT uPosition,
      UINT uFlags,
      UINT_PTR uIDNewItem,
      LPCSTR lpNewItem
      );

      Parameters
      hMenu
      Type: HMENU
      A handle to the menu to be changed.
      uPosition
      Type: UINT
      The menu item before which the new menu item is to be inserted, as determined by the uFlags parameter.
      uFlags
      Type: UINT
      Controls the interpretation of the uPosition parameter and the content, appearance, and behavior of the new menu item.
      uIDNewItem
      Type: UINT_PTR
      The identifier of the new menu item or, if the uFlags parameter has the MF_POPUP flag set, a handle to the drop-down menu or submenu.
      lpNewItem
      Type: LPCTSTR
      The content of the new menu item. The interpretation of lpNewItem depends on whether the uFlags parameter includes the MF_BITMAP, MF_OWNERDRAW, or MF_STRING flag

      Return Value
      Type: BOOL
      If the function succeeds, the return value is nonzero.
      If the function fails, the return value is zero. To get extended error information, call GetLastError.

      Remarks
      The application must call the DrawMenuBar function whenever a menu changes, whether the menu is in a displayed window.
      The following groups of flags cannot be used together:
      MF_BYCOMMAND and MF_BYPOSITION
      MF_DISABLED, MF_ENABLED, and MF_GRAYED
      MF_BITMAP, MF_STRING, MF_OWNERDRAW, and MF_SEPARATOR
      MF_MENUBARBREAK and MF_MENUBREAK
      MF_CHECKED and MF_UNCHECKED

    • 7、DestroyMenu function

  • 一段创建弹出式菜单的例子:

/*资源id*/
#define IDM_OPT1     301
#define IDM_OPT2     302

HMENU hRoot;//顶层菜单句柄

void createMyMenu() {
    hRoot = CreateMenu();//创建顶层菜单

    if (!hRoot) {
        printf("%s", "request for menu resource fail!");
        return;
    }

    HMENU pop1 = CreatePopupMenu();//创建弹出式菜单
    AppendMenu(hRoot, MF_POPUP, (UINT_PTR)pop1, L"操作");//往顶层菜单插入弹出式菜单
    AppendMenu(pop1, MF_STRING, IDM_OPT1, L"操作1");//往弹出式菜单插入菜单项

    MENUITEMINFO menuInfo;
    menuInfo.cbSize = sizeof(MENUITEMINFO);
    menuInfo.cch = 100;
    menuInfo.dwItemData = NULL;
    menuInfo.dwTypeData = L"操作2";
    menuInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_STATE;
    menuInfo.fState = MFS_ENABLED;
    menuInfo.fType = MIIM_STRING;
    menuInfo.wID = IDM_OPT2;

    InsertMenuItem(pop1, IDM_OPT2, FALSE, &menuInfo);//往弹出式菜单插入菜单项
    InsertMenu(pop1, ID_OPTION3, MF_BYCOMMAND | MF_STRING, ID_OPTION3, L"操作3");//往弹出式菜单插入菜单项
}

int CALLBACK WinMain(
    _In_ HINSTANCE hInstance,
    _In_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine,
    _In_ int nCmdShow
) {
    ...
    createMyMenu();
    ...
    HWND hWnd = CreateWindow(
        szWindowClass,
        szTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        500, 300,
        NULL,
        hRoot, //菜单资源
        hInstance,
        NULL
    );
    ...
}

运行效果如下:
这里写图片描述

2、利用资源文件添加菜单

在vs2015中,点击菜单栏中的视图 – 其他窗口 – 资源视图,打开资源视图窗口,
这里写图片描述
然后右键点击你的项目,点击添加–资源,选中Menu,点击新建
这里写图片描述
在弹出的可视化菜单窗口中创建你想要的菜单:
这里写图片描述
双击(或右键)菜单项设置其属性,可以在ID栏中更改其资源id为你想要的id名
这里写图片描述
保存,还可以在解决方案资源管理器中的头文件看到”resource.h”一项,资源文件中出现后缀名为.rc的文件。
右键该rc文件,点击查看代码,可以看到创建的菜单结构如下:
这里写图片描述

这样就建好了菜单资源,而将菜单添加到窗口有两种方法
第一种方法是设计窗口类时, 直接指定给WNDCLASS结构的lpszMenuName成员,这样做意味着,在调用CreateWindow函数创建窗口时,无论你是否为窗口指定菜单,最终显示的窗口上都会有菜单,因为它是基于整个窗口类的。

wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);

第二种是不设置为类级别的菜单,而是在调用CreateWindow时指定给hMenu参数

HWND hWnd = CreateWindow(
        szWindowClass,
        szTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        500, 300,
        NULL,
        LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1)),
        hInstance,
        NULL
    );

这样就设置好我们的菜单了。

3、消息响应

添加好菜单后我们还想根据选择菜单的不同项做出不同的响应。如何获取菜单,如何知道选择的菜单项,再做出响应呢?
在WindowProc函数中,我们针对不同的消息做出不同的响应,其实点击菜单时也会有消息,因此我们的消息响应将在WindowProc中处理。
首先我们需要获取菜单:

HMENU hmenu = GetMenu(hwnd); // 获取菜单
HMENU hSubMenu = GetSubMenu(hmenu, 0); //获取菜单的第0个子菜单

菜单项发送的是WM_COMMAND消息,因此在消息处理中加入对WM_COMMAND消息的处理:

switch (uMsg)
    {
    case WM_COMMAND:
        ...
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
        break;
    }

在WM_COMMAND类型的消息中,wParam的低位记录了菜单项的id,因此利用这个信息就可以知道是选择了哪个菜单项:

case WM_COMMAND:    
        switch (LOWORD(wParam)) {
        case ID_OPTION1:
            MessageBox(hwnd, L"操作1", L"提示", MB_OK);
            break;
        case ID_OPTION2:
            MessageBox(hwnd, L"操作2", L"提示", MB_OK);
            break;
        case ID_OPTION3:
            MessageBox(hwnd, L"操作3", L"提示", MB_OK);
            break;
        default:
            break;
        }
        break;

还可以给选择了的菜单项添加已选择的提示:

//圆点项
//四个参数分别表示菜单句柄,菜单项的选择范围的起始、终止,要判断的菜单项,以及参数的类型是id还是pos
CheckMenuRadioItem(hSubMenu, ID_OPTION1, ID_OPTION3, ID_OPTION1, MF_BYCOMMAND);

//勾选项
//三个参数分别表示菜单句柄,要判断的菜单项,以及选中的表示方法
CheckMenuItem(hSubMenu, ID_OPTION1, MF_CHECKED);

猜你喜欢

转载自blog.csdn.net/unirrrrr/article/details/81201261
今日推荐