qt消息处理机制深入分析(Qt消息机制与window程序消息的对比)

更新时间:2023-06-30 10:24:03 阅读: 评论:0

罢黜qt消息处理机制深⼊分析(Qt消息机制与window程序消息的对
⽐)
理解Qt消息机制刻不容缓,那我们从对⽐传统的windows消息处理机制对⽐来说起;只有知道QT底层的消息处理、对我们理解并学习Qt有很⼤帮助;
克里斯托弗 里夫下⾯我将对windows程序与Qt对⽐,并在核⼼代码处并给出注释进⾏对⽐、⽅便学习。
注意重点看代码中的注视进⾏对⽐:!
注意重点看代码中的注视进⾏对⽐:!
注意重点看代码中的注视进⾏对⽐:!
⼀:windows程序的消息处理
windows程序的处理⼤概⼀致
如下:
1.0 windows 消息处理机制:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Hello");
HWND  hwnd;
MSG    msg;
WNDCLASS wndclass;
//fill wndclass
wndclass.lpfnWndProc  = WndProc;
...
RegisterClass(&wndclass);
hwnd = CreateWindow( .... );      // creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0))  { //这⼀块位置得到消息
TranslateMessage(&msg);//转换消息
DispatchMessage(&msg);//分发消息到系统处理
}
return msg.wParam;
}
1.1 这是分发消息的回调函数熟悉windows程序应该不难看懂
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message) {
ca WM_CREATE:
return 0;
ca WM_PAINT://重绘、⽐如窗⼝⼤⼩拉伸
...
return 0;
ca WM_DESTROY:
PostQuitMessage(0);
return 0;wsas
}
return DefWindowProc(hwnd, message, wParam, lParam); // windows 操作系统内部的消息机制、系统调⽤函数;
}
⼆ Qt消息处理机制
2.0 Qt的消息机制
QEventDispatcherWin32:
注册窗⼝类别,并创建⼀个隐藏窗⼝ (QEventDispatcherWin32_Internal_WidgetXXXX)
窗⼝的回调函数 qt_internal_proc()
安装WH_GETMESSAGE类型的钩⼦函数 qt_GetMessageHook()
bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0))  与上⾯的消息循环:的while⼀样、得到过滤所有消息{
TranslateMessage(&msg);//转换消息
DispatchMessage(&msg); //分发消息
}
DispatchMessage(&msg); //分发消息
分发消息的或回调函数、这个与windows程序的CALLBACK WndProc⼀样
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) 2.1 下⾯就是从系统获得的消息后Qt封装消息后所作的事情
这个就是Qt的消息回调:
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
RAM lp)
{
if (message == WM_NCCREATE)leafy
return true;
// MSG windows 消息结构:
MSG msg;
msg.hwnd = hwnd;
msg.wParam = wp;
msg.lParam = lp;
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
long result;
if (!dispatcher) {
if (message == WM_TIMER)
KillTimer(hwnd, wp);
return 0;
} el if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result)) {
return result;
}
#ifdef GWLP_USERDATA
QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
#el
homeworkQEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
#endif
QEventDispatcherWin32Private *d = 0;
if (q != 0)
d = q->d_func();
// 下⾯ WM_QT_SOCKETNOTIFIER socket Qt 事件底层的处理机制、处理⽹络的消息事件
if (message == WM_QT_SOCKETNOTIFIER) {
// socket notifier message
int type = -1;
switch (WSAGETSELECTEVENT(lp)) { //在⾮阻塞模式下利⽤socket事件的消息机制,Server端与Client端之间的通信处于异步状态下        ca FD_READ: //socket ⽂件描述符 read 、有数据到达时发⽣
ca FD_ACCEPT: //socket ⽂件描述符接收连接、作为客户端连接成功时发⽣
初一下册英语
type = 0;
break;
ca FD_WRITE: //socket ⽂件描述符写、有数据发送时产⽣
ca FD_CONNECT:  //socket ⽂件描述符发起连接、作为服务端等待连接成功时发⽣
type = 1;
break;
ca FD_OOB: //socket ⽂件描述符收到数据、收到外带数据时发⽣
type = 2;
break;
ca FD_CLOSE: //socket ⽂件描述符关闭断开连接、套接⼝关闭时发⽣
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();
} el {
Q_ASSERT(d->ains(sn->fd));
QSockFd &sd = d->active_fd[sn->fd];
if (sd.lected) {
Q_ASSERT(sd.mask == 0);
d->doWsaAsyncSelect(sn->fd, 0);
sd.lected = fal;
}
兵马俑侠
d->postActivateSocketNotifiers();
// Ignore the message if a notification with the same type was
/
/ received previously. Suppresd message is definitely spurious.
const long eventCode = WSAGETSELECTEVENT(lp);
if ((sd.mask & eventCode) != eventCode) {
sd.mask |= eventCode;
QEvent event(type < 3 ? QEvent::SockAct : QEvent::SockClo);
QCoreApplication::ndEvent(sn->obj, &event);
}
}
}
return 0;
} el if (message == WM_QT_ACTIVATENOTIFIERS) { // 处理postEvent事件
Q_ASSERT(d != 0);
// postEvent() 事件,因为是队列的存储的⽅式,邮递发送消息、直接返回
// 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()) { // d->queuedSocketEvents 消息队列如果消息有很多的时候都会加⼊这个队列、这个就是关于Qt::connect();参数:地            // register all socket notifiers
for (QSFDict::iterator it = d->active_fd.begin(), end = d->d();
it != end; ++it) {
QSockFd &sd = it.value();
if (!sd.lected) {
d->doWsaAsyncSelect(it.key(), sd.event);
// allow any event to be accepted
sd.mask = 0;
sd.lected = true;
}
}
}
d->activateNotifiersPosted = fal;
return 0;
} el if (message == WM_QT_SENDPOSTEDEVENTS  // 处理 Qt ndPostEvent()发送事件
// we also u a Windows timer to nd posted events when the message queue is full
// WM_QT_SENDPOSTEDEVENTS : 这个消息是我们Qt程序⼤部分⾛的事件,特殊情况除外。
|| (message == WM_TIMER
&& d->ndPostedEventsWindowsTimerId != 0
&& wp == (uint)d->ndPostedEventsWindowsTimerId)) {
const int localSerialNumber = d->rialNumber.load();
if (localSerialNumber != d->lastSerialNumber) {
d->lastSerialNumber = localSerialNumber;
q->ndPostedEvents();//因为ndevent是同步所以直接进⼊进⾏调⽤
}
5921
return 0;
} el if (message == WM_TIMER) {//系统定时器超时
Q_ASSERT(d != 0);
d->ndTimerEvent(wp);
return 0;
}
return DefWindowProc(hwnd, message, wp, lp); // 这个与windows程序⼀样的地⽅。
}
另外还有⼀点很重要的:⼤家都知道Qt消息处理⽐windows处理的块,Qt程序通过⼀通处理才调⽤DefWindowProc传给系统所以Qt系统
costco怎么读
的消息机制是⽐windows的消息慢的原因之⼀;
不过他也有它优点:qt的信号与槽函数让我们让我们编程更⽅便。
2.3 消息全局通知事件
另外我们都知道我们开发的系统、所有的消息都会到这个类QApplication::notify事件过滤所有的事件:
其实QApplication继承QGuiApplication类;
bool QGuiApplication::notify(QObject *object, QEvent *event)
{
if (object->isWindowType())
QGuiApplicationPrivate::ndQWindowEventToQPlatformWindow(static_cast<QWindow *>(object), event);
return QCoreApplication::notify(object, event);
}
2.4 消息的组装
下⾯是所有的消息类型处理:在我们开发的系统中别⼈使⽤processEvent发送消息是⽐较⾼效的。
原因:这个消息直达经过的处理的少。
void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
{
switch(e->type) {
ca QWindowSystemInterfacePrivate::FrameStrutMou:
ca QWindowSystemInterfacePrivate::Mou:
QGuiApplicationPrivate::processMouEvent(static_cast<QWindowSystemInterfacePrivate::MouEvent *>(e));
cosplay什么意思break;
ca QWindowSystemInterfacePrivate::Wheel:
QGuiApplicationPrivate::processWheelEvent(static_cast<QWindowSystemInterfacePrivate::WheelEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::Key:
QGuiApplicationPrivate::processKeyEvent(static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::Touch:
QGuiApplicationPrivate::processTouchEvent(static_cast<QWindowSystemInterfacePrivate::TouchEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::GeometryChange:
QGuiApplicationPrivate::processGeometryChangeEvent(static_cast<QWindowSystemInterfacePrivate::GeometryChangeEvent*>(e));
break;
ca QWindowSystemInterfacePrivate::Enter:
QGuiApplicationPrivate::processEnterEvent(static_cast<QWindowSystemInterfacePrivate::EnterEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::Leave:
QGuiApplicationPrivate::processLeaveEvent(static_cast<QWindowSystemInterfacePrivate::LeaveEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::ActivatedWindow:
QGuiApplicationPrivate::processActivatedEvent(static_cast<QWindowSystemInterfacePrivate::ActivatedWindowEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::WindowStateChanged:
QGuiApplicationPrivate::processWindowStateChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowStateChangedEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::WindowScreenChanged:
QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::ApplicationStateChanged: {
QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEv        QGuiApplicationPrivate::tApplicationState(changeEvent->newState, changeEvent->forcePropagate); }
break;
ca QWindowSystemInterfacePrivate::FlushEvents: {
QWindowSystemInterfacePrivate::FlushEventsEvent *flushEventsEvent = static_cast<QWindowSystemInterfacePrivate::FlushEventsEvent *>(e);
QWindowSystemInterface::deferredFlushWindowSystemEvents(flushEventsEvent->flags); }
break;
ca QWindowSystemInterfacePrivate::Clo:
QGuiApplicationPrivate::processCloEvent(
static_cast<QWindowSystemInterfacePrivate::CloEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::ScreenOrientation:
QGuiApplicationPrivate::reportScreenOrientationChange(
static_cast<QWindowSystemInterfacePrivate::ScreenOrientationEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::ScreenGeometry:
QGuiApplicationPrivate::reportGeometryChange(
static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInch:
QGuiApplicationPrivate::reportLogicalDotsPerInchChange(
static_cast<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::ScreenRefreshRate:
QGuiApplicationPrivate::reportRefreshRateChange(
static_cast<QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *>(e));
break;
ca QWindowSystemInterfacePrivate::ThemeChange:
QGuiApplicationPrivate::processThemeChanged(
static_cast<QWindowSystemInterfacePrivate::ThemeChangeEvent *>(e));

本文发布于:2023-06-30 10:24:03,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/162504.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:消息   处理   机制   事件   系统
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图