I’ve been using Xojo for a couple of weeks know and purchased my license. I’ve managed to create a quite simple yet functional app and I got a lot of help reading the docs and searching in the forums. Everything looks good so far, but I’m stuck with the menu bar. I have a menu bar with two options (for the moment haha):
File with a menu item Close(woks fine) Window with these menu items:
[b] Minimize[/b] [i]works fine minimizing the window[/i]
[b]Separator[/b]
[b]My app name[/b] [i] A menu item (MyMenuItem) with the name of the app[/i]
The window have an EventHandler, there I use MyMenuItem.Checked = True so there’s a checkmark simulating the active window.
The problem comes when resizing the window, all of the options of the menu bar become “disabled” (I suppose that’s normal behavior) but what I want to achieve is the My app name item (MyMenuItem) to be “active” so the user can click it to restore the window (restore/maximize) and have a “bullet” instead of the checkmark (until the window is maximized) but I don’t know how and can’t find the exact answer on the forums (I swear I tried!!!)
Here’s the behavior I want to achieve (from another app):
I’ve tried enabling MyMenuItem in the EventHandler, but it doesn’t work. I don’t know if the “bullet” is an icon I have to assign.
Thanks for the prompt response! That did the trick. The “WindowMenu” in the example projects also helped me understand some other things.
The only doubt I have is the “bullet” instead of the check mark in the MenuItem when the window is minimized. I know this is too much, given I already have the menu item enabled but I’m curious, how can I achieve this? is this a custom icon?
Well, this is available in MacOSLib, but that is kind of overkill. You may be able to strip it out and use it directly but I don’t know for sure. Look in the Additional Modules Folder -> Cocoa MenuItems module and you should see the relevant class. I think it’s called MenuItemWindowMenu.
Thanks for the prompt response! That did the trick. The “WindowMenu” in the example projects also helped me understand some other things.
The only doubt I have is the “bullet” instead of the check mark in the MenuItem when the window is minimized. I know this is too much, given I already have the menu item enabled but I’m curious, how can I achieve this? is this a custom icon?
[quote=142884:@Dave S]but you don’t have “control” of changing text in that area.
.CHECKED=true gives a checkmark
or adding an ICON (picture of a diamond)[/quote]
Diamond is just a character he can copy/paste from this post and place in the Text property of his menuitem just like any other character.
I created a menuitem subclass which you can set to have a diamond, a checkmark, or nothing. It is independent of MacOSLib but depends on a BasicNSImage class to provide some of the system images, as well as a module for reading string constants to be used in the BasicNSImage class. Add the two classes and module to your project and set the super of your window menu items to DiamondMenuItem and you should be all set. Enjoy! Link to project
I’m learning stuff looking at your code Jason, thanks for sharing. It gave me the idea to change just the MixedState image to the diamond and then the Checked and Unchecked states can still be controlled with normal Xojo methods.
Implemented as extension methods there’s only 2 needed…
MenuItem.addDiamondAsMixedStateImage() sets the image for mixedstate
MenuItem.setToMixedState() switches to mixedstate
Also, _NSGetThemeImage is a private function. Probably fine (except for App Store inclusion) but I copied the image out to file diamond.png and use that instead. Maybe this is not so good, missing a retina version or something and a better picture can be saved out.
Another odd wrinkle is that the docs for setOnStateImage, setOffStateImage and setMixedStateImage all say “Changing state images is currently unsupported in OS X.” yet they all seem to work.
//file diamond.png is in Resources folder that's next to project file
//(will also need CopyFiles build step to copy file into built app)
//Menubar has item named FileMainWindow
Class App inherits Application
Sub Open()
FileMainWindow.addDiamondAsMixedStateImage //load diamond when app opens
End Sub
Function FileMainWindow() As Boolean //MenuHandler
Window1.Show
Return True
End Function
End Class
Window MainWindow
Sub Open()
FileMainWindow.Checked = true //show checked on initial opening
End Sub
Sub Close()
FileMainWindow.Checked = false //clear when closed
End Sub
Sub Minimize()
FileMainWindow.setToMixedState //switch to diamond
End Sub
Sub Restore()
FileMainWindow.Checked = true //return to check
End Sub
End Window
Module DiamondizeMenu
Sub addDiamondAsMixedStateImage(extends theMenuItem As MenuItem)
//set MixedState image to be a diamond
const Cocoa = "Cocoa"
declare function NSClassFromString lib Cocoa (className as CFStringRef) as ptr
declare function alloc lib Cocoa selector "alloc" (classRef as ptr) as ptr
declare function URLWithString lib Cocoa selector "URLWithString:" _
(id as Ptr, URLString as CFStringRef) as Ptr
declare function initWithContentsOfURL lib Cocoa selector "initWithContentsOfURL:" _
(id as Ptr, url as Ptr) as Ptr
declare sub setMixedStateImage lib Cocoa selector "setMixedStateImage:" _
(id as integer, image as Ptr)
dim NSURLclass As Ptr = NSClassFromString("NSURL")
dim NSImageclass As Ptr = NSClassFromString("NSImage")
dim f As FolderItem = getDiamondFile //get file of diamond image
dim url As Ptr = URLWithString(NSURLclass, f.URLPath) //get NSURL of file
dim img As Ptr = initWithContentsOfURL(alloc(NSImageclass), url) //open as NSImage
dim menuHandle As integer = theMenuItem.Handle(MenuItem.HandleType.CocoaNSMenuItem)
setMixedStateImage(menuHandle, img) //set the image for mixedstate
End Sub
Sub setToMixedState(extends theMenuItem As MenuItem)
//set state to mixedstate option
declare sub setState lib "Cocoa" selector "setState:" (id as integer, newState as integer)
dim menuHandle As integer = theMenuItem.Handle(MenuItem.HandleType.CocoaNSMenuItem)
setState(menuHandle, -1) //-1=MixedState, 0=empty, 1=on/checked
End Sub
Private Function getDiamondFile() As FolderItem
#if DebugBuild then
return GetFolderItem("").Child("Resources").Child("diamond.png")
#else
return App.ExecutableFile.Parent.Parent.Child("Resources").Child("diamond.png")
#endif
End Function
End Module