如何检测全局鼠标按钮事件 [英] How to detect global mouse button events

查看:253
本文介绍了如何检测全局鼠标按钮事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何编写一个代码来全局监视鼠标按钮。这将是OS X,我想尝试写在Qt / C ++。



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



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



我最后的想法是制作一个像steerMouse这样的免费程序,只是为了弄清楚如何做。



我要求从哪里开始指导 - 我如何在全球范围内检测鼠标按钮事件?

解决方案

这不可能只使用Qt。有另一个问题详细说明了问题。它归结为:


  1. QApplication 上安装事件过滤器让您在光标位于任何应用程序窗口之上但不在其外部时接收鼠标事件。


  2. 如果小部件使用 grabMouse()抓取鼠标,


所以,你需要去度假使用平台特定的API来做到这一点 - 这意味着Cocoa和写在Objective C / C ++。有一个问题,提供了非常好的答案,几乎提供了我们需要的一切,但是Qt集成。



缺少的部分,如下所示,是将独立代码与Qt集成。这个代码显示一个空的小部件,只是为了证明我们正确地处理了鼠标事件对于我们的应用程序及其外部。



这是一个完整的工作示例,使用Cocoa 。它需要进入 .mm 文件;不要忘记将它添加到qmake项目文件中的 OBJECTIVE_SOURCES SOURCES NSEvent 转换为 code> QMouseEvent 。最好的方法是从 <$中复制并粘贴一些代码c $ c> 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 Q_UNUSED(result)
NSEvent * event =(NSEvent *)message;
switch([event type]){
case NSLeftMouseDown:
out< Lv;打破;
case NSLeftMouseUp:
out<< L ^;打破;
case NSRightMouseDown:
out<< Rv;打破;
case NSRightMouseUp:
out<< R ^;打破;
case NSOtherMouseDown:
out<< [event buttonNumber]<< v;打破;
case NSOtherMouseUp:
out<< [event buttonNumber]<< ^;打破;
默认值:
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;
//全局监视处理程序对发送到我们的应用程序的事件是* not *。
id monitorId = [NSEvent addGlobalMonitorForEventsMatchingMask:mask handler:^(NSEvent * event){
filter-> nativeEventFilter(NSEvent,event,0);
}];
//我们还需要处理来自我们应用程序的事件
a.installNativeEventFilter(filter.data());
QWidget w;
w.show();
int rc = a.exec();
[NSEvent removeMonitor:monitorId];
return rc;
}


I'm wondering how can I write a code to monitor the mouse buttons globally. This would be for OS X, and I'd like to try writing it in Qt/C++.

To begin with I don't know how to capture those global events. The monitor application would not display a GUI, it'd simply be a process that runs in the background and detects mouse buttons being clicked.

In the second part of the program I would like to launch hot-keys depending of the mouse key pressed.

My final idea is make a free program like steerMouse, just to figure out how it could be done.

I'm asking for a guidance of where to start - how can I detect the mouse button events globally?

解决方案

It's not possible using only Qt. There's another question that details the issues. It boils down to:

  1. Installing an event filter on QApplication will let you receive mouse events while the cursor is over any application window, but not outside of it. That's not helpful in your case.

  2. If a widget grabs the mouse using grabMouse(), it will receive all mouse events globally, but interaction with other applications becomes impossible.

So, you'll need to resort to using platform-specific APIs to do this - that means Cocoa and writing in Objective C/C++. There's a question with excellent answers that provides almost everything we need but Qt integration.

The missing part, shown below, is integrating the stand-alone code with Qt. This code shows an empty widget just to demonstrate that we correctly handle mouse events for both our application, and outside of it.

This is a complete, working example, using Cocoa. It needs to go into a .mm file; don't forget to add it to OBJECTIVE_SOURCES in your qmake project file (not to SOURCES!).

Unfortunately, there's isn't a single function/method that would translate from NSEvent to QMouseEvent. The best one can do is copy&paste some code from qnsview.mm. This is unfortunate but results from the design of Qt platform abstraction: the platform code ends up calling QWindowSystemInterface::handleMouseEvent(....) to post the event to the application.

#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;
}

这篇关于如何检测全局鼠标按钮事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆