如何在Transparent NSWindow中区分mouseDown事件和mouseDragged

时间:2012-06-04 20:42:02

标签: objective-c xcode macos transparent nswindow


我有一个透明NSWindow,其中有一个简单的图标,可以在屏幕上拖动 我的代码是:
.H:

@interface CustomView : NSWindow{
}

@property (assign) NSPoint initialLocation;

的.m

@synthesize initialLocation;

- (id) initWithContentRect: (NSRect) contentRect
                 styleMask: (NSUInteger) aStyle
                   backing: (NSBackingStoreType) bufferingType
                     defer: (BOOL) flag{
    if (![super initWithContentRect: contentRect 
                          styleMask: NSBorderlessWindowMask 
                            backing: bufferingType 
                              defer: flag]) return nil;
    [self setBackgroundColor: [NSColor clearColor]];
    [self setOpaque:NO];
    [NSApp activateIgnoringOtherApps:YES];
    return self;
}

- (void)mouseDragged:(NSEvent *)theEvent {
    NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame];
    NSRect windowFrame = [self frame];
    NSPoint newOrigin = windowFrame.origin;

    // Get the mouse location in window coordinates.
    NSPoint currentLocation = [theEvent locationInWindow];
    // Update the origin with the difference between the new mouse location and the old mouse location.
    newOrigin.x += (currentLocation.x - initialLocation.x);
    newOrigin.y += (currentLocation.y - initialLocation.y);

    // Don't let window get dragged up under the menu bar
    if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height)) {
        newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height);
    }

    // Move the window to the new location
    [self setFrameOrigin:newOrigin];
}

- (void)mouseDown:(NSEvent *)theEvent {    
    // Get the mouse location in window coordinates.
    self.initialLocation = [theEvent locationInWindow];
}

我想在用户点击透明窗口的图片时显示NSPopover。但是,正如您在代码中看到的那样,mouseDown事件用于获取鼠标位置(上面的代码来自一个示例)。
如果用户点击图标只是拖动图标或只是点击图标以显示NSPopover,我该怎么办? 谢谢

1 个答案:

答案 0 :(得分:2)

这是在您需要它之后接收定义事件以开始操作的经典情况。具体来说,在拖动开始之前,您无法知道mouseDown是否是拖动的开始。但是,如果拖动没有开始,您希望对该mouseDown采取行动。

在iOS中(我意识到这与代码没有直接关系,但它是指导性的),有一个完整的API围绕让iOS尝试为您做出这些决定。整个Gesture系统基于这样的想法:用户开始做一些可能是许多不同操作之一的事情,因此需要随着时间的推移解决,可能导致在跟踪期间取消操作。

在OS X上,我们没有很多系统可以帮助解决这个问题,所以如果你需要处理点击和差异拖动的东西,你需要推迟你的下一个动作,直到保护时间过去,如果通过,您可以执行原始操作。在这种情况下,您可能希望执行以下操作:

mouseDown中,开始NSTimer设置适当的保护时间(不会太久以至于人们会不小心移动指针,而不是那么短,以至于在用户拖动之前你会触发)为了稍后再回电话来触发弹出窗口。

mouseDragged中,使用保护区域以确保如果用户稍微抽搐一下,则不会将其视为拖拽。这可能会令人恼火,因为它有时会导致为了开始拖动而需要拖动比看起来更远的东西,因此您需要在某处找到魔法常量,或者进行一些实验。超过警戒区域后,通过使用NSTimer取消[timer invalidate]并开始拖动来开始合法的拖动操作。

在计时器的回调中,显示你的弹出窗口。如果拖动用户,NSTimer将失效,导致它不会触发,因此弹出窗口不会显示。