The Coding Journal ツ

Home

Impressum

x3ro’s Toolkit

This is short tutorial on how to use Cocoa’s NSTrackingArea to get a hold of useful mouse events such as mouseEntered and mouseExited , so lets jump right into it.

We’ll be starting off with an NSView -subclass, such as the following (which is identical to the ones Xcode automatically creates):

And the corresponding header:

First of all, we are going to implement drawRect to fill the view with a color, so we can see what we are doing:

This code is pretty self-explanatory, at least if you’ve already done some drawing in Cocoa at all. If you haven’t you should check out the Introduction to Cocoa Drawing .

There is a nifty little method called updateTrackingAreas in NSView, which is invoked automatically whenever the view’s geometry changes in a way that its tracking areas need to be updated. Sounds like what we need, so lets implement it. First of all, we will need to create the NSTrackingArea instance:

The first parameter, an NSRect , specifies the actual area to be tracked. I use [self bounds] instead of [self frame] here, because the latter is in the superview’s coordinate system, which is probably not what you want (if you are unfamiliar with the difference between a view’s frame and bounds, look into the View Programming Guide ).

The second parameter ( options ) specifies various aspects of the tracking area behavior. In our case we want to get notified whenever the mouse enters or leaves our NSTrackingArea ( NSTrackingMouseEnteredAndExited ), and the tracking should be active even if our window is not focused ( NSTrackingActiveAlways ). For more options just take a look at the NSTrackingArea Class Reference .

The third parameter ( owner ) specifies where the event messages should be sent to, in our case it is our example view which we reference with self .

The fourth and last parameter can specify some extra data which will be passed with every event (except for mouse move events, probably because of the frequency in which they are triggered), but we don’t need this feature now, so we can just pass nil .

Now we want to add the NSTrackingArea to our NSView :

Note that an NSView can have multiple tracking areas and you cannot update the old ones, so if you need to update a tracking area, remove the old one and just add a new one!

So before creating a new tracking area, we will want to check if one already exists, and if thats the case, remove it:

Don’t forget to release your old tracking areas, or you’ll end up with a nice memory leak ;) Now lets stuff all that code into our updateTrackingAreas method:

To see if our previously written code works, we also need the respective mouse events, that is, mouseEntered and mouseExited :

Those are small and simple, whenever the mouse enters our view we want to increase the view’s size by 100, and when we leave we reduce it again. The code for resizeFrameBy is the following:

Thats it already. All we need to do now is create an instance of the view and add it somewhere, and see the NSTrackingArea magic do its job. I did this directly inside the applicationDidFinishLaunching method of the app delegate:

For the full, runnable source code check out the tutorial repository on GitHub.

This is short tutorial on how to use Cocoa’s NSTrackingArea to get a hold of useful mouse events such as mouseEntered and mouseExited, so lets jump right into it. We’ll...

Wouter on September 11, 2012 at 3:45 pm said: Great, thanks. One addition: I think you need to add if (trackingArea != nil) [trackingArea release]; in the dealloc to prevent a memory leak. Reply ↓ Lucas on September 11, 2012 at 3:49 pm said: Do you mean a different dealloc than this one: https://github.com/CodingJournal/NSTrackingArea-Tutorial/blob/master/NSTrackingAreaTutorial/CJTutorialView.m#L51 ? :) Or should I just add a note to the blog post so people don’t forget about it? Reply ↓

Great, thanks. One addition: I think you need to add if (trackingArea != nil) [trackingArea release]; in the dealloc to prevent a memory leak.

Lucas on September 11, 2012 at 3:49 pm said: Do you mean a different dealloc than this one: https://github.com/CodingJournal/NSTrackingArea-Tutorial/blob/master/NSTrackingAreaTutorial/CJTutorialView.m#L51 ? :) Or should I just add a note to the blog post so people don’t forget about it? Reply ↓

Do you mean a different dealloc than this one: https://github.com/CodingJournal/NSTrackingArea-Tutorial/blob/master/NSTrackingAreaTutorial/CJTutorialView.m#L51 ? :) Or should I just add a note to the blog post so people don’t forget about it?

Whitney on June 2, 2013 at 9:05 pm said: Good tutorial, thank you. I had to call NSRectFromCGRect() in the “resizeFrameBy” implementation: [[self animator] setFrame:NSRectFromCGRect(CGRectMake(frame.origin.x, frame.origin.y, frame.size.width + value, frame.size.height ))]; Reply ↓

Good tutorial, thank you.

I had to call NSRectFromCGRect() in the “resizeFrameBy” implementation:

[[self animator] setFrame:NSRectFromCGRect(CGRectMake(frame.origin.x, frame.origin.y, frame.size.width + value, frame.size.height ))];

Your email address will not be published. Required fields are marked *

Name *

Email *

Website

Comment

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>