在Qt和Mac OS X下注册全局热键

5

我已经阅读了各种帖子和线程,但没有找到答案,现在需要您的帮助。

我有一个针对Mac OS X的Qt应用程序,在某些使用情况下会处于后台而不是活动状态。当这种情况发生时,我想添加全局热键,以便用户可以通过点击预定义的热键轻松地打开或关闭某些功能。 以下内容在应用程序处于后台且未获得焦点时无法正常工作。

QShortcut *shortcut = new QShortcut(QKeySequence(Qt::Key_F12), parent);
shortcut->setContext(Qt::ApplicationShortcut);

到目前为止,我发现Qxt已经过时,无法用于Qt 5.5。 然后还有DDHotkey,需要特定的编译器,由于各种原因我们无法使用。 最后,我找到了添加全局AppleScript的解决方案,它注册了一个事件,但并不是我想要的。

tell application "System Events" to tell process "myApp"
    click menu item "myButton" of menu 1 of menu bar item "Menu" of menu bar 1
end tell

有没有一种使用objective-ccocoa来达到我想要的效果的方法?如果我漏掉了什么,请指导一下我应该去哪里找。
提前致谢!
对于那些寻求更多Qt方式的人,请查看以下存储库:https://github.com/ddqd/qxtglobalshortcut5 它利用了过时的qxt库,但又使其正常工作。该人在Qt 5.4上进行了测试,我们在Qt 5.5下成功地使用它。
1个回答

5

这可能是你正在寻找的东西 https://github.com/jaz303/JFHotkeyManager

你也可以看看苹果公司提供的这个示例,使用RegisterEventHotKey API调用,我认为这将指引你朝着正确的方向。 https://developer.apple.com/library/prerelease/mac/samplecode/FunkyOverlayWindow/Listings/FunkyOverlayWindow_OverlayWindow_m.html#//apple_ref/doc/uid/DTS10000391-FunkyOverlayWindow_OverlayWindow_m-DontLinkElementID_8

或者你可以尝试这段代码

#import <Carbon/Carbon.h>

EventHandlerUPP hotKeyFunction;

pascal OSStatus hotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{    
    Notify *obj =  userData;
    [obj foo];    
    return noErr;
}

@implementation Notify

- (id)init
{
    self = [super init];
    if (self) {
        //handler
        hotKeyFunction = NewEventHandlerUPP(hotKeyHandler);
        EventTypeSpec eventType;
        eventType.eventClass = kEventClassKeyboard;
        eventType.eventKind = kEventHotKeyReleased;
        InstallApplicationEventHandler(hotKeyFunction,1,&eventType,self,NULL);
        //hotkey
        UInt32 keyCode = 80; //F19    
        EventHotKeyRef theRef = NULL;
        EventHotKeyID keyID;
        keyID.signature = 'FOO '; //arbitrary string
        keyID.id = 1;
        RegisterEventHotKey(keyCode,0,keyID,GetApplicationEventTarget(),0,&theRef);

    }        
    return self;
}

- (void)foo
{

}

@end

和标题

#include "notify.mm"
@interface Notify
 - (id)init;
 - (void)foo;
@end

简单来说,这只是一个带有方法和构造函数的对象,在Objective-C中称为init或initialize及其变体。使用“new”直接调用即可。

E.x

#include "notify.h"
int main(){
  Notify* object = new Notify();
}

然而,需要一些基本的Objective-C理解。在我看来,这主要是语法上的差异。但我自己并不是Objective-C专家。无论如何,有很多方法可以解决它,这可能不是最好的想法。您还可以从自己的C++类中调用Objective-C代码。请查看下面的链接,了解如何实现。

https://el-tramo.be/blog/mixing-cocoa-and-qt/

https://github.com/remko/mixing-cocoa-and-qt/

http://philjordan.eu/article/mixing-objective-c-c++-and-objective-c++


这可能会指引你朝着正确的方向:https://dev59.com/tH_aa4cB1Zd3GeqP00N6你也可以将项目拆分并构建一个dylib,然后将其作为库加载。(就像Windows上的dll和Linux上的so文件一样) - Meeh
1
你只需要创建一个头文件,将你的.mm Objective-C代码文件中的对象或函数放入其中,然后将其包含在你的QT项目中,这样你就可以像调用其他QT/C++函数/对象一样调用它们。 - Meeh
好的。你能帮我一下吗? 假设我想把我的类命名为“Hotkey”。我添加了相应的hotkey.hhotkey.mm文件。在.mm文件中,我添加了你粘贴的代码。 现在,由于我不理解提供的Objective-C代码,我需要在我的.h文件中添加什么?你能否提供一个更详细的答案,并分别给出头文件和.mm文件的内容? - Philipp Meissner
1
我已经更新了示例。我将FooBar重命名为Notify。这是类名。在类中发生的情况是,在构造函数中注册了热键,并设置hotKeyHandler在调用热键时触发,然后执行Notify中的foo方法。如果您不熟悉Objective-C,我建议将逻辑移出Objective-C类到C++类中,可以参考我的答案底部的github项目,注意文件扩展名是mm,即使是C++类也是如此编写的。 - Meeh
谢谢,你太厉害了! 我已经接受了这个答案。感谢你的冷静和帮助! 另外补充一下今天我们发现的另一个解决方案。 这也是更Qt的方式 ;) - Philipp Meissner
显示剩余2条评论

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