回答
这是疯了,但我得到了它,并没有任何的Objective-C编码:
我得出的QApplication。在我的派生类的*的.cpp部分我把:
#ifdef Q_OS_MAC
#include <objc/objc.h>
#include <objc/message.h>
bool dockClickHandler(id self,SEL _cmd,...)
{
Q_UNUSED(self)
Q_UNUSED(_cmd)
((MyApplictionClass*)qApp)->onClickOnDock();
return true;
}
#endif
在我的派生的应用程序类的构造函数,我把:
#ifdef Q_OS_MAC
objc_object* cls = objc_getClass("NSApplication");
SEL sharedApplication = sel_registerName("sharedApplication");
objc_object* appInst = objc_msgSend(cls,sharedApplication);
if(appInst != NULL)
{
objc_object* delegate = objc_msgSend(appInst, sel_registerName("delegate"));
objc_object* delClass = objc_msgSend(delegate, sel_registerName("class"));
const char* tst = class_getName(delClass->isa);
bool test = class_addMethod((objc_class*)delClass, sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"), (IMP)dockClickHandler,"[email protected]:");
if (!test)
{
// failed to register handler...
}
}
#endif
添加这种简单的方法,以我的应用程序类(注意,它被称为从在我的回答顶部的处理程序)
void MyApplictionClass::onClickOnDock()
{
// do something...
}
像魅力工作。
由于弃用警告(post-OS X 10.5)和类型错误,我无法正确编译原始答案;我改变了一些类型的名称,并将其编译,但代码仍然无法正常工作。
事实证明,较新版本的Qt(4.8.7+,包括5.x;我使用5.4.1)实现了我们想要添加的方法,如果该方法已经存在,则class_addMethod
失败。见this QTBUG。
注意:上述错误报告包含一个稍微不同的解决方案(我自己解决问题后发现它)。
对我而言,一种解决方案是检查方法是否存在。如果是这样,我们将其替换。如果不是,我们只需添加它。
我还没有在旧的Qt版本上测试过这个代码,但它使用OPs逻辑,所以它应该可以工作。
这是我的代码。就像在OP中一样,所有代码都在QApplication子类的.cpp文件中。
#ifdef Q_OS_MAC
#include <objc/objc.h>
#include <objc/message.h>
void setupDockClickHandler();
bool dockClickHandler(id self,SEL _cmd,...);
#endif
我QApplication的子类构造函数包含
#ifdef Q_OS_MAC
setupDockClickHandler();
#endif
最后,地方在同一个文件(在底部,在我的情况):
#ifdef Q_OS_MAC
void setupDockClickHandler() {
Class cls = objc_getClass("NSApplication");
objc_object *appInst = objc_msgSend((objc_object*)cls, sel_registerName("sharedApplication"));
if(appInst != NULL) {
objc_object* delegate = objc_msgSend(appInst, sel_registerName("delegate"));
Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class"));
SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
if (class_getInstanceMethod(delClass, shouldHandle)) {
if (class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, "[email protected]:"))
qDebug() << "Registered dock click handler (replaced original method)";
else
qWarning() << "Failed to replace method for dock click handler";
}
else {
if (class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler,"[email protected]:"))
qDebug() << "Registered dock click handler";
else
qWarning() << "Failed to register dock click handler";
}
}
}
bool dockClickHandler(id self,SEL _cmd,...) {
Q_UNUSED(self)
Q_UNUSED(_cmd)
// Do something fun here!
qDebug() << "Dock icon clicked!";
// Return NO (false) to suppress the default OS X actions
return false;
}
#endif
另见Apple documentation on the applicationShouldHandleReopen:hasVisibleWindows: method。
为了编译,您还需要链接一些额外的框架。
使用qmake的,我增加了以下我的.pro文件:
LIBS += -framework CoreFoundation -framework Carbon -lobjc
这些标志当然正是你应该添加什么到C++或铛++命令行,如果你手动编译。
这应该是所需的一切。
这是一个很好的答案,但是,我不认为有必要避免使用目标C。qmake处理它,而Qt头文件在从'.mm'文件包含时是有效的。这可以简单地用obj-C++写成'.mm'文件,并且在没有显式调用objc运行时的情况下可读性更强。 Mac上的Qt项目可以包含.m和.mm文件,您可以使用.mm文件中的Qt。 – 2015-07-06 12:44:05
从Qt5.4.0开始,您可以处理QEvent,它与点击dock相关:QEvent :: ApplicationActivate。
与QEvent的问题:: ApplicationActivate是,它会发出每一个激活 - 例如,即使您切换到应用程序切换应用程序。原生行为是仅在Dock图标点击时显示应用程序,而不是在通过cmd +选项卡切换时显示应用程序。
但是,至少在Qt 5.9.1中有一个破解版。 Dock图标点击产生2个连续的QEvent :: ApplicationStateChangeEvent事件,同时cmd + tab - 只有一个。 因此,这段代码会相当准确地发出Dock点击信号。应用程序类是从QApplication继承的应用程序类,也是自身的事件过滤器。
bool App::eventFilter(QObject* watched, QEvent* event)
{
#ifdef Q_OS_MACOS
if (watched == this && event->type() == QEvent::ApplicationStateChange) {
auto ev = static_cast<QApplicationStateChangeEvent*>(event);
if (_prevAppState == Qt::ApplicationActive
&& ev->applicationState() == Qt::ApplicationActive) {
emit clickedOnDock();
}
_prevAppState = ev->applicationState();
}
#endif // Q_OS_MACOS
return QApplication::eventFilter(watched, event);
}
- 1. 在Dock上检测鼠标,任何Dock图标点击
- 2. 如何从Mac OS X dock中隐藏应用程序图标
- 3. OS X Dock在Iphone应用程序中?
- 4. 的Java OS X - Dock中没有应用程序图标
- 5. 如何从Mac OS X dock中隐藏PyQt应用程序的图标
- 6. OS X Dock API?检索带有徽章和其他修改的OS X活动应用程序的图标
- 7. 在Mac OS X上构建Qt应用程序x部署
- 8. 由Dock图标(Mac OS X)启动的菜单栏应用程序
- 9. 如何在Mac OS X和Linux上编程鼠标点击?
- 10. 如何在MacOS运行时更改Qt应用程序的dock图标?
- 11. 在OS X的dock上下文菜单中显示图标?
- 12. 检测点击OS X菜单栏?
- 13. 检测os x上运行的壁纸应用程序?
- 14. 将Java应用程序放入Mac OS X的Dock中
- 15. 应用程序不会退出dock图标,而是退出qt
- 16. 如何在Qt 4.4.1中检测应用程序级别焦点?
- 17. 当用户在Mac上右键点击可可应用程序的dock图标时如何创建菜单?
- 18. 在Mac OS X Snow Leopard上部署Qt应用程序
- 19. Python Tkinter:如何通过点击Mac上的Dock图标重新打开应用程序?
- 20. Qt - 如何检测应用程序的焦点
- 21. 如何将OS X风味添加到Qt的应用程序
- 22. 编译Linux上的Mac OS X的Qt应用程序
- 23. 如何使用install_name_tool在Mac OS X上部署Qt应用程序?
- 24. 从OS X上的xcassets加载应用程序图标
- 25. Mac OS X Dock:如何以编程方式使应用程序的主图标最大化我的应用程序,而不是最小化的图标?
- 26. Javascript - 检测x-webkit-speech图标上的点击
- 27. (OS X)在程序化鼠标点击过程中阻止keyobard
- 28. 如何检测修改键在Qt中的鼠标点击
- 29. cocos2d OS X:如何检测鼠标右键单击?
- 30. 如何检测Mac OS X中使用扬声器的程序?
谢谢!显然,这段代码在Qt 4.8.7中停止了工作,但我设法使它工作(在Qt 5.4.1上),所以我发布了一个更新版本的答案。 – exscape 2015-03-02 20:19:02
这不适合我。 exscape的答案是' – 2015-03-12 19:52:55