• 11.菜单(一)


    1.菜单的分类

      菜单其实是一个容器,容器中放的每个菜单项。

      HMENU类型表示菜单,菜单每一项有相应的ID。

      (1)窗口顶层菜单

         窗口标题栏和客户区之间的区域。

      (2)弹出式菜单

         例如:右键菜单、下拉菜单等

      (3)系统菜单

    2.菜单的使用

      (1)窗口顶层菜单

          创建菜单:HMENU CreateMenu(VOID);  //成功返回菜单句柄

          添加菜单项:BOOL AppendMenu( HMENU       hMenu,          //菜单句柄

                                                                UINT          uFlag,            //菜单顶风格

                                                                UINT_PTR   uIDNewItem,  //菜单ID或下拉菜单句柄

                                                                LPCTSTR     lpNewItem);   //菜单项名称

          菜单风格:MF_POPUP - 具有这种风格的菜单项,被点击后弹出下拉菜单或子菜单,uIDNewItem必须设置下拉菜单或子菜单句柄。

                 MF_SEPARATOR - 具有这种风格的菜单项,为分割线。

                 MF_STRING  - 具有这个风格的菜单项,被点击后能发出消息(WM_COMMAND)。

          设置到窗口:BOOL SetMenu( HWND   hWnd,    //窗口句柄

                                                          HMENU  hMenu);  //菜单句柄

      (2)弹出式菜单

          创建菜单:HMENU CreatePopupMenu(VOID);  //成功返回菜单句柄

          加入顶层菜单:BOOL AppendMenu( HMENU      hMenu,           //菜单句柄

                                                                   UINT         uFlag,             //菜单顶风格

                                                                   UINT_PTR  uIDNewItem,   //菜单ID或下拉菜单句柄

                                                                   LPCTSTR    lpNewItem);   //菜单项名称

      (3)菜单命令处理

           WM_COMMAND消息

         wPARAM:HIWORD - 对于菜单为0

                                  LOWORD - 菜单项ID

         lPARAM:对于菜单为NULL

         命令处理过程:获取(WPARAM的LOWORD)菜单ID,根据ID处理

      (4)菜单项的状态

          在增加菜单项可以设置菜单项的状态,可以使用菜单API(CheckMenuItem、EnableMenuItem)修改状态。

         //设置菜单项勾选/非勾选状态

         DWOED CheckMenuItem( HMENU  hMenu,            //菜单句柄

                                                       UINT     uIDCheckItem,  //菜单项ID或位置(索引)

                                                       UINT     uCheck);          //具体状态

         uCheck:MF_BYCOMMAND - uIDCheckItem参数必须填写菜单项ID

                      MF_POSITION - uIDCheckItem参数必须填写菜单项位置

                      MF_CHECKED - 菜单项勾选

                      MF_UNCHECKED - 菜单项非勾选                  

         //设置菜单项可用/不可用/灰色状态

         BOOL EnableMenuItem( HMENU  hMenu,              //菜单句柄

                                                    UINT      uIDEnableItem,  //菜单项ID或位置(索引)

                                                    UINT      uEnable);          //具体状态

         uEnable:MF_BYCOMMAND - uIDEnableItem参数必须填写菜单项ID

                       MF_POSITION - uIDEnableItem参数必须填写菜单项位置

                                MF_DISABLE - 不可用

                                MF_ENABLE - 可用

                                MF_GRAYED - 灰色状态

         函数使用时,需要通过设置MF_BYPOSITION或者MF_BYCOMMAND,确定使用菜单索引号或者菜单ID。

      (5)WM_INITMENUPOPUP

         在菜单被激活但为显示时,窗口会收到这个消息 

         wPARAM:即将显示的菜单句柄

         lPARAM:LOWORD - 被点击顶层菜单索引(位置)       

                                HIWORD - 即将显示菜单是否为窗口菜单

         窗口菜单:顶层菜单/系统菜单属于窗口菜单,弹出式菜单不属于窗口菜单。

      相关示例代码: 

    #include "stdafx.h"
    #include "stdio.h"
    
    HINSTANCE g_hInstance = 0;  //接收当前程序实例句柄
    HMENU hFile = 0;
    HANDLE g_hOutput = 0;
    
    void OnCreate(HWND hWnd)
    {
        //创建(顶层)菜单
        HMENU hMain = CreateMenu();
    
        //创建下拉菜单
        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, "关于");
    
        //添加菜单项
        //MF_POPUP风格的菜单被点击后才会弹出菜单,而且第三个参数必须为下拉菜单的句柄
        AppendMenu(hMain, MF_POPUP, (UINT)hFile, "文件");
        AppendMenu(hMain, MF_POPUP, (UINT)hHelp, "帮助");
        //将菜单设置到窗口
        SetMenu(hWnd, hMain);
    }
    int g_state = 0;//标志量(标识新建菜单项当前状态)
    void OnCommand(HWND hWnd, WPARAM wParam)
    {
        switch (LOWORD(wParam))
        {
        case 1003:
            if (0 == g_state)
            {
                CheckMenuItem(hFile, 1003, MF_BYCOMMAND | MF_UNCHECKED);
            }
            else
            {
                CheckMenuItem(hFile, 0, MF_BYPOSITION | MF_CHECKED);
            }
            g_state = !g_state;
            break;
        case 1004:
            MessageBox(hWnd, "退出被点击", "Info", MB_OK);
            break;
        case 1005:
            MessageBox(hWnd, "关于被点击", "Info", MB_OK);
            break;
        default:
            break;
        }
    }
    void OnInitMenuPopup(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "即将显示菜单的句柄:%d,被点击的菜单项位置:%d,是否为窗口菜单:%d
    ",
            wParam, LOWORD(lParam), HIWORD(lParam));
        WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    //窗口处理函数
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_INITMENUPOPUP:
            OnInitMenuPopup(hWnd, wParam, lParam);
            break;
        case WM_COMMAND:
            OnCommand(hWnd, wParam);
            break;
        case WM_CREATE:
            OnCreate(hWnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    //注册窗口类
    BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
    {
        WNDCLASSEX wce = { 0 };
    
        wce.cbSize = sizeof(wce);
        wce.cbClsExtra = 200;
        wce.cbClsExtra = 200;
        wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wce.hCursor = NULL;
        wce.hIcon = NULL;
        wce.hIconSm = NULL;
        wce.hInstance = g_hInstance;
        wce.lpfnWndProc = wndProc;
        wce.lpszClassName = lpClassName;
        wce.lpszMenuName = NULL;
        wce.style = CS_HREDRAW | CS_VREDRAW;
    
        ATOM nAtom = RegisterClassEx(&wce);
        if (0 == nAtom)
        {
            return FALSE;
        }
        return TRUE;
    }
    //创建主窗口
    HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName)
    {
        HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, g_hInstance, NULL);
        return hWnd;
    }
    //创建子窗口
    HWND CreateChildWindow(LPSTR lpClassName, LPSTR lpWndName, HWND hParent)
    {
        HWND hChild = CreateWindowEx(0, lpClassName, lpWndName, WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
            100, 100, 200, 200, hParent, NULL, g_hInstance, NULL);
        return hChild;
    }
    //显示窗口
    void Display(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    //消息循环
    void Message()
    {
        MSG nMsg = { 0 };
        while (GetMessage(&nMsg, NULL, 0, 0))
        {
            TranslateMessage(&nMsg);
            DispatchMessage(&nMsg);
        }
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
        AllocConsole();
        g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    
        g_hInstance = hInstance;
        Register("Main", WndProc);
        HWND hWnd = CreateMainWindow("Main", "window");
        Display(hWnd);
        Message();
    
        return 0;
    }
    View Code

      运行结果:

        

      (6)系统菜单

         系统菜单的获取:HMENU GetSystemMenu( HWND hWnd,      //窗口句柄

                                                                             BOOL  bRevert);  //重置选项

         返回获取到的系统菜单句柄

           bRevert:TRUE - 删除旧菜单,恢复到默认的系统菜单

                                  FALSE - 返回当前的系统菜单句柄

         系统菜单的修改:AppendMenu

                                     DeleteMenu( HMENU  hMenu,     //菜单句柄

                                                           UINT     uPosition,  //菜单项ID或位置

                                                           UINT     uFlags);    //决定uPosition参数填写什么

         系统菜单命令响应:

                    通过WM_SYSCOMMAND响应菜单命令。

                        wPARAM:LOWORD - 命令ID

      相关示例代码:

    #include "stdafx.h"
    
    HINSTANCE g_hInstance = 0;  //接收当前程序实例句柄
    
    void OnCreate(HWND hWnd)
    {
        HMENU hSys = GetSystemMenu(hWnd, FALSE);
        for (int i = 0; i < 6; i++)
        {
            DeleteMenu(hSys, 0, MF_BYPOSITION);
        }
        AppendMenu(hSys, MF_SEPARATOR, 0, "");
        AppendMenu(hSys, MF_STRING, 1001, "我的菜单项");
    }
    void OnSysCommand(HWND hWnd, WPARAM wParam)
    {
        switch (LOWORD(wParam))
        {
        case 1001:
            MessageBox(hWnd, "我的菜单项被点击", "Info", MB_OK);
            break;
        }
    }
    //窗口处理函数
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_SYSCOMMAND:
            OnSysCommand(hWnd, wParam);
            break;
        case WM_CREATE:
            OnCreate(hWnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    //注册窗口类
    BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
    {
        WNDCLASSEX wce = { 0 };
    
        wce.cbSize = sizeof(wce);
        wce.cbClsExtra = 200;
        wce.cbClsExtra = 200;
        wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wce.hCursor = NULL;
        wce.hIcon = NULL;
        wce.hIconSm = NULL;
        wce.hInstance = g_hInstance;
        wce.lpfnWndProc = wndProc;
        wce.lpszClassName = lpClassName;
        wce.lpszMenuName = NULL;
        wce.style = CS_HREDRAW | CS_VREDRAW;
    
        ATOM nAtom = RegisterClassEx(&wce);
        if (0 == nAtom)
        {
            return FALSE;
        }
        return TRUE;
    }
    //创建主窗口
    HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName)
    {
        HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW,
            100, 100, 500, 300, NULL, NULL, g_hInstance, NULL);
        return hWnd;
    }
    //显示窗口
    void Display(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    //消息循环
    void Message()
    {
        MSG nMsg = { 0 };
        while (GetMessage(&nMsg, NULL, 0, 0))
        {
            TranslateMessage(&nMsg);
            DispatchMessage(&nMsg);
        }
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
        g_hInstance = hInstance;
        Register("Main", WndProc);
        HWND hWnd = CreateMainWindow("Main", "window");
        Display(hWnd);
        Message();
    
        return 0;
    }
    View Code

      运行结果:

        

        

  • 相关阅读:
    论文阅读笔记(七十二)【ICMR2020】:Compact Network Training for Person ReID
    论文阅读笔记(七十一)【CVPR2018】:Harmonious Attention Network for Person Re-Identification
    论文阅读笔记(七十)【CVPR2021】:Combined Depth Space based Architecture Search For Person Re-identification
    论文阅读笔记(六十九)【CVPR2021】:BiCnet-TKS: Learning Efficient Spatial-Temporal Representation for Video Person Re-Identification
    论文阅读笔记(六十八):图文跨模态行人检索(3篇)
    (一万小时计划)二月二日总结
    (一万小时计划)一月二十三日总结
    (一万小时计划)一月二十日总结
    (一万小时计划)一月二日总结
    (一万小时计划)十二月二十二日总结
  • 原文地址:https://www.cnblogs.com/csqtech/p/5609013.html
Copyright © 2020-2023  润新知