Qtの事件の処理のメカニズムの2を浅く議論します


転載先:http://blog.csdn.net/changsheng230/article/details/6092978
上記では、Qtフレームワークのイベント処理メカニズム:イベントの発生、配布、受け入れ、処理を紹介し、ウィンドウシステムのマウスクリックQWidgetを例に、コードを分析し、QtフレームワークがどのようにEvent Loop処理を通じてメッセージキューサイクルに入り、どのようにプラットフォーム関連の関数に一歩一歩委任されるかを分析した.パッケージングユーザ入力イベントはウィンドウシステム処理に渡され、関数呼び出しスタックは以下の通りである.
  • main(int, char **)
  • QApplication::exec()
  • QCoreApplication::exec()
  • QEventLoop::exec(ProcessEventsFlags )
  • QEventLoop::processEvents(ProcessEventsFlags )
  • QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags)

  •  
    ここでは、Qt appがウィンドウシステムでコールバックされた後、イベントがQLPplicationを介して最終イベントの受信者と処理者QWidget::event、(QWidgetはObjectを継承し、その虚関数eventを再ロードする)にどのように配布されるかについて説明します.以下のすべての議論はソースコードに埋め込まれます.
  • QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) bool QETWidget::translateMouseEvent(const MSG &msg)
  • bool QApplicationPrivate::sendMouseEvent(...)
  • inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
  • bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
  • bool QApplication::notify(QObject *receiver, QEvent *e)
  • bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
  • bool QWidget::event(QEvent *event)
  • // (   Section 7) Section 2-1:
    QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
    {
       ...
       //  message    Qt        
       if (qt_is_translatable_mouse_event(message)) {
            if (QApplication::activePopupWidget() != 0) {            
                POINT curPos = msg.pt;
                //           QWidget  ,      main   widget  
                QWidget* w = QApplication::widgetAt(curPos.x, curPos.y);
                if (w)
                    widget = (QETWidget*)w;
            }
            if (!qt_tabletChokeMouse) {
                // ,    。Windows               Qt Widget 
                // => Section 2-2
                result = widget->translateMouseEvent(msg);       
         ...
    }
    // Section 2-2  $QTDIR/src/gui/kernel/qapplication_win.cpp
    //      Windows    ,        windows           、   QApplication    QMouseEvent,QWidget.
    bool QETWidget::translateMouseEvent(const MSG &msg)
    {
         //..              
          //       sendMouseEvent   
         // widget       ; e     QMouseEvent
         // ==> Section 2-3
         res = QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down, qt_last_mouse_receiver);
    }
    // Section 2-3 $QTDIR/src/gui/kernel/qapplication.cpp
    bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
                                             QWidget *alienWidget, QWidget *nativeWidget,
                                             QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
                                             bool spontaneous)
    {
         //             
         //MouseEvent        spontaneous,      sendSpontaneousEvent。 sendSpontaneousEvent()   sendEvent         ,   QEvent   spontaneous    。        spontaneous  :              ,        。   MousePress                (    Section 1~ Section 7),    
    spontaneous  
        if (spontaneous)
            result = QApplication::sendSpontaneousEvent(receiver, event);  ==〉Section 2-4
        else
            result = QApplication::sendEvent(receiver, event);
    }
    
    // Section 2-4 C:/Qt/4.7.1-Vs/src/corelib/kernel/qcoreapplication.h
    inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
    { 
        // event       
         //      2-5 QCoreApplication::notifyInternal
        if (event) event->spont = true; return self ? self->notifyInternal(receiver, event) : false; 
    }
    // Section 2-5:  $QTDIR/gui/kernel/qapplication.cpp
    bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
    {
        
        //       Qt Jambi (QT Java    )  QSA (QT Script for Application)   
         ...
         //          Qt                  ,    receiver->d_func()->threadData    QThreadData::current()。   ,          Event Loop   
         QObjectPrivate *d = receiver->d_func();
        QThreadData *threadData = d->threadData;
        ++threadData->loopLevel;
        bool returnValue;
        QT_TRY {
            // ,           QCoreApplication::nofity()  ==> Section 2-6
            returnValue = notify(receiver, event);
        } QT_CATCH (...) {
            --threadData->loopLevel;
            QT_RETHROW;
        }
    }
    // Section 2-6:  $QTDIR/gui/kernel/qapplication.cpp
    // QCoreApplication::notify       QApplication::notify Qt             ,Qt          :                      notify  。
    bool QApplication::notify(QObject *receiver, QEvent *e)
    {
       //    ,          Switch,Case
       ..
       switch ( e->type())
       {
        ...
        case QEvent::MouseButtonPress:
        case QEvent::MouseButtonRelease:
        case QEvent::MouseButtonDblClick:
        case QEvent::MouseMove:
         ...
            //      (d       )       ==> Section 2-7
            res = d->notify_helper(w, w == receiver ? mouse : &me);
            e->spont = false;
            break;
        }
        ...
    }
    // Section 2-7:  $QTDIR/gui/kernel/qapplication.cpp
    bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
    {
        ...
        //            ,      Event Filters.                           。
       //                     。    QObject::eventFilter()     ,         ,                。                     ,             。            ,                     。
        if (sendThroughObjectEventFilters(receiver, e))
            return true;
         //      receiver  => Section 2-8
        bool consumed = receiver->event(e);
        e->spont = false;
    }
    // Section 2-8  $QTDIR/gui/kernel/qwidget.cpp
    // QApplication  notify     notify_helper,         QObject   - QWidget.
    bool QWidget::event(QEvent *event)
    {
        ...
        switch(event->type()) {
        case QEvent::MouseButtonPress:
            // Don't reset input context here. Whether reset or not is
            // a responsibility of input method. reset() will be
            // called by mouseHandler() of input method if necessary
            // via mousePressEvent() of text widgets.
    #if 0
            resetInputContext();
    #endif
            //mousePressEvent    ,QWidget             mousePress     
            mousePressEvent((QMouseEvent*)event);
            break;   
    }