检测鼠标按下状态

3

我想要检测鼠标按下而非点击的事件。以下是我的代码,但我希望能够检测到鼠标按下而不是点击次数。

-(void)mouseDown:(NSEvent *)event;
{
    //instead of clickCount I want my if statement to be 
    // if the mouse is being held down.
    if ([event clickCount] < 1) 
    {

    }
    else if ([event clickCount] > 1)
    {

    }
}

当用户点击并按住时,该事件不会触发吗? - millimoose
mouseDown 事件发生时,计算机无法预测用户是否会继续按住鼠标按钮。通常,为了实现拖放功能,你只需要在 mouseDown 事件中找出正在被拖动的内容,在 mouseUp 事件中像 Kristian 所述一样观察并确定物品被放置的位置,并处理 mouseMoved(或其他名称)事件(检查 mouseIsHeldDown)以查看是否正在拖动某些内容。 - Mike DeSimone
另一种选择是在 mouseDown 中设置某种类型的延迟回调。如果鼠标释放,则清除回调,如果回调触发,则鼠标按钮至少按下了该时间量。这类似于键盘重复工作原理。 - Mike DeSimone
@Mike:-1个答案已经作为评论发布了 :) - jscs
@Iulius:我将其发布为评论,因为我觉得它不够完整,不能作为答案。此外,我对Obj-C也不太熟悉。 - Mike DeSimone
@Mike:我只是觉得有趣,你的评论涵盖了答案中的两种可能性。 - jscs
3个回答

11

从OS X 10.6开始,您可以在任何地方使用NSEventpressedMouseButtons方法:

NSUInteger mouseButtonMask = [NSEvent pressedMouseButtons];
BOOL leftMouseButtonDown = (mouseButtonMask & (1 << 0)) != 0;
BOOL rightMouseButtonDown = (mouseButtonMask & (1 << 1)) != 0;
方法返回当前按下的鼠标按钮的索引掩码。1 << 0 对应左键,1 << 1 对应右键,1 << n,n >= 2对应其他鼠标按钮。使用这个方法时不需要捕获mouseDown:mouseDragged:mouseUp:事件。

5

您可能想要检测鼠标是否被按住了一段时间。这很简单,只需要一个计时器。

mouseDown:中,启动一个定时器,在您选择的时间之后触发。您需要将其放入ivar中,因为您还需要在mouseUp:中引用它。

- (void)mouseDown: (NSEvent *)theEvent {
    mouseTimer = [NSTimer scheduledTimerWithTimeInterval:mouseHeldDelay
                                                  target:self
                                                selector:@selector(mouseWasHeld:)
                                                userInfo:theEvent
                                                 repeats:NO];
}

mouseUp: 方法中,销毁定时器:
- (void)mouseUp: (NSEvent *)theEvent {
    [mouseTimer invalidate];
    mouseTimer = nil;
}

如果定时器触发,则说明鼠标按钮已经按住了您指定的一段时间,您可以采取任何喜欢的动作:
- (void)mouseWasHeld: (NSTimer *)tim {
    NSEvent * mouseDownEvent = [tim userInfo];
    mouseTimer = nil;
    // etc.
}

你的 mouseUp 处理程序还应该处理用户单击某个东西但没有按住按钮时需要发生的任何事情。此外,是否保证定时器不会在输入 mouseUp: 之后但在调用 [mouseTimer invalidate]; 之前触发? - Mike DeSimone
@Mike:1) 当然可以,我把它留给问题提出者作为一个练习。2)定时器和事件处理都是放在运行循环中作为排队输入的,所以这不应该成为问题。我想不到其他保证的方法。 - jscs
我一按住鼠标并调用 mouseWasHeld 函数一段时间后就会出现 EXC_BAD_ACCESS 错误。只有在我释放鼠标时调用 mouseWasHeld 函数才会出现此错误。您知道我做错了什么吗? - Grant Wilkinson
2
你需要在 mouseWasHeld: 方法中将 mouseTimer 设置为 nil。否则,计时器会触发并被无效化,然后你会在 mouseUp: 方法中再次发送 invalidate 消息给它。 - jscs

0
据我所记,mouseDown 仅在用户第一次单击元素时触发,而不是按住不放时触发。
解决您的问题的方法是在 .h 文件中定义一个 BOOL,如下所示:
bool mouseIsHeldDown = false;

然后在你的mouseDown事件中:

mouseIsHeldDown = true;

在你的鼠标抬起事件中:

mouseIsHeldDown = false;

然后您可以在代码的任何位置检查mouseIsHeldDown = true。

希望这能解决您的问题!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接