如何在 Win32 菜单中使用 SDL

Posted

技术标签:

【中文标题】如何在 Win32 菜单中使用 SDL【英文标题】:How to use SDL with Win32 Menus 【发布时间】:2017-12-11 02:38:58 【问题描述】:

这是我已经研究了很长一段时间的 GameBoy 模拟器。它最初只适用于 MacOS,但我最近一直在使用 Windows 端口。我正在使用 SDL 来创建和渲染窗口。我想做的是使用 Win32 API(CreateMenu、AppendMenu 等)创建一个普通的 Windows 菜单栏。到目前为止,我可以让菜单栏存在于窗口中,但我正在尝试使用 CALLBACK WndProc() 添加回调,因此菜单知道您正在单击一个选项。这没有那么成功。有人知道怎么做吗?

这是 WinMain 入口点:

/***************** INSTANCES *******************/
static Core::GameBoy* mGameBoy_Instance;
static FrontEnd::SDLContext* mSDL_Instance;
/***********************************************/
INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)

    // Load options
    Core::Settings settings;
    Util::CreateSettingsFromFile(OPTIONS_FILE_PATH, settings);
    settings.skip_bootrom = true;
    // Create the system instance
    mGameBoy_Instance = new Core::GameBoy(settings, WIN_WIDTH, WIN_HEIGHT);
    // Initalize Render Context
    const char* windowTitle = mGameBoy_Instance->GetCurrentROM()->GetRomName();
    mSDL_Instance = new FrontEnd::SDLContext(WIN_WIDTH, WIN_HEIGHT, WIN_SCALE, windowTitle);

    // Initialize menubar
    SDL_SysWMinfo sysInfo;
    SDL_VERSION(&sysInfo.version);
    SDL_GetWindowWMInfo(mSDL_Instance->GetWindow(), &sysInfo);
    HWND hwnd = sysInfo.info.win.window;

    /*********************************/
    HMENU menubar = CreateMenu();
    /*********************************/
    HMENU file = CreateMenu();
    HMENU exit = CreateMenu();
    /*********************************/
    AppendMenu(menubar, MF_POPUP, (UINT_PTR)file, "File");
    AppendMenu(file, MF_STRING, (UINT_PTR)exit, "Exit");
    SetMenu(hwnd, menubar);

    // start sdl thread and main loop

这是回调函数代码:

LRESULT CALLBACK WndProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)

    switch (uMsg) 
    case WM_COMMAND:
    
        switch (LOWORD(wParam)) 
        case 2: // Should be the Exit button in the order of the menu
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            break;
        
        return 0;
    
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProcW(hwnd, uMsg, wParam, lParam);
    

    return NULL;

当我这样做时,不会调用回调。 任何帮助表示赞赏。 谢谢!

【问题讨论】:

显示minimal reproducible example.. 【参考方案1】:

您将退出 HMENU 指定为您为退出创建的项目的 ID,这与“案例 2:”不匹配。

摆脱“HMENU退出”拨打电话:

AppendMenu(file, MF_STRING, 2, _T("Exit"));

我建议您分配一些常量名称(#define 或 enum)并在 AppendMenu 和 case 语句中使用该标识符。

【讨论】:

不行,还是不行。当我点击它时什么都不做。【参考方案2】:

普通菜单项具有数字 ID,而不是 HMENU 句柄。 Submenus should be created with CreatePopupMenu,不是CreateMenu

#define ID_EXIT 50

...

  HMENU menubar = CreateMenu();
  HMENU filemenu = CreatePopupMenu();
  AppendMenu(filemenu, MF_STRING, ID_EXIT, "Exit");
  AppendMenu(menubar, MF_POPUP, (UINT_PTR) filemenu, "File");
  SetMenu(hwnd, menubar);

...

  case WM_COMMAND:
        switch (LOWORD(wParam)) 
          case ID_EXIT:
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            break;
        
    break;

【讨论】:

以上是关于如何在 Win32 菜单中使用 SDL的主要内容,如果未能解决你的问题,请参考以下文章

SDL2:如何同时拥有 SDL2 菜单和 OpenGL 上下文?

在win32中绘制像素的最快方法是啥

如何在c ++ win32 API中将图标添加到菜单项[重复]

c++ win32输出一个文本

如何修复“SDL_image无法初始化!”?

如何查看电脑是Win32还是64