Search code examples
c++macosmenuwxwidgetsmenubar

Empty wxWidgets menus on OSX


I'm using wxWidgets 2.9.4 on OSX 10.8.3 and built the library for Cocoa.

I want to add a menu bar with some menus to a wxFrame:

wxMenuBar* menuBar = new wxMenuBar();

wxMenu* fileMenu = new wxMenu();
wxMenu* helpMenu = new wxMenu();

helpMenu->Append(wxID_ABOUT, wxT("About"));
fileMenu->Append(wxID_EXIT, wxT("Exit"));

menuBar->Append(fileMenu, wxT("File"));
menuBar->Append(helpMenu, wxT("About"));

SetMenuBar(menuBar);

Since i'm using standard IDs for adding menu items(as described here), it automatically moves About and Exit to application menu(I think it's called apple menu), but also makes File and Help menus empty:

Demonstration

Are there any ways to hide those empty menus?

Actually I tried to remove them:

#if defined(__WXMAC__) || defined(__WXOSX__) || defined(__WXOSX_COCOA__)
    menuBar->Remove(0);
    menuBar->Remove(0);
#endif

but that caused the about and exit menu items HelpText, not to be displayed on my frame StatusBar (might have other side effects as well.)


Solution

  • It seems there's no standard way for hiding menus in wxWidgets.

    I ended up writing a few lines of Objective-C code to find and hide empty menus:

    // MacMenuWorkaround.h
    
    #import <Cocoa/Cocoa.h>
    
    @interface MacMenuWorkaround : NSObject
    
    +(void) hideEmptyMenus;
    
    @end
    

    // MacMenuWorkaround.m
    
    #import "MacMenuWorkaround.h"
    
    @implementation MacMenuWorkaround
    
    +(void) hideEmptyMenus {
        NSMenu* mainMenu = [[NSApplication sharedApplication] mainMenu];
    
        for (NSMenuItem* item in [mainMenu itemArray]) {
            NSMenu* menu = [item submenu];
    
            if ([[menu itemArray] count] < 2) {
                [item setHidden:YES];
            }
        }
    }
    
    @end
    

    // MacMenuWorkaroundBridge.h
    
    #ifndef __wxstarter__MacMenuWorkaroundBridge__
    #define __wxstarter__MacMenuWorkaroundBridge__
    
    namespace CocoaBridge {
        void hideEmptyMenus();
    }
    
    #endif /* defined(__wxstarter__MacMenuWorkaroundBridge__) */
    

    // MacMenuWorkaroundBridge.cpp
    // Set file type to Objective-C++ Source
    
    #import "MacMenuWorkaround.h"
    #include "MacMenuWorkaroundBridge.h"
    
    namespace CocoaBridge {
        void hideEmptyMenus() {
            [MacMenuWorkaround hideEmptyMenus];
        }
    }
    

    Then in my code:

    #include "MacMenuWorkaroundBridge.h"
    //...
    #if defined(__WXMAC__) || defined(__WXOSX__) || defined(__WXOSX_COCOA__)
    CocoaBridge::hideEmptyMenus();
    #endif