-hitTestForEvent:inRect:ofView
用于触发动作是完全错误的方法。您应该使用-trackMouse:inRect:ofView:untilMouseUp:
,或 -startTrackingAt:inView:
, -continueTracking:at:inView:
and -stopTracking:at:inView:mouseIsUp:
。
重要提示:如果您在 中实现自己的鼠标跟踪循环-trackMouse:inRect:ofView:untilMouseUp:
,您应该在某处记录这一事实,因为一般来说,它会排除其他三种方法的使用。AppKit 框架中的一些NSCell
子类会这样做,但没有记录他们已经这样做了(结果你会思考几个小时为什么它-startTrackingAt:inView:
永远不会被调用)。
您如何实现自己的跟踪循环?像这样:
- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame
ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp
{
NSPoint pos = [controlView convertPoint:[theEvent locationInWindow]
fromView:nil];
if ([theEvent type] == NSLeftMouseDown && NSPointInRect (pos, myClickRect)) {
NSWindow *window = [controlView window];
NSEvent *myEvent;
NSDate *endDate = [NSDate distantFuture];
while ((myEvent = [window nextEventMatchingMask:(NSLeftMouseDragged
|NSLeftMouseUp)
untilDate:endDate
inMode:NSEventTrackingRunLoopMode
dequeue:YES])) {
if ([myEvent type] != NSLeftMouseUp)
continue;
pos = [controlView convertPoint:[theEvent locationInWindow]
fromView:nil];
if (NSPointInRect (pos, myClickRect)) {
// React somehow
}
return YES;
}
}
return [super trackMouse:theEvent inRect:cellFrame ofView:controlView
untilMouseUp:untilMouseUp];
}
(The above code was just typed in here, so the usual caveats apply; it assumes the existence of an NSRect
called myClickRect
that defines the active area of your cell. You might need to calculate that from cellFrame
at the head of the method.)
Obviously you can watch for and handle other events too, if they are relevant to you.
Perhaps I should also add that the three method approach, while conceptually cleaner, tends to be quite a bit slower, which generally leads me to prefer overriding -trackMouse:inRect:ofView:untilMouseUp:
as shown above.