c++ - C++ Win32程序中,如何修改菜单的标题?

标签 c++

我使用 c++ win32 创建了一个弹出菜单。 源代码是:

IDR_POPUP_MENU MENU DISCARDABLE
BEGIN
POPUP "POPUP"
BEGIN
    MENUITEM "Turn On"                          IDM_STATUS
    POPUP "Preferences"         
    BEGIN
        MENUITEM "Turn Autostart Off"                           IDM_AUTOSTART 
        MENUITEM "Turn Lock Screen Off"                         IDM_LOCKSCREEN
    END
    MENUITEM "Exit",                        IDM_EXIT
END
END

现在我想在单击时将标题“关闭锁屏”更改为“打开锁屏”。

.cpp 中的代码是:

case IDM_LOCKSCREEN:
{
    if(lockscreen)
    {
        lockscreen = FALSE;
        HMENU hMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUP_MENU));
        hMenu = GetSubMenu(hMenu, IDM_LOCKSCREEN);
        ModifyMenu(hMenu, IDM_LOCKSCREEN, MF_BYCOMMAND | MF_CHECKED, IDM_LOCKSCREEN, "Turn LockScreen Off");
    }

    break;
}

但是我无法用这种方法获取hMenu。

hMenu 的指针为空。我在那里放了一个断点并得到 (*hMenu).unused:CXX0030:Error: expression cannot be evaluated!

有人可以向我解释如何处理这个错误吗?

最佳答案

您的代码失败的原因是您将 hMenu 替换为 GetSubMenu。您的菜单应该在 WM_CREATE 案例的开头加载。您正在修改的菜单是最近加载的菜单,它没有添加到当前窗口,因此您看不到任何更改。对于 ModifyMenu,您需要指定 MF_STRING 标志来更改标题!

如果菜单是动态的并且是在右键单击时创建的,那么您不需要使用 SetMenu 来设置菜单并且它可以即时加载和更改..但是请记住,您不需要为此使用 GetSubMenu,因为您正在为每个菜单使用定义的 ID。如果要通过从 0 开始的索引位置检索菜单,GetSubMenu 会有所帮助。

此外,在下面的代码中,我选择将菜单句柄保存到一个变量中。您不需要此静态变量。您还可以在需要 MenuHandle 的 case 语句中使用 GetMenu

资源.h:

#ifndef RESOURCES_HPP_INCLUDED
#define RESOURCES_H_INCLUDED

#define IDR_POPUP_MENU 1001
#define IDM_STATUS 1002
#define IDM_AUTOSTART 1003
#define IDM_LOCKSCREEN 1004
#define IDM_EXIT 1005

#endif // RESOURCES_H_INCLUDED

资源.rc:

#include "Resources.h"

IDR_POPUP_MENU MENU DISCARDABLE
BEGIN
POPUP "POPUP"
BEGIN
    MENUITEM "Turn On", IDM_STATUS
    POPUP "Preferences"
    BEGIN
        MENUITEM "Turn Autostart Off", IDM_AUTOSTART
        MENUITEM "Turn Lock Screen Off", IDM_LOCKSCREEN
    END
    MENUITEM "Exit", IDM_EXIT
END
END

主要.cpp:

#include <windows.h>
#include "Resources.h"

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HMENU hMenu = NULL;

    switch(message)
    {
        case WM_CREATE:
        {
            hMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUP_MENU));
            SetMenu(hwnd, hMenu);

        }
        break;

        case WM_COMMAND:
        {
            switch(wParam)
            {
                case IDM_LOCKSCREEN:
                {
                    static bool locked = true;

                    if (locked)
                    {
                        //You can use HMENU = GetMenu(hwnd); if you want.. instead of a static variable..
                        ModifyMenu(hMenu, IDM_LOCKSCREEN, MF_BYCOMMAND | MF_STRING, IDM_LOCKSCREEN, "Turn LockScreen On");
                    }
                    else
                    {
                        ModifyMenu(hMenu, IDM_LOCKSCREEN, MF_BYCOMMAND | MF_STRING | MF_CHECKED, IDM_LOCKSCREEN, "Turn LockScreen Off");
                    }

                    locked = !locked;
                }
                break;
            }
        }
        break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    HWND hwnd;
    MSG messages;

    WNDCLASSEX wincl;
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = "CodeBlocksWindowsApp";
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (0, "CodeBlocksWindowsApp", "Code::Blocks Template Windows App", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
    ShowWindow (hwnd, nCmdShow);

    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
}

关于c++ - C++ Win32程序中,如何修改菜单的标题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28120101/

相关文章:

c++ - 搜索 vector 成员的前n%个C++

C++ 使用 boost fusion adapt_struct 迭代到嵌套结构字段

c++ - C++ 链接步骤中的 undefined reference 错误

c++ - cpp继承问题

c++ - std::allocator::max_size() 背后的基本原理是什么?

c++ - std::atomic_thread_fence 具有 undefined reference

c++ - 为什么这段带有 TCHAR 和可变参数的代码会有这种行为?

c++ - AssociateColorProfileWithDevice,你从哪里得到设备名称?

c++ - 在 Visual C++ 中通过 TCP 发送字符串数据

c++ - 为什么不调用私有(private)成员的默认构造函数?