回答
這是瘋了,但我得到了它,並沒有任何的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