Setting the diamond minimized state for an NSMenuItem

Discussion in 'Mac Programming' started by Nutter, May 12, 2007.

  1. Nutter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #1
    Does anyone know how to set an NSMenuItem to show the diamond icon used to denote a minimised window? I've worked out how to use -setState: to set the "tick" (NSOnState) and the "dash" (NSMixedState), but that diamond seems curiously elusive...
     
  2. Eraserhead macrumors G4

    Eraserhead

    Joined:
    Nov 3, 2005
    Location:
    UK
  3. Nutter thread starter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
  4. Eraserhead macrumors G4

    Eraserhead

    Joined:
    Nov 3, 2005
    Location:
    UK
    #4
    In which case I have no idea, sorry.
     
  5. wittegijt macrumors member

    Joined:
    Feb 18, 2007
    Location:
    Eindhoven
    #5
    Isn't the diamond set automatically by Cocoa?

    Wittegijt.
     
  6. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #6
    You'll have to use Carbon it seems. It looks like you might be able to do something with SetMenuItemKeyGlyph and kMenuDiamondGlyph, but I'm not sure. There is a method for disabling that column where the diamond would go (SetMenuExcludesMarkColumn) but I didn't see any related methods to that for setting the actual diamond (SetMenuItemKeyGlyph seems to set the glyph on the right side).
     
  7. Nutter thread starter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #7
    Thanks kainjow, I'll have a sniff around.

    Wittegijt, Cocoa does automatically set the diamond mark for items it adds to the Window menu itself. However, I'm placing a menu item for my window in the menu manually, as I want it to be there whether or not the window is open.

    I'm pretty amazed that I can't seem to find anything at all about this by searching the web. Nobody even seems to have asked the question before. This page on CocoaDev mentions tracking and setting the window's minimization state, but maddeningly it doesn't say how!
     
  8. Nutter thread starter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #8
    This seems to be possible using the Menu Manager function SetItemMark() with the constant diamondMark. But that takes a MenuRef.

    How does one get a MenuRef from an NSMenu instance? With the undocumented function _NSGetCarbonMenu(). Of course.

    I might try it if I am desperate. :)
     
  9. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #9
    I would just not worry about it. In Safari, when you select Window > Downloads, the downloads window that appears has its own menu in Window, just like a normal window. I would suggest going that route.
     
  10. Nutter thread starter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #10
    Yeah, that's probably sensible. I just think that, since my app will only have one window, having it listed twice in the Windows menu will look a bit silly. Not that anyone ever looks in the Windows menu...

    ... and it's a good thing they don't, because the inconsistency between apps is shocking. The one-window apps that Apple ships with the OS all seem to display only one item for the main window, but some of them put it above "Bring All to Front" and others put it below, none of them bother with the diamond mark when the window is minimized, and many of them don't even display the tick when the window is active. Except for iTunes, which displays both tick and diamond, but unlike the other apps hides/unhides the window when you select it from the menu. What a mess!
     
  11. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #11
    If you run the onStateImage method for each menu item in the Window menu, the menu items that correspond to a window will return a 12x12 diamond image: View attachment 74269 - however, "Changing state images is currently unsupported in Mac OS X."

    But for fun I tried to write a hack category method but it didn't seem to work :)

    Code:
    interface NSMenuItem (Hacks)
    - (void)setOnStateImageHack:(NSImage *)image;
    @end
    @implementation NSMenuItem (Hacks)
    - (void)setOnStateImageHack:(NSImage *)image
    {
    	[_onStateImage release];
    	_onStateImage = [image retain]; 
    }
    @end
     
  12. Nutter thread starter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #12
    Haha. You would have thought someone would get around to deprecating that at some point in the last six years.

    Here's a quick way to do it:

    Code:
    extern MenuRef _NSGetCarbonMenu(NSMenu *);
    SetItemMark(_NSGetCarbonMenu([NSApp windowsMenu]), [[NSApp windowsMenu] indexOfItemWithTag:someTag] + 1, diamondMark);
    
    I will post back when I have worked out how to do this without using an unsupported, undocumented private function.
     
  13. Nutter thread starter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #13
    Hmmm, not as easy as I thought. I don't think it can be done without knowing the menu ID of the Windows menu, and I don't know how to get that.

    On second thoughts, this might be a little safer:

    Code:
    extern MenuRef _NSGetCarbonMenu(NSMenu *);
    MenuRef windowsMenuRef = _NSGetCarbonMenu([NSApp windowsMenu]);
    if (windowsMenuRef != NULL)
    	SetItemMark(windowsMenuRef, [[NSApp windowsMenu] indexOfItemWithTag:someTag] + 1, diamondMark);
    
     

Share This Page