Adding a symbol in menuItems for minimized windows

As a menuItem can be “checked”, is there a way to put a symbol (Lozence or white diamond or whatever) for minimized windows?
(Because using menuitem.icon, the symbol does not show in the same position as the checkmark).

I’m referring to:

No plugings, please. Thanks.

Edited: I’m not using macosLib. Pure Xojo coding, hopefuly with some declare…

You could add an emoji in the caption or text as an alternative to a checkbox or checkmark.

As I said, at present I added a smallish Logenze as icon. But I’ll try and see about adding an emoji.
At least users get an idea that such window is in an uncommon state.

Your question makes sense, as the Apple Interface Guidelines tell you should put a diamond for minimized windows and a checkmark for the active one. And, indeed, it’s expected to be at the same column as the checkmark.
There are declares for this; don’t give up. But I can’t find them right now, sorry.

I will not.
BTW, I could never understand why Xojo, alongside the .checked boolean, did not provide a .diamonded one too.

Under the hood, the checkmark and diamond are the same property (an integer). Xojo only provides the checkmark as a boolean, possibly because others systems only support checkmarks and Xojo dislikes providing features that are on a single OS (it does, rarely, though).

The diamond appears in the window list on the application icon (right click on the application icon in the dock and the mark is there). I’ve never noticed that it should appear in the Window menu as well.

Safari certainly does it.

and Mail.

macOSLib is using an old Carbon API to add/read checkmarks. There must be an updated Cocoa API for that.

Let the macOS do it for you. Over on my blog is how to tell the macOS which menuitem to use as the Window menu.

https://ohanaware.com/blog/202127/Letting-the-macOS-manage-your-Window-menu.html

1 Like

Thanks Sam, that works a treat. Here is the API2 version to work with DesktopMenuItems:

#If targetMacOS Then
  // --- This code snippet was made from the Ohanaware App Kit 2021 - ohanaware.com
  // --- Basically, we grab the NSMenu instance of the windowMenu item, tell Apple's App Kit to use that for the Window menu.
  // --- Modified for API2
  
  Declare Function NSClassFromString               Lib "Foundation"                          ( className As CFStringRef ) As Ptr
  Declare Function NSMenuitem_Submenu              Lib "AppKit" Selector "submenu"           ( NSMenuitemInstance As Ptr ) As Ptr
  Declare Sub      NSApplication_setWindowsMenu    Lib "AppKit" Selector "setWindowsMenu:"   ( NSApplicationInstance As Ptr, inNSMenuitem As Ptr )
  Declare Function NSApplication_sharedApplication Lib "AppKit" Selector "sharedApplication" ( NSApplicationClass As Ptr ) As Ptr
  
  Dim subMenuRef As Ptr = NSMenuitem_Submenu( WindowMenu.Handle )
  NSApplication_setWindowsMenu( NSApplication_sharedApplication( NSClassFromString( "NSApplication" ) ), subMenuRef )
#endif

If you are using this code you need to strip out anything in your application that adds Window menu items to your window menu. macOS will do this for you. You should also ensure you do not end your window menu template with a separator, macOS will add its own.

Another thing this enables is the • indicator next to menus for Windows that are ‘modified’ or ‘dirty’, ie contain unsaved changes. It also sorts the Windows into alphabetical order (which is a macOS guideline).

How does it know when a window is dirty? Suppose it contains a group of radio buttons, how does it spot that I have changed a selection?

The window has a “Changed” flag. If that is true you get the bullet in the red dot (close window) and on the menus. If it is false you don’t.

DesktopWindow - Changed

Righto, thanks.

I tried this example, which works (thanks for sharing; I looked for it since months). But what if I need to have a menu item there for which the window may not be on screen yet (or closed later, with the menu item being the entry to show the window)?

It’s not what I’m getting:
image

(I’d have changed my OS to english to post an english screenshot, but my app isn’t in english anyway).

After the “Move to iPad” item, there are 5 menu items from the Xojo menu (including one separator), and then the windows added automatically. There’s no separator after “Move to iPad”.

So this is my Window Menu as it appears in Xojo Window editor:

This is how it appears when running:

In the application Open event I have the following code:

#If targetMacOS Then
  // --- This code snippet was made from the Ohanaware App Kit 2021 - ohanaware.com
  // --- Basically, we grab the NSMenu instance of the windowMenu item, tell Apple's App Kit to use that for the Window menu.
  
  Declare Function NSClassFromString               Lib "Foundation"                          ( className As CFStringRef ) As Ptr
  Declare Function NSMenuitem_Submenu              Lib "AppKit" Selector "submenu"           ( NSMenuitemInstance As Ptr ) As Ptr
  Declare Sub      NSApplication_setWindowsMenu    Lib "AppKit" Selector "setWindowsMenu:"   ( NSApplicationInstance As Ptr, inNSMenuitem As Ptr )
  Declare Function NSApplication_sharedApplication Lib "AppKit" Selector "sharedApplication" ( NSApplicationClass As Ptr ) As Ptr
  
  Dim subMenuRef As Ptr = NSMenuitem_Submenu( WindowMenu.Handle ) // WindowMenu is the name of my Window menu, if you have changed it you need to change it here.
  NSApplication_setWindowsMenu( NSApplication_sharedApplication( NSClassFromString( "NSApplication" ) ), subMenuRef )
#endif

It only works for currently open windows. As you open them it will automatically add them to the menu, as you remove them it will automatically remove them. It also only shows “Document” type windows.

If you want a fixed menu item like Mail has for “Message Viewer”, then just add a static menu item and action that yourself.

If your menu looks like this in the Menu editor:

Then this will happen:

Which isn’t correct.

First: thank you for sharing with us your code.

Using BigSur.
So, in the open event of App I pasted:
#if TargetMacOS
declare Function NSClassFromString lib “Foundation” ( className as CFStringRef ) as integer
declare Function NSMenuitem_Submenu lib “AppKit” selector “submenu” ( NSMenuitemInstance as integer ) as integer
declare Sub NSApplication_setWindowsMenu lib “AppKit” selector “setWindowsMenu:” ( NSApplicationInstance as integer, inNSMenuitem as integer )
declare function NSApplication_sharedApplication lib “AppKit” selector “sharedApplication” ( NSApplicationClass as integer ) as integer

Dim subMenuRef as integer = NSMenuitem_Submenu( windowMenu.handle( menuitem.handleType.CocoaNSMenuItem ) )
NSApplication_setWindowsMenu( NSApplication_sharedApplication( NSClassFromString( "NSApplication" ) ), subMenuRef )

#endif

In the MainMenuBar > WindowMenu I already had these two menuitems:
windowMinimize
windowMaximize

Now, lanching the app, in the Window Menu I find four items:
Tile Window to Left of Screen
Tile Window to Right of Screen
Minimize M
Zoom
plus, at the bottom, the name of my main window.

I expected Minimize and Zoom to be at the top. So I tried removing from the MainMenuBar both windowMinimize and windowMaximize

but now the launched app only shows:
Tile Window to Left of Screen
Tile Window to Right of Screen

So, in the MainMenuBar I restored windowMinimize and windowMaximize and added, at the end of your code:
windowMenu.remove(“TileWindowtoLeftofScreen”)
windowMenu.remove(“Tile WindowtoRightofScreen”)

but the two menus do not get removed. I spent some time on AppleDeveloper to find the right name of the two items. But until now I could not find them.
Tomorrow I’ll resume experimenting.
Meantime, thanks again.

Hence my question :wink:

Yes, but I feel it defeat a bit the purpose of a Window menu.

Indeed. Between Xojo and an OS function, some things need to be tuned.

Thanks for your answer.

Are you sure the Xojo menu items’ name can actually match the OS identifier?