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);
}
- createInternalHwnd 调用 qt_create_internal_window
- qt_create_internal_window 调用 QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext();
- 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源码