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

问题描述 投票:0回答:2


我有一个透明的

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
时,我该怎么做才能知道?
谢谢你

objective-c xcode macos transparent nswindow
2个回答
4
投票

这是在需要定义事件后接收定义事件以开始操作的典型情况。 具体来说,直到拖动开始之后,您才能知道 mouseDown 是否是拖动的开始。 但是,如果拖动未开始,您希望对 mouseDown 执行操作。

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

在 OS X 上,我们没有很多系统来帮助解决此问题,因此,如果您有需要以不同方式处理单击和拖动的操作,则需要推迟下一个操作,直到过了保护时间,并且如果通过,您可以执行原始操作。 在这种情况下,您可能需要执行以下操作:

mouseDown
中,开始
NSTimer
设置适当的保护时间(不要太长,以免人们意外移动指针,也不要太短,以免在用户拖动之前触发),以便给您回电稍后触发弹出窗口。

mouseDragged
中,使用保护区来确保如果用户只是轻微抽搐,则不会算作拖动。 这可能会令人恼火,因为有时会导致需要将某些东西拖动得比开始拖动所需的距离更远,因此您需要在某处找到一个魔法常数,或者进行一些实验。 当超出警戒区域时,然后通过用
NSTimer
取消
[timer invalidate]
来开始合法的拖动操作,然后进行拖动。

在计时器的回调中,显示您的弹出窗口。 如果用户拖动,

NSTimer
将失效,导致它不会触发,因此不会显示弹出窗口。


0
投票

您可以检查 onMouseUp() 是否有“快速点击” - 即,如果自上次 onMouseDown() 以来鼠标位置没有移动,则为快速点击,否则为拖动。

#import <Cocoa/Cocoa.h>
#define QUICK_TAP_THRESHOLD 1.0

@interface DraggableWindow : NSWindow
@property (nonatomic) NSPoint initialLocation;
@property (nonatomic, strong) NSDate *mouseDownTime;

@property (nonatomic, copy) void (^onQuickTap)(void);
@end

@implementation DraggableWindow

- (void)mouseDown:(NSEvent *)event {
    self.initialLocation = event.locationInWindow;
    self.mouseDownTime = [NSDate date];
}

- (void)mouseDragged:(NSEvent *)event {
   // your custom logic here..
}

- (void)mouseUp:(NSEvent *)event {
    NSPoint currentLocation = event.locationInWindow;
    NSPoint tempInitialLocation = self.initialLocation;
    self.initialLocation = NSZeroPoint;
    NSDate *tempMouseDownTime = self.mouseDownTime;
    self.mouseDownTime = nil;

    if ([[NSDate date] timeIntervalSinceDate:tempMouseDownTime] < QUICK_TAP_THRESHOLD) {
        if (NSEqualPoints(currentLocation, tempInitialLocation)) {
            if (self.onQuickTap) {
                self.onQuickTap();
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.