在mac 下应用场景如下:
1、点击关闭窗口按钮时,不退出应用。
2、点击dock应用图标时候显示应用程序住窗口。
应用的显示和隐藏不是本文重点,实现点击dock应用图标在QT获取对应通知是本文关键。
在写之前参考了
https://stackoverflow.com/questions/15143369/qt-on-os-x-how-to-detect-clicking-the-app-dock-icon
但是编译通不过。
修改一些编译错误,能正常工作。
1、编译开关和工程配置。
在xcode中设置Build Settings->Apple Clang - Preprocessing -> Enable Strict Checking of objc_msgSend Calls ,关闭Strict检查
否则会报错
objc_msgSend requires 0 arguments, but 2 were provided
或者
error: no matching function for call to 'objc_msgSend'
但是QT没有Enable Strict Checking of objc_msgSend Calls,经过查看mesage源代码,pro配置如下:
macx {
LIBS += -framework CoreFoundation
LIBS += -lobjc
LIBS += -framework AppKit
DEFINES += OBJC_OLD_DISPATCH_PROTOTYPES
}
2、代码
#ifdef Q_OS_MAC
#include <objc/objc.h>
#include <objc/message.h>
bool applicationShouldHandleReopen(id self,SEL _cmd,...);
#endif
void setupDockClickEvent();
#ifdef Q_OS_MAC
bool applicationShouldHandleReopen(id self,SEL _cmd, ...)
{
qDebug()<<__FUNCTION__;
// Return NO (false) to suppress the default OS X actions
return false;
}
#endif
void setupDockClickEvent()
{
#ifdef Q_OS_MAC
Class cls = objc_getClass("NSApplication");
id appInstance = objc_msgSend(cls, sel_registerName("sharedApplication"));
if(appInstance != nullptr)
{
id appDelegate = objc_msgSend(appInstance, sel_registerName("delegate"));
Class delClass = objc_msgSend(appDelegate, sel_registerName("class"));
SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:");
if (class_getInstanceMethod(delClass, shouldHandle))
{
if (class_replaceMethod(delClass, shouldHandle, reinterpret_cast<IMP>(applicationShouldHandleReopen), "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, reinterpret_cast<IMP>(applicationShouldHandleReopen),"B@:"))
qDebug() << "Registered dock click handler";
else
qWarning() << "Failed to register dock click handler";
}
}
#endif
}
在main.cpp中
int main(int argc, char *argv[])
{
setupDockClickEvent();
}