由于弃用警告(OS X 10.5之后)和类型错误,我无法得到正确编译的原始答案; 我更改了一些类型名称并将其编译,但代码仍然无效.
事实证明,较新版本的Qt(4.8.7+,包括5.x;我使用5.4.1)实现了我们想要添加class_addMethod的方法,如果方法已经存在则会失败.看到这个QTBUG.
注意:上面的错误报告包含一个稍微不同的解决方案(我自己解决了问题后发现了它).
一个对我有用的解决方案是检查方法是否存在.如果是,我们将其替换.如果没有,我们只需添加它.
我没有在较旧的Qt版本上测试此代码,但它使用OP逻辑,所以它应该工作.
这是我的代码.与在OP中的情况一样,所有代码都在QApplication子类的.cpp文件中.
#ifdef Q_OS_MAC
#include <objc/objc.h>
#include <objc/message.h>
void setupDockClickHandler();
bool dockClickHandler(id self,SEL _cmd,...);
#endif
Run Code Online (Sandbox Code Playgroud)
我的QApplication子类构造函数包含
#ifdef Q_OS_MAC
setupDockClickHandler();
#endif
Run Code Online (Sandbox Code Playgroud)
最后,在同一个文件的某个地方(在我的情况下,在底部):
#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, "B@:"))
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,"B@:"))
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
Run Code Online (Sandbox Code Playgroud)
另请参阅有关applicationShouldHandleReopen:hasVisibleWindows:方法的Apple文档.
为了编译它,您还需要链接一些额外的框架.
使用qmake,我将以下内容添加到我的.pro文件中:
LIBS += -framework CoreFoundation -framework Carbon -lobjc
Run Code Online (Sandbox Code Playgroud)
如果您手动编译,那些标志当然正是您应该添加到c ++或clang ++命令行的标志.
这应该是所需要的一切.
这很疯狂,但我得到了它,没有任何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
Run Code Online (Sandbox Code Playgroud)
在我的派生应用程序类构造函数中我把:
#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,"B@:");
if (!test)
{
// failed to register handler...
}
}
#endif
Run Code Online (Sandbox Code Playgroud)
将这个简单的方法添加到我的应用程序类中(注意它是从我的答案顶部的处理程序中引用的)
void MyApplictionClass::onClickOnDock()
{
// do something...
}
Run Code Online (Sandbox Code Playgroud)
像魅力一样工作.
| 归档时间: |
|
| 查看次数: |
2898 次 |
| 最近记录: |