Adding a Custom Menu
Windows only
Problem
Imagine you would like to add a submenu to Rhino’s File menu. You might start fiddling around with the InsertPlugInMenuToRhinoMenu()
and InsertPlugInItemToRhinoMenu()
functions but not seem to be getting anywhere. InsertPlugInMenuToRhinoMenu()
adds a menu into the Rhino’s main menu bar. InsertPlugInItemToRhinoMenu()
adds a menu item anywhere in the Rhino menu. To solve this problem, you want a little of both…
Solution
To insert a menu item, or a submenu, into Rhino’s menu, do the following:
- Use
CRhinoApp::FindMenuItem
to search through Rhino’s menu structure for an existing menu item that’s where you want to insert your menu item. - Use
CRhinoPlugIn::InsertPlugInItemToRhinoMenu
to insert your menu into Rhino’s menu.
Sample
The following example command demonstrates how to add and remove a custom menu from Rhino’s menu:
////////////////////////////////////////////////////////////////
// cmdMyMenu.cpp
#include "StdAfx.h"
#include "MyTestPlugIn.h"
#include "Resource.h"
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
//
// BEGIN MyMenu command
//
class CCommandMyMenu : public CRhinoCommand
{
public:
CCommandMyMenu() {}
~CCommandMyMenu() {}
UUID CommandUUID()
{
static const GUID MyMenuCommand_UUID =
{ <TODO: add your command uuid here> };
return MyMenuCommand_UUID;
}
const wchar_t* EnglishCommandName() { return L"MyMenu"; }
const wchar_t* LocalCommandName() { return L"MyMenu"; }
CRhinoCommand::result RunCommand( const CRhinoCommandContext& );
BOOL LoadMyMenu();
BOOL UnloadMyMenu();
private:
CMenu m_menu;
};
// The one and only CCommandMyMenu object
static class CCommandMyMenu theMyMenuCommand;
CRhinoCommand::result CCommandMyMenu::RunCommand( const CRhinoCommandContext& context )
{
bool bVisible = ( m_menu.GetSafeHmenu() ) ? true : false;
ON_wString prompt;
prompt.Format( L"%s is %s. New value",
EnglishCommandName(),
bVisible ? L"visible" : L"hidden"
);
CRhinoGetOption go;
go.SetCommandPrompt( prompt );
int s_opt = go.AddCommandOption( RHCMDOPTNAME(L"Show") );
int h_opt = go.AddCommandOption( RHCMDOPTNAME(L"Hide") );
int t_opt = go.AddCommandOption( RHCMDOPTNAME(L"Toggle") );
go.GetOption();
if( go.CommandResult() != success )
return go.CommandResult();
const CRhinoCommandOption* opt = go.Option();
if( 0 == opt )
return failure;
if( opt->m_option_index == s_opt )
{
if( false == bVisible )
LoadMyMenu();
}
else if( opt->m_option_index == h_opt )
{
if( true == bVisible )
UnloadMyMenu();
}
else
{
if( true == bVisible )
UnloadMyMenu();
else
LoadMyMenu();
}
return success;
}
BOOL CCommandMyMenu::LoadMyMenu()
{
// Switch the module state so resources are read
// from our plugin (DLL), not Rhino.
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
// Try to load our menu resource from our plugin.
// Note, m_my_menu is a CMenu member variable.
if( 0 == m_menu.GetSafeHmenu() )
{
if( !m_menu.LoadMenu(IDR_MY_MENU) )
return FALSE;
}
// Find a location in Rhino's menu to insert our
// menu item. For this example, we will insert our
// menu on the "Tools" menu just below the "Commands"
// item.
HMENU hParent = 0;
int index = 0;
//if( !RhinoApp().FindRhinoMenuItem(L"&File::&Print...Ctrl+P", hParent, index) )
if( !RhinoApp().FindRhinoMenuItem(L"Too&ls::&Commands", hParent, index) )
{
m_menu.DestroyMenu();
return FALSE;
}
// Create and initialize a MENUITEMINFO struct.
MENUITEMINFO mi;
memset( &mi, 0, sizeof(mi) );
mi.cbSize = sizeof(mi);
// Fill in our menu info
mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU;
mi.wID = MF_POPUP;
mi.fType = MFT_STRING;
ON_wString wstr = L"MyMenu";
mi.dwTypeData = wstr.Array();
mi.fState = MFS_ENABLED;
mi.hSubMenu = m_menu.GetSafeHmenu();
mi.hSubMenu = ::GetSubMenu( mi.hSubMenu, 0 );
mi.wID = IDR_MY_MENU;
// Add our menu to Rhino's menu
BOOL rc = MyTestPlugIn().InsertPlugInItemToRhinoMenu( hParent, index + 1, &mi );
if( !rc )
m_menu.DestroyMenu();
return rc;
}
BOOL CCommandMyMenu::UnloadMyMenu()
{
BOOL rc = FALSE;
// Find our menu item in Rhino's menu.
HMENU hParent = 0;
int index = 0;
if( RhinoApp().FindRhinoMenuItem(L"Too&ls::MyMenu", hParent, index) )
{
// Remove our menu item.
if( ::RemoveMenu(hParent, index, MF_BYPOSITION) )
{
// Redraw Rhino's menu bar.
DrawMenuBar( RhinoApp().MainWnd() );
m_menu.DestroyMenu();
rc = TRUE;
}
}
return rc;
}
//
// END MyMenu command
//
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////