So while working on RB 6 I found myself working with the new MenuItem APIs, and I was getting frustrated over not knowing how to share most of a menu bar amongst windows while still keeping them slightly different. Here's the scenario:
For console application, I want the mostly same menu bar as for GUI applications. The difference is, for the console window I want things like "Add Window" to be gone since they don't make sense. But I want to make sure things like the open recents menu are the same between each window. So how do you do this?
Easy! You call Mars up and ask! Just kidding... but he did point out something that I never realized (keep in mind, Mars and I were the two people who wrote the new MenuItem APIs): you can make a new instance of a menu bar since it's really a class under the hood. So, to accomplish what I want to do, I wrote code like this:
[rbcode]
Sub Open()
if IsWindowConsoleWindow() then
// Make a new, identical copy of the menu bar
MenuBar = new GuiMenuBar
// Remove the stuff we don't care about
RemoveFrom( MenuBar.Child( "EditMenu" ), "EditArrange" )
// Hook in the proper instances of the global menus we want to
// be the same.
SwapMenus( MenuBar, "WindowMenu", App.MenuBar.Child( "WindowMenu" ) )
end
End Sub
[/rbcode]
In this code, RemoveFrom simply takes the MenuItem you wish to yank a child item from and the name of the child item and it works like this:
[rbcode]
Sub RemoveFrom( parent as MenuItem, name as String )
Dim i, count as Integer
count = parent.Count
for i = 0 to count - 1
if parent.Item( i ).Name = name then
// This is the child to yank
parent.Remove( i )
return
end
next
End Sub
[/rbcode]
And SwapMenus is similarly easy to write. It just takes the MenuItem which is the parent, the name of the item to replace, and the replacement item. It looks something like this:
[rbcode]
Sub SwapMenus( parent as MenuItem, name as String, replacement as MenuItem )
Dim i, count as Integer
for i = 0 to count - 1
if parent.Item( i ).Name = name then
// Remove the old item from the parent
parent.Remove( i )
// Replace it with what we're given
parent.Insert( replacement, i )
return
end
next
End Sub
[/rbcode]
Voila! This handful of code lets me have multiple windows with mostly the same menu bars (but still slightly different) and all the same MenuItem handling logic. After looking into how easy it was to do (when all the other ideas I could come up with were very complicated) I was shocked. Oh well, maybe Mars and I really did get the API right after all. ;-)
Leave a comment