如何检测全局鼠标按钮事件

Ang*_*oll 2 c++ macos qt osx-snow-leopard

我想知道如何编写代码来全局监控鼠标按钮.这适用于OS X,我想尝试用Qt/C++编写它.

首先,我不知道如何捕获这些全球事件.监视器应用程序不会显示GUI,它只是一个在后台运行并检测单击鼠标按钮的进程.

在程序的第二部分,我想根据按下的鼠标键启动热键.

我最后的想法是制作像steerMouse这样的免费程序,只是想弄清楚它是如何完成的.

我要求指导从哪里开始 - 如何全局检测鼠标按钮事件?

Rei*_*ica 6

仅使用Qt是不可能的.还有一个问题详述了这些问题.归结为:

  1. 安装事件过滤器QApplication将允许您在光标位于任何应用程序窗口上时接收鼠标事件,但不在其外部.这对你的情况没有帮助.

  2. 如果窗口小部件使用鼠标抓取鼠标grabMouse(),它将全局接收所有鼠标事件,但与其他应用程序的交互变得不可能.

因此,您需要使用特定于平台的API来执行此操作 - 这意味着Cocoa并使用Objective C/C++编写.有一个问题有很好的答案,提供我们需要的几乎所有东西,但Qt集成.

缺少的部分,如下所示,是将独立代码与Qt集成在一起.此代码显示一个空小部件,仅用于演示我们正确处理应用程序及其外部的鼠标事件.

这是一个完整的工作示例,使用Cocoa.它需要进入一个.mm文件; 不要忘了将它添加到OBJECTIVE_SOURCES你的qmake项目文件(没有SOURCES!).

不幸的是,没有一个功能/方法可以转化NSEventQMouseEvent.最好的方法是复制和粘贴一些代码qnsview.mm.这是不幸的,但是Qt平台抽象的设计产生了结果:平台代码最终要求QWindowSystemInterface::handleMouseEvent(....)将事件发布到应用程序.

#include <QApplication>
#include <QAbstractNativeEventFilter>
#include <QTextStream>
#include <QWidget>
#include <cstdio>
#import <AppKit/AppKit.h>

QTextStream out(stdout);

class MyEventFilter : public QAbstractNativeEventFilter {
public:
    bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
        Q_UNUSED(eventType) Q_UNUSED(result)
        NSEvent * event = (NSEvent*)message;
        switch ([event type]) {
        case NSLeftMouseDown:
            out << "Lv"; break;
        case NSLeftMouseUp:
            out << "L^"; break;
        case NSRightMouseDown:
            out << "Rv"; break;
        case NSRightMouseUp:
            out << "R^"; break;
        case NSOtherMouseDown:
            out << [event buttonNumber] << "v"; break;
        case NSOtherMouseUp:
            out << [event buttonNumber] << "^"; break;
        default:
            return false;
        }
        out << endl;
        return false;
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QSharedPointer<QAbstractNativeEventFilter> filter(new MyEventFilter);
    const int mask =
            NSLeftMouseDownMask | NSLeftMouseUpMask |
            NSRightMouseDownMask | NSRightMouseUpMask |
            NSOtherMouseDownMask | NSOtherMouseUpMask;
    // The global monitoring handler is *not* called for events sent to our application
    id monitorId = [NSEvent addGlobalMonitorForEventsMatchingMask:mask handler:^(NSEvent* event) {
        filter->nativeEventFilter("NSEvent", event, 0);
    }];
    // We also need to handle events coming to our application
    a.installNativeEventFilter(filter.data());
    QWidget w;
    w.show();
    int rc = a.exec();
    [NSEvent removeMonitor:monitorId];
    return rc;
}
Run Code Online (Sandbox Code Playgroud)