【问题标题】:Handling Mac OS X file open event BEFORE C++ main() executes在 C++ main() 执行之前处理 Mac OS X 文件打开事件
【发布时间】:2015-04-16 09:32:00
【问题描述】:

我用谷歌搜索了很多,但仍然找不到好的解决方案:/
所以,我正在将一个复杂的 Qt5 应用程序(某些网络服务的客户端)移植到 Mac OS X(10.7.0 “Lion”及更高版本)。

我需要处理像 *.xyz 这样的自定义文件和像 xyz:// 这样的自定义 URL 方案。
好的,Qt5 有 QFileOpenEvent 类来处理 OS X 相应的事件。
但是:此事件仅在应用程序事件循环开始后到达(显然)!

我需要“捕捉”并处理 OS X 的文件打开事件之前 main 开始,因为程序逻辑设计为只处理命令行参数处理。 p>

简化的main功能码:

int main(int argc, char[]* argv)
{
     QApplication app( argc, argv );

     QStringList arguments = app.arguments();
     if( arguments.count() == argc ) arguments.removeFirst();

     Logic appLogic( NULL, &app );
     app.installMessageHandler( &appLogic );

     // The problem:
     // **This function will always called earlier than the any event**
     if( ! appLogic.start( arguments ) ) return 0;

     // Start processing of events
     // Only after this call Logic class get the desired event
     return app.exec();
}

有没有办法在 C++ main 函数启动之前 获取 OS X 的文件打开事件,或者在 argv 参数中获取“我的”文件/url?
也许,一些Objective-C 黑魔法可以完成这项工作?

注意:start 做了许多复杂且异步的事情。事件在执行期间到达,因此当异步内容已经工作时很难处理它。所以看起来我只需要阻止 start 执行,如果事件将到达。

如果应用程序已经打开,则没有问题。

【问题讨论】:

    标签: c++ macos qt events qt5


    【解决方案1】:

    我找到了一个可能很奇怪的解决方案 - 使用 Qt 事件系统。

    int main(int argc, char[]* argv)
    {
        QApplication app( argc, argv );
    
        QStringList arguments = app.arguments();
        if( arguments.count() == argc ) arguments.removeFirst();
    
        Logic appLogic( NULL, &app );
        #ifdef Q_OS_MAC
        app.installMessageHandler( &appLogic );
    
        // Here we should alreasy get FileOpenEvent, if it occurs
        // NOTE: without this FileOpenEvent will arrive LATER
        //       than the DryRunEvent!
        app.processEvents();
    
        // If there is no file open event in the queue,
        // we should just open the blank program window
        // NOTE: Qt takes ownership of this event object,
        //       so you should not delete it manually
        DryRunEvent* runEv = new DryRunEvent( p );
        a.postEvent( &l, runEv, Qt::LowEventPriority );
        #endif
    
        ...
    
        #ifndef Q_OS_MAC
        if( ! appLogic.start( arguments ) ) return 0;
        #endif
    
        return app.exec();
    }
    

    自定义事件标题:

    class BaseEvent : public QEvent
    {
    public:
        BaseEvent( QEvent::Type& eType ) : QEvent( getEventType( eType ) )
        {
        }
    
        ~BaseEvent() {}
    
        QEvent::Type getEventType( QEvent::Type& eType )
        {
            if( eType == QEvent::None )
            {
                eType = static_cast<QEvent::Type>( QEvent::registerEventType() );
            }
            return eType;
        }
    };
    
    class DryRunEvent : public BaseEvent
    {
        QStringList m_params;
    
        public:
             DryRunEvent( const Parameters& params ) :
                 BaseEvent( eventType ), m_params( params )
             {
             }
    
             ~DryRunEvent(){}
    
             QStringList GetCmdLineParams() const { return m_params; }
    
        public:
            static QEvent::Type eventType;
    };
    

    自定义事件源:

    QEvent::Type ViewerDryRunEvent::eventType = QEvent::None;
    

    逻辑类头:

    class Logic : public QObject
    {
        Q_OBJECT
        Q_DISABLE_COPY( Logic )
    
        public:
            explicit Logic(QObject *parent, QApplication* application);
            virtual ~Logic();
    
        public slots:
            bool Start( QStringList parameters );
            void ReceiveParameters( QStringList parameters );
            void Stop();
    
            #ifdef Q_OS_MAC
            bool Logic::WasStarted() const
            {
                ... Determine wether logic was started or not ...
            }
            #endif
    
        private:
            #ifdef OS_MACOSX
            // Virtual overrided functions
             bool eventFilter( QObject* obj, QEvent* event )
             {
                 if( event->type() == QEvent::FileOpen )
                 {
                     QFileOpenEvent* fileEvent = static_cast< QFileOpenEvent* >(event);
                     Q_ASSERT( fileEvent != NULL );
    
                     QString uri;
                     if( fileEvent->file().isEmpty() == false )
                     {
                         uri = fileEvent->file();
                     }
                     else if( fileEvent->url().isEmpty() == false )
                     {
                         uri = fileEvent->url().toString();
                     }
    
                     if( uri.isEmpty() == false )
                     {
                         if( WasStarted() ) ReceiveParameters( uri );
                         else Start( uri );
                     }
    
                     return false;
                 }
                 else if( event->type() == DryRunEvent::eventType )
                 {
                     DryRunEvent* myEvent = static_cast< DryRunEvent* >( event );
                     Q_ASSERT( myEvent != NULL );
                     QStringList cmdLineParams = myEvent->GetCmdLineParams();
    
                     Q_ASSERT( !WasStarted() );
                     if( WasStarted() ) return false;
    
                     if( !Start( cmdLineParams ) ) m_application->exit( 0 );
                     return false;
                 }
    
                 // Standard event processing
                 return QObject::eventFilter( obj, event );
            }
            #endif
        };
    

    我希望有人觉得这些东西有用:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-31
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多