Programming a Menu Bar Button


The goal of this tutorial is to teach you how to create an icon in the menu bar for your application, which when pressed, activates the main application window. An example of this can be seen in the Iconfactory’s Twitterrific. The main class you will be exploring in this tutorial is NSStatusItem. Apple’s documentation for the NSStatusItem class can be found here.

Before we go on, I’d like to note that this simple usage of a menubar icon severely violates the Apple Human Interface Guidelines. The menubar of the system should not ever be used like the system tray is in Windows. A menubar icon should perform more actions than simply showing/hiding an app’s window, and cluttering up the menubar with an icon for every application makes no sense whatsoever. Notice the dock at the bottom of your screen:  that’s why it is there.

Step 1. Open XCode.app and create a new project. For now, let’s stick with simplicity and choose “Cocoa Application.” Name the project “AwesomeMenubarButton,” and go on to the next step.

Step 2. We’re going to need to set up the project with a controller. Create a new Objective-C class and call it “AppController.”

Step 3. Next we’ll need to add outlets for all of the needed UI components. In the case of this project, we’re only going to need on outlet:  the main window that we’re going to be hiding and showing. Add the following code in the @interface section of AppController.h:

IBOutlet NSWindow *mainWindow;

Step 4. There are two different actions that the menubar button will be performing:  showing the window, and hiding it. For simplicity, we can simplify these two actions into one method that “toggles” the visibility of the window. Directly under the @interface section in AppController.h, add the following code:

- (void)toggleVisibilityOfMainWindow:(id)sender;

And let’s add the window toggling code in AppController.m:

- (void)toggleVisibilityOfMainWindow:(id)sender {
if ([mainWindow isVisible]) {
[mainWindow orderOut:nil];
return;
}
[mainWindow makeKeyAndOrderFront:nil];
}

Save both files and lets move on.

Step 5. Open MainMenu.xib in Interface Builder and select File: Read Class Files. Browse to the AppController.h file that we created, and open it. Add a new blank NSObject from the library into your document, and go into the Identity tab of the inspector. Set the object’s Class to “AppController.” The name of the object should now change in the document window.

Step 6. Make sure you still have the App Controller object selected, and go into the Connections inspector. Drag a connection from the mainWindow outlet to the only window in the xib file. Save and close!

Step 7. Here is where it starts to get tricky. NSStatusItem, the class that we’re going to use to make the menubar icon/button cannot be added in Interface Builder:  we have to create it via code. Go back to AppController.m and add the following method implementation:

NSStatusItem *statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];<br />
[statusItem setTitle:@"A"];<br />
// Uncomment this area and fill in the name of your image<br />
// to add a custom icon to your status item.<br />
//[statusItem setImage:[NSImage imageNamed:@"Icon"]];<br />
[statusItem setEnabled:YES];<br />
[statusItem setHighlightMode:YES];<br />
[statusItem setTarget:self]; //This sets the AppController as the receiver of all sent actions.<br />
[statusItem setAction:@selector(toggleVisibilityOfMainWindow:)]; //This tells the status item to call our toggle method when clicked.

You’re all done! Build and Go, and the menu item will appear and when pressed, it will toggle the visibility of the main window.

Related posts:

  1. Understanding Object-Oriented Programming and the MVC System Introduction Before you begin to learn the basic syntax...
  2. Basic C Programming In This tutorial, we will look at the basic principles...

20 Responses

06.25.09

This Is Brilliant! Works really well with my App. Is there anyway to make the App active if it’s not active when you click the menu bar button to show the window? Because if it’s not active the window becomes visible but in the background. Thanks Again!

06.25.09

This line of code should work, though I haven’t tested it:

[NSApplication activateIgnoringOtherApps:YES];

Try it, see if it works.

06.25.09

Awesome tutorial Carter!

06.25.09

Thanks, Where would I put the code though?

06.25.09

Directly under the makeKeyAndOrderFront: line in the first method.

06.25.09

I have pasted it there but it doesn’t seem to work, probably because of this error. Snap Of Error : http://snapplr.com/eyjy

06.25.09
06.25.09

Thanks It works perfectly now! However I have one more question, Is it possible to make the window appear in front even though it’s already open instead of closing it and only close/hide the window when the app is active (for example like Tweetie)?

06.25.09

I’m sure there is.

06.25.09

I see, Would you happen to know how?

06.25.09

Yes.

06.25.09

Could you tell me how by giving me the code?

06.25.09

Are you able to give me some code to do that?

06.25.09

Yes. I am.

06.25.09

Could you give me the code (actually give me it in your next post if you say yes)?

06.25.09

Joshua: The reason Carter isn’t giving you the code to do it is because a monkey that’s borderline retarded could easily do it by just reading the code.

- (void)toggleVisibilityOfMainWindow:(id)sender {
[mainWindow makeKeyAndOrderFront:nil];
}

Obviously, all I took out was the if statement that said if the window was already visible, close it.

06.25.09

Well He Could Of Just Said That, instead of letting you make a offensive comment.

06.25.09

Also, that code doesn’t work. So your not as smart as you think you are. :P

06.25.09

Perhaps I understood your question incorrectly.

06.25.09

Yeh, thanks for the help anyway.

Leave Your Response

* Name, Email, Comment are Required