Chapter 18. Tracking the Mouse

We’re in the home stretch! In this and the following three chapters, we’re going to fill in many of the standard Mac OS X features that you need to know in order to write commercial-level Cocoa applications.

Tracking the Mouse

Today’s users are so demanding! A few years ago you could write an application that would just sit there and wait for you to click a mouse button or press a key, but these days users expect your application to be always prepared to respond. When a user moves the mouse over something in an application’s window, if there is some way that your application can possibly convey information, the user expects it to happen.

What kind of information are we talking about? For example, if a user mouses over (i.e., lets the cursor hover over) the toolbar icons in the Mail application or the Colors panel, he will expect to get feedback about what clicking those icons will do. This is an example of Cocoa tool tips — something that is so simple to set with Interface Builder that we haven’t even bothered showing you how to do it. Can we arrange for even more sophisticated mouseover behavior within GraphPaper? Of course we can, and in this chapter we’ll show you how!

Tracking Rectangles

Until now, we’ve thought of Cocoa events as being in two categories: mouse events and keyboard events (although there are periodic and other types of events as well). Another way of classifying events is according to the type of programmatic gyrations that you have to go through in order to receive them.

The simplest events to program are those that require no setup; you merely subclass NSView and implement the corresponding event methods to receive the events. Some of the methods that handle these simple events are:

- mouseDown:(NSEvent *)theEvent
- mouseUp:(NSEvent *)theEvent
- mouseDragged:(NSEvent *)theEvent
- rightMouseDown:(NSEvent *)theEvent
- rightMouseUp:(NSEvent *)theEvent
- rightMouseDragged:(NSEvent *)theEvent

A second group of mouse events involves the responder chain. Usually, your NSView subclass receives these events by making itself a first responder. This can happen automatically if the user clicks the mouse in your NSView and your NSView responds YES to the acceptsFirstResponder: message. The responder-chain events include keyboard events as well as events that have to deal with simple mouse motion. Some of the methods that handle these first responder events are:

- keyDown:(NSEvent *)theEvent
- keyUp:(NSEvent *)theEvent
- flagsChanged:(NSEvent *)theEvent

The last group of events has to do with tracking rectangles , rectangular regions within windows that track the mouse cursor. You can arrange to have messages sent to an object whenever a tracking rectangle is entered or exited (no click) by the mouse. Some of the methods that handle these tracking events are:

- mouseMoved:(NSEvent *)theEvent
- mouseEntered:(NSEvent *)theEvent
- mouseExited:(NSEvent *)theEvent

To set up a tracking rectangle, send the addTrackingRect:owner:userData:assumeInside: message to an NSWindow object:

- (NSTrackingRectTag)addTrackingRect:(NSRect)aRect
                               owner:(id)anObject
                            userData:(void *)userData
                        assumeInside:(BOOL)insideFlag

These arguments are described in Table 18-1.

Table 18-1. Method arguments of NSTrackingRectTag

Argument

Meaning

addTrackingRect:

A pointer to the tracking rectangle in the NSWindow’s coordinate system. The tracking rectangle does not change if the NSWindow is resized.

owner:

The object that will be sent mouseEntered: and mouseExited: messages when the mouse moves in or out of the tracking rectangle. Normally the owner will be the NSView itself, but it can be any object that responds to mouseEntered: and mouseExited: messages.

userData:

Data that is provided in the NSEvent object with the mouseEntered: or mouseExited: events.

assumeInside:

Set this flag to indicate whether you think the mouse cursor is initially inside or outside the tracking rectangle. If this flag is NO, the mouseEntered: event will be sent the first time the cursor moves into the tracking rectangle. If this flag is YES, the first tracking event sent will be a mouseExited: event, when the cursor leaves the tracking rectangle.

Tracking rectangles are actually handled by windows, not by views. Unfortunately, you normally want to manage and use tracking rectangles from within views. Cocoa meets you halfway in this pursuit — for example, tracking rectangles are created by sending messages to NSViews. Nevertheless, the fact that tracking rectangles are managed by windows results in some weirdness:

  • If you change your NSView’s frame, you need to remove the old tracking rectangle and create a new one.

  • An NSView receives mouseMoved: events only when it is the NSWindow’s first responder.

  • There is no default tracking rectangle. If you don’t set a tracking rectangle, you won’t get mouseEntered: and mouseExited: events.

If your only reason for using a tracking rectangle is to give your NSView subclass a custom cursor, don’t use a tracking rectangle; use NSView’s addCursorRect:cursor: method instead.

Accepting Mouse-Moved Events

Each window maintains an internal flag called acceptsMouseMovedEvents that determines whether the Window Server will send it mouse-moved events. The reason for this, once again, is efficiency — most applications simply don’t need to know every time the mouse moves. The default, therefore, is not to send these events. If you set the acceptsMouseMovedEvents flag, you’ll get the events regardless of whether your application is the active application. That’s useful, but it can slow down your entire computer, so be judicious in your use of mouse-moved events.

To receive mouse-moved events from an NSWindow object called aWindow, send aWindow the following message:

[aWindow setAcceptsMouseMovedEvents:YES]

When you don’t need these events anymore, send the following message:

[aWindow setAcceptsMouseMovedEvents:NO]
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.222.239