TweetFollow Us on Twitter

Writing a Menulet Extension

Volume Number: 22 (2006)
Issue Number: 2
Column Tag: Programming

Writing a Menulet Extension

Extending an Application or Providing a Service via a Menulet

by Andrew Turner


Most modern operating systems have some constantly viewable area that displays useful icons, data, and notifications relating to your computer and other services. Windows uses the 'task tray', the Linux specifies a 'system tray', and Mac OS X uses the menubar. On the Mac, this menubar is where users see the date/time, audio volume, spotlight icon, and any other number of tools they can install to display information.

The menubar icons and tools are frequently called 'menulets', or status items. Menulets can be an application unto themselves, such as MenuMeters ( software/menumeters/), which displays the current CPU, memory, or network usage as graphs and blinking lights. A menulet can also extend a larger application such as DesktopManager's ( menulet that allows a user another means to switch between multiple virtual desktops and can display the current viewable desktop.

Figure 1: Example Menubar with Menulets.

Figure 1 shows an example menubar with the menulets (from left to right): DesktopManager, Salling Clicker, Applescript Menu, MissingSync, MenuMeters, Date/Time, Audio, and Spotlight.

There are two major 'flavors' of menulets: the standard and publicly documented NSStatusItem and the private and undocumented NSMenuExtra. NSStatusItems are fully capable of doing most anything a menulet can do. The one major benefit of an NSMenuExtra is the ability to mouse-drag reorder the menulet with regards to the other system menulets, whereas NSStatusItems are placed further along the left-side of the menulets area of the menubar. Because the NSMenuExtra API is undocumented, and subject to change by Apple whenever deemed necessary, it is best to avoid using the API in your applications.

The rest of this article will lead you through developing your own NSStatusItem menulet including displaying text or an icon in the view, making a drop-menu and setting up automatic updating.

Creating the Menulet

The first thing to do is create a new XCode project for building this tutorial. Alternatively, you could add these files and resources to an already existing application. Menulets must belong to an application since the status bar will not retain and update your menulet for you. Therefore, for purposes of illustration and testing we will be creating a new, stand-alone application for controlling our menulet.

The example menulet will display the user's external IP address in the menu bar. The external IP address is obtained by querying a remote server and then setting the text in the menubar to the external IP address.

In XCode select New Project... and choose to create a Cocoa Application. After the new project is created, right click on the Classes folder and choose Add > New File... You will be adding an 'Objective-C class', and name it "IPMenulet.m". Make sure to leave 'Also create IPMenulet.h' checked.

The application will need to hold a reference to the NSStatusItem, as well as initialize the menulet, add it to the system status bar, and update data in the menulet. Add the following code to the IPMenulet.h and IPMenulet.m files you created in your project.


@interface IPMenulet : NSObject {
    NSStatusItem *statusItem;



    [statusItem release];
      [super dealloc];
- (void)awakeFromNib
   statusItem = [[[NSStatusBar systemStatusBar] 
   [statusItem setHighlightMode:YES];
   [statusItem setTitle:[NSString 
   [statusItem setEnabled:YES];
   [statusItem setToolTip:@"IPMenulet"];

   [statusItem setAction:@selector(updateIPAddress:)];
   [statusItem setTarget:self];

The code above creates and attaches a new NSStatusItem of variable length to the system status bar. Since the status item is variable length, the area will grow and shrink depending on the content of the status item's title or icon. Alternatively, you could set the length via the statusItemWithLength: method to NSSquareStatusItemLength, which would fix the width of the status item to the height of the status bar (currently always 22 pixels high).

The parameter highlightMode specifies if a box is drawn around the menulet when clicked, and enabled determines if the menulet is grayed out or darkened. Since we don't yet know our IP address, we will set the initial display to, and the tooltip is what is displayed when a user hovers their mouse over the menulet.

At the end of the initialization code there are the setAction: and setTarget: functions. Similar to other applications, these functions set the functions that should be called when a user clicks on the menulet. In this example, we will be updating the IP address whenever the user clicks on the menubar. It is also possible to set the double-click action if desired.

We now need to implement the updateIPAddress: method.


   NSString *ipAddr = [NSString stringWithContentsOfURL:
         [NSURL URLWithString:
   if(ipAddr != NULL)
       [statusItem setTitle:
            [NSString stringWithString:ipAddr]]; 

The updateIPAddress: function gets the IP address as a string from an external server query and then sets the title of the NSStatusItem.

Building the NIB Interface

We now have all of the code that we need . However, when the application starts, it needs to know to create the menulet. Therefore, we will create an instantiation of the menulet in the NIB file that is loaded. This will allow us to later add more code and hooks to our menulet for controlling menu items.

To create the menulet double-click the MainMenu.nib in the Resources folder of the project. After it loads, click the "Classes" tab, then choose "Classes" in the menubar, "Read Files...", navigate to IPMenulet.h and "Parse".

Figure 2: Parsing IPMenulet.h into Interface Builder allows it to be instantiated as part of the application.

This parsing loads the IPMenulet interface into Interface Builder. We still need an instance of the class to use in our application. Right-click "IPMenulet" in the pane view and click "Instantiate IPMenulet". This will place a blue-cube and IPMenulet instance in our Interface Builder window.

At this point we don't want a main application window to pop-up at startup, so click the Window icon and delete it. Then save the nib file, return to XCode and choose the "Build and Go".

Depending on how many menulets you already had in your status bar you may have to click outside of XCode since XCode has a large number of menubar items. You should see Click on the menulet and after a short pause you should see an updated IP address.

Removing the Dock Icon

If you are making a menulet-only application, having a dock icon seems like an unnecessary item. It is possible to have an application 'hide' its dock icon by specifying a new value in the "Info.plist" file in your XCode project. At the end of the list, just before, the </dict>, add the following key and value:


Now when your menulet application starts up, it doesn't have a dock icon. Be careful however, as you currently have no easy means to quit your menulet application either. While developing, it is possible to quit the application by pressing the "Stop" icon in XCode.

Using a Menulet Icon

You now have a fully functional menulet application that takes up a lot of valuable menubar space. For some menulets, it may be best to use an icon that the user will click for more information, or an icon that changes depending on the state of some application variable or other data source.

Unicode Glyphs

The simplest way to add an iconic view to the menulet is by using a Unicode character for the title. This has several benefits, such as not requiring the design, creating, and loading of an image. Also, when a user clicks on a menulet and it becomes highlighted, the icon should have an 'inverse' view that inverts the colors of the icon in some way to alert the user that the menulet has been clicked. The title of a status item, and therefore a symbolic glyph, is automatically inverted.

Finding a good glyph (symbol) is a bit tricky. In the end, we need the hex value for a Unicode character. Mac OS X provides a very nice tool for looking at Unicode characters, though it is a bit buried.

Go to System Preferences, International and check Character Palette. After you do this you will see your current input language flag in the menubar (look, another menulet!). Click on the flag and choose Show Character Palette. The character palette window pane will pop-up and sit above all of your other windows. At the top of the pane, there is View: and a drop menu. Click on the drop menu and choose Code Tables. You can now navigate through all of the Unicode characters. When you find a glyph that you want to use, click on it and then get the Unicode: value next to the zoomed in view of the character.

Figure 3: The Character Palette is a very useful tool for finding glyphs and their associated Unicode hex values.

Now armed with a Unicode value, return to the IPMenulet.m file and replace the

[statusItem setTitle:[NSString 

with a formatted string using one (or many) hex values the formatter is %C. Therefore, the following code will produce the ??symbol:

[statusItem setTitle:[NSString 

Image Icons

While using a built in glyph is very simple, it does not offer the flexibility an icon provides. The NSStatusItem API provides the setImage:(NSImage*) function to set the icon. The following code obtains a 22x22 pixel image that has been added to the project resources, which is then stored and set to the status items image. You can use any small icon in your project that you want. For purposes of this example, the icon is "IPMenuIcon.tif".

First, add a pointer to an NSImage to the data members of the IPMenulet class.


NSImage *menuIcon;

Then we need to get the bundle, the path, and finally the image at this path. We will store this image for future reference if we want to show or hide the icon depending on the menulet's state. We also set the title to an empty string although it is allowed to have both an image and text in the status item. Make sure to release the icon when the application quits.

IPMenulet.m (awakeFromNib:)

NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *path = [bundle pathForResource:@"IPMenuIcon" ofType:@"tif"];
menuIcon= [[NSImage alloc] initWithContentsOfFile:path];

[statusItem setTitle:[NSString stringWithString:@""]]; 
[statusItem setImage:menuIcon];

[menuIcon release];

Test this new version. You should see the icon in the header. When the icon is clicked, the IP address is filled in to the right of the icon as shown in Figure 4.

Figure 4: The Menulet with both an icon and text title.

Adding a Menu

The menulet has shaped up rather nicely, but is limited to a single line of information and a single action when clicking. It is possible to extend the menulet by adding a menu to provide more information and interaction with user such as bringing up "About" boxes, "Preferences...", or displaying the IP address in the menu and keeping the menulet itself to a single icon.

First we will modify our code to include the pointer to the menu and a menu item we will be creating by adding the following to the IPMenulet interface definition.


IBOutlet NSMenu *theMenu;
NSMenuItem *ipMenuItem;

Now we need to build the actual menu. Double-click the MainMenu.nib file to bring up Interface Builder. The first thing to do is to update Interface Builder's knowledge of the IPMenulet class. We need to double click the IPMenulet instantiation, right-click and choose "Read IPMenulet.h". After this is complete, return to the "Instances" tab.

Choose the "Cocoa-Menus" tab from the Interface Builder palette. Drag and drop the menu icon in the lower-right corner to the MainMenu.nib panel. This will add an NSMenu1 item to our nib file. Rename the first item "External IP" and delete the second menu item.

Next we connect the menu to our class. Control left-click and drag from the IPMenulet instantiation to the new NSMenu1 and connect theMenu data member of the class.

We assigned the menu to the class, but now the menu now needs to be assigned to IPMenulet. Return to XCode and modify the IPMenulet.m file to use theMenu instead of calling the updateIPAddress: selector. We're also going to dynamically create a menu item that is the external IP address and set it to update the IP address when the user clicks it.

IPMenulet.m (awakeFromNib:)

[statusItem setMenu:theMenu];
ipMenuItem = [[NSMenuItem alloc] initWithTitle:@"" 
      action:@selector(updateIPAddress:) keyEquivalent:@""];
[ipMenuItem setTarget:self];
[theMenu insertItem:ipMenuItem atIndex:1];

The menulet will know to call and expand the menu on a user click. Therefore, comment out:

//  [statusItem setAction:@selector(updateIPAddress:)];
//  [statusItem setTarget:self];

We also want to update the IP address menu item with the new IP address. This is a simple change, instead of setting the title of the statusItem, we want to change the title of the ipMenuItem.

IPMenulet.m (updateIPAddres:)

[statusItem setTitle:[NSString stringWithString:ipAddr]];


[ipMenuItem setTitle:[NSString stringWithString:ipAddr]];

Click "Build and Go" again to see the newest results. You will only see the icon in the menubar. Click on this to expand down your new menu. Click on the IP Address to have it update and change the menu item.

Figure 5: The menulet with a drop-down menu.

Automatic Updating

To this point we have made a menulet that has either an icon or text in the status bar, and updates the IP address when the user interacts with the menu item. By contrast, most menulets provide the user information without requiring interaction from the user. Therefore, it is often useful to use a timer to automatically update the menulet. This allows the menulet to provide up to date information without requiring constant interaction from a user.

This example hardcodes the timer interval to a predetermined value that seems adequate for the task, 1000 seconds. However, it would be useful for more advanced menulets to include a preference pane or selectable menu items for setting a variable update rate.

Add the following sections of code to your source files:


NSTimer *updateTimer;
IPMenulet.m (awakeFromNib:)

updateTimer = [[NSTimer 
               repeats:YES] retain];
[updateTimer fire];

[updateTimer release];

The timer is built with 1000 second delay, and when it 'fires' (timer runs out), it will call our updateIPAddress: selector. The timer will continue firing for as long as the application remains active (repeats is set to YES).

Build and run the updated application. The IP address will be updated immediately upon startup. It will then be updated every 1000 seconds. If you want to double-check your timer, change the timer interval to 10.0, and add

[statusItem setTitle:[NSString 

to the beginning of the updateIPAddress: function. At the end of the function, add:

[statusItem setTitle:[NSString 

These additions will cause the menu to print "Updating" in the menu bar while retrieving the external IP address.


You've now successfully developed several iterations of a Mac OS X menulet. Each variation has different uses, depending on the desired information to be displayed, and user interaction required. Furthermore, menulets as described here can be made either stand-alone or as part of a larger application. In a larger application, the menulet's selectors and menu items would be connected to the application's code and data. This type of interface provides users with a potentially useful resource for quickly gleaning information from your application.

Menulets also provide an interface for drawing to an NSView. This capability allows a developer limitless freedom in drawing icons, graphs, blinken-lights, or anything else in their menulet.

For more information on the NSStatusItem API, check out the Apple developer documentation: ApplicationKit/ObjC_classic/Classes/NSStatusItem.html

Andrew Turner is a Systems Development Engineer with Realtime Technologies, Inc ( and has built robotic airships, automated his house, designed spacecraft, and in general looks for any excuse to hack together cool technology. You can read more about his projects at


Community Search:
MacTech Search:

Software Updates via MacUpdate

BetterTouchTool 2.417 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
Mellel 4.1.0 - The word processor for sc...
Mellel is the leading word processor for OS X and has been widely considered the industry standard for long form documents since its inception. Mellel focuses on writers and scholars for technical... Read more
ScreenFlow 7.3 - Create screen recording...
ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your entire monitor while also capturing your video camera, microphone and your... Read more
Dashlane 5.9.0 - Password manager and se...
Dashlane is an award-winning service that revolutionizes the online experience by replacing the drudgery of everyday transactional processes with convenient, automated simplicity - in other words,... Read more
ForkLift 3.2 - Powerful file manager: FT...
ForkLift is a powerful file manager and ferociously fast FTP client clothed in a clean and versatile UI that offers the combination of absolute simplicity and raw power expected from a well-executed... Read more
Cocktail 11.5 - General maintenance and...
Cocktail is a general purpose utility for macOS that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
Hazel 4.2.4 - Create rules for organizin...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a familiar... Read more
Skype - Voice-over-internet pho...
Skype allows you to talk to friends, family, and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more
Backup and Sync 3.40.8921.5350 - File ba...
Backup and Sync (was Google Drive) is a place where you can create, share, collaborate, and keep all of your stuff. Whether you're working with a friend on a joint research project, planning a... Read more
Dashlane 5.9.0 - Password manager and se...
Dashlane is an award-winning service that revolutionizes the online experience by replacing the drudgery of everyday transactional processes with convenient, automated simplicity - in other words,... Read more

Latest Forum Discussions

See All

Destiny meets its mobile match - Everyth...
Shadowgun Legends is the latest game in the Shadowgun series, and it's taking the franchise in some interesting new directions. Which is good news. The even better news is that it's coming out tomorrow, so if you didn't make it into the beta you... | Read more »
How PUBG, Fortnite, and the battle royal...
The history of the battle royale genre isn't a long one. While the nascent parts of the experience have existed ever since players first started killing one another online, it's really only in the past six years that the genre has coalesced into... | Read more »
Around the Empire: What have you missed...
Oh hi nice reader, and thanks for popping in to check out our weekly round-up of all the stuff that you might have missed across the Steel Media network. Yeah, that's right, it's a big ol' network. Obviously 148Apps is the best, but there are some... | Read more »
All the best games on sale for iPhone an...
It might not have been the greatest week for new releases on the App Store, but don't let that get you down, because there are some truly incredible games on sale for iPhone and iPad right now. Seriously, you could buy anything on this list and I... | Read more »
Everything You Need to Know About The Fo...
In just over a week, Epic Games has made a flurry of announcements. First, they revealed that Fortnite—their ultra-popular PUBG competitor—is coming to mobile. This was followed by brief sign-up period for interested beta testers before sending out... | Read more »
The best games that came out for iPhone...
It's not been the best week for games on the App Store. There are a few decent ones here and there, but nothing that's really going to make you throw down what you're doing and run to the nearest WiFi hotspot in order to download it. That's not to... | Read more »
Death Coming (Games)
Death Coming Device: iOS Universal Category: Games Price: $1.99, Version: (iTunes) Description: --- Background Story ---You Died. Pure and simple, but death was not the end. You have become an agent of Death: a... | Read more »
Hints, tips, and tricks for Empires and...
Empires and Puzzles is a slick match-stuff RPG that mixes in a bunch of city-building aspects to keep things fresh. And it's currently the Game of the Day over on the App Store. So, if you're picking it up for the first time today, we thought it'd... | Read more »
What You Need to Know About Sam Barlow’s...
Sam Barlow’s follow up to Her Story is #WarGames, an interactive video series that reimagines the 1983 film WarGames in a more present day context. It’s not exactly a game, but it’s definitely still interesting. Here are the top things you should... | Read more »
Pixel Plex Guide - How to Build Better T...
Pixel Plex is the latest city builder that has come to the App Store, and it takes a pretty different tact than the ones that came before it. Instead of being in charge of your own city by yourself, you have to work together with other players to... | Read more »

Price Scanner via

Back in stock! Apple’s full line of Certified...
Save $300-$300 on the purchase of a 2017 13″ MacBook Pro today with Certified Refurbished models at Apple. Apple’s refurbished prices are the lowest available for each model from any reseller. A... Read more
Back in stock: 13-inch 2.5GHz MacBook Pro (Ce...
Apple has Certified Refurbished 13″ 2.5GHz MacBook Pros (MD101LL/A) available for $829, or $270 off original MSRP. Apple’s one-year warranty is standard, and shipping is free: – 13″ 2.5GHz MacBook... Read more
Apple restocks Certified Refurbished 2017 13″...
Apple has Certified Refurbished 2017 13″ MacBook Airs available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: – 13″ 1.8GHz/8GB/128GB MacBook Air (... Read more
8-Core iMac Pro on sale for $4699, save $300
Amazon has the 8-core iMac Pro on sale for $4699 including free shipping. Their price is $300 off MSRP, and it’s the currently lowest price available for an iMac Pro. For the latest up-to-date prices... Read more
10″ 512GB WiFi iPad Pros on sale for $849, sa...
B&H Photo has Space Gray and Rose Gold 10.5″ 512GB WiFi iPad Pros on sale for $849. Their price is $150 off MSRP, and it’s the lowest price available for these models, new, from any Apple... Read more
MacBook Pro sale! B&H drops prices on new...
B&H Photo has dropped prices on new 2017 13″ MacBook Pros, with models now on sale for up to $200 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only. Their... Read more
13″ MacBook Airs on sale for $100-$150 off MS...
B&H Photo has 13″ MacBook Airs on sale for $100-$150 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $899, $... Read more
Huge iMac sale! Apple reseller now offering 2...
B&H Photo has new 2017 21″ & 27″ iMacs on sale today for up to $300 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 27″ 3.8GHz iMac (MNED2LL/A): $... Read more
Sale! 1.4GHz Mac mini for $399, $100 off MSRP
B&H Photo has the 1.4GHz Mac mini on sale for $399 for a limited time. Their price is $100 off MSRP, and it’s the lowest price available for a mini from any Apple reseller: – 1.4GHz Mac mini (... Read more
Sale of the year continues as Apple resellers...
Adorama has new 2017 15″ MacBook Pros on sale for $250-$300 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 15″ 2.8GHz Touch Bar MacBook Pro Space Gray (MPTR2LL/A): $... Read more

Jobs Board

*Apple* Retail Sales Associate / Service Wri...
Job DescriptioniStore is the premier retailer of Apple products and solutions. We're looking for dedicated individuals with a passion to simplify and enhance the Read more
Integration Technician, *Apple* - Zones, In...
…adapted, and grown for over 30 years. Position Overview The Apple Integration Technician will be responsible for performing customer specific configuration Read more
*Apple* Retail - Multiple Positions - Apple,...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Part Time Reseller Specialist - *Ap...
…in a reseller store, you help create the energy and excitement around Apple products, providing the right solutions and getting products into customers' hands. You Read more
*Apple* Technical Specialist - Apple, Inc. (...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.