QT 消息处理机制

Qt提供函数QApplication::processEvents()来处理消息。
调用流程如下:
1.

bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
	{
		 createInternalHwnd();
		 do{
			PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
                                    WMWP_QT_TOFOREIGNLOOP, 0);
            TranslateMessage(&msg);
            DispatchMessage(&msg);
		 }while(true);
	}
  1. createInternalHwnd 调用 qt_create_internal_window
  2. qt_create_internal_window 调用 QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext();
  3. qWindowsMessageWindowClassContext里面:
	WNDCLASS wc;
    wc.lpfnWndProc = qt_internal_proc;//窗体消息处理函数为qt_internal_proc
5. 最后,qt_internal_proc的实现代码:
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
    if (message == WM_NCCREATE)
        return true;
    MSG msg;
    msg.hwnd = hwnd;
    msg.message = message;
    msg.wParam = wp;
    msg.lParam = lp;
    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    qintptr result;
#else
    long result;
#endif
    if (!dispatcher) {
        if (message == WM_TIMER)
            KillTimer(hwnd, wp);
        return 0;
    }
    if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result))
        return result;
#ifdef GWLP_USERDATA
    auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
#else
    auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLong(hwnd, GWL_USERDATA));
#endif
    QEventDispatcherWin32Private *d = 0;
    if (q != 0)
        d = q->d_func();
    switch (message) {
    case WM_QT_SOCKETNOTIFIER: {
        // socket notifier message
        int type = -1;
        switch (WSAGETSELECTEVENT(lp)) {
        case FD_READ:
        case FD_ACCEPT:
            type = 0;
            break;
        case FD_WRITE:
        case FD_CONNECT:
            type = 1;
            break;
        case FD_OOB:
            type = 2;
            break;
        case FD_CLOSE:
            type = 3;
            break;
        }
        if (type >= 0) {
            Q_ASSERT(d != 0);
            QSNDict *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read };
            QSNDict *dict = sn_vec[type];
            QSockNot *sn = dict ? dict->value(wp) : 0;
            if (sn == nullptr) {
                d->postActivateSocketNotifiers();
            } else {
                Q_ASSERT(d->active_fd.contains(sn->fd));
                QSockFd &sd = d->active_fd[sn->fd];
                if (sd.selected) {
                    Q_ASSERT(sd.mask == 0);
                    d->doWsaAsyncSelect(sn->fd, 0);
                    sd.selected = false;
                }
                d->postActivateSocketNotifiers();
                // Ignore the message if a notification with the same type was
                // received previously. Suppressed message is definitely spurious.
                const long eventCode = WSAGETSELECTEVENT(lp);
                if ((sd.mask & eventCode) != eventCode) {
                    sd.mask |= eventCode;
                    QEvent event(type < 3 ? QEvent::SockAct : QEvent::SockClose);
                    QCoreApplication::sendEvent(sn->obj, &event);
                }
            }
        }
        return 0;
    }
    case WM_QT_ACTIVATENOTIFIERS: {
        Q_ASSERT(d != 0);
        // Postpone activation if we have unhandled socket notifier messages
        // in the queue. WM_QT_ACTIVATENOTIFIERS will be posted again as a result of
        // event processing.
        MSG msg;
        if (!PeekMessage(&msg, d->internalHwnd,
                         WM_QT_SOCKETNOTIFIER, WM_QT_SOCKETNOTIFIER, PM_NOREMOVE)
            && d->queuedSocketEvents.isEmpty()) {
            // register all socket notifiers
            for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end();
                 it != end; ++it) {
                QSockFd &sd = it.value();
                if (!sd.selected) {
                    d->doWsaAsyncSelect(it.key(), sd.event);
                    // allow any event to be accepted
                    sd.mask = 0;
                    sd.selected = true;
                }
            }
        }
        d->activateNotifiersPosted = false;
        return 0;
    }
    case WM_TIMER:
        Q_ASSERT(d != 0);
        d->sendTimerEvent(wp);
        return 0;
    case WM_QT_SENDPOSTEDEVENTS:
        Q_ASSERT(d != 0);
        // Allow posting WM_QT_SENDPOSTEDEVENTS message.
        d->wakeUps.storeRelaxed(0);
        // We send posted events manually, if the window procedure was invoked
        // by the foreign event loop (e.g. from the native modal dialog).
        q->sendPostedEvents();
        return 0;
    } // switch (message)
    return DefWindowProc(hwnd, message, wp, lp);
}
int QCoreApplication::exec(){
    QEventLoop eventLoop;
    self->d_func()->in_exec = true;
    self->d_func()->aboutToQuitEmitted = false;
    int returnCode = eventLoop.exec();
}
int QEventLoop::exec(ProcessEventsFlags flags)
 while (!d->exit.loadAcquire())
        processEvents(flags | WaitForMoreEvents | EventLoopExec);
		
}

如上:exec 调用的就是processEvents函数。
在线查看qt源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值