额,还是从一个window程序的基本结构看起吧
Win32程序基本结构
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
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;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message) {
case WM_CREATE:
return 0;
case WM_PAINT:
...
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Windows为当前执行的每个Windows程式维护一个消息队列,通过PostMessage、PostThreadMessage可以把消息放入队列,在事件循环中通过GetMessage、PeekMessage可以或者队列中的消息并可通过DispatchMessage将消息派发到相应的窗口回调函数。
-
消息队列为空时,GetMessage 会阻塞,而PeekMessage不会。现在一般都使用后者
-
SendMessage发送消息直接到窗口回调函数,不进入消息队列
-
WH_GETMESSAGE类型的钩子可以截获GetMessage和PeekMessage的消息
-
截获SendMessage发送的消息,需要WH_CALLWNDPROC或WH_CALLWNDPROCRET类型的钩子
QEventDispatcherWin32
这3个比较容易和前面的对应上。但是... 该怎么叙述呢...
事件循环
Qt中的事件循环式通过 QEventLoop::exec() 来启动的。(它通常以QCoreApplication::exec()、QDialog::exec()等身份出现)
在 QEventLoop::exec() 内,是一个while 循环。
int QEventLoop::exec(ProcessEventsFlags flags)
{
while (!d->exit)
//...
该循环内,调用的就是QEventDispatcherWin32::processEvents() 函数
bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
...
haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
...
TranslateMessage(&msg);
DispatchMessage(&msg);
...
这样一来,消息被派发到窗口回调函数中。进而可以被
- 回调函数 qt_internal_proc()
-
钩子qt_GetMessageHook()
处理
相关函数
- bool QAbstractEventDispatcher::hasPendingEvents ()
Qt事件队列以及程序的消息队列是否有非空
- void QAbstractEventDispatcher::wakeUp ()
processEvents() 可能会处于一个阻塞状态,比如调用MsgWaitForMultipleObjectsEx(),此时需要唤醒它。
比如QCoreApplication::postEvent()往队列放入新的事件时,会调用该函数。
- void QAbstractEventDispatcher::interrupt ()
打断processEvents() ,使其尽快返回,即使队列中还有很多东西。
定时器
主要是定时器的注册与反注册,相关的成员函数
在Windows层面,
Socket Notifier
- void QAbstractEventDispatcher::registerSocketNotifier ( QSocketNotifier * notifier )
- void QAbstractEventDispatcher::unregisterSocketNotifier ( QSocketNotifier * notifier )
在源码中,你可以看到 WSAAsyncSelect 这个函数的身影,但是它不是Windows的同名的api函数。而是一个本地的函数。
在Qt下,它是通过创建新线程,并在线程内调用 ::select() 函数来实现的。线程内通过SendMessage将消息传递到窗口的回调函数中。
int select(
__in int nfds,
__inout fd_set *readfds,
__inout fd_set *writefds,
__inout fd_set *exceptfds,
__in const struct timeval *timeout
);
- The select function determines the status of one or more sockets, waiting if necessary, to perform synchronous I/O.
QSocketNotifier::Read
|
FD_READ
|
有可读消息通知
|
FD_CLOSE
|
关闭消息通知
|
FD_ACCEPT
|
链接请求消息通知
|
QSocketNotifier::Write
|
FD_WRITE
|
有可写消息通知
|
FD_CONNECT
|
希望得到connect或多点join操作完成信息通知
|
QSocketNotifier::Exception
|
FD_OOB
|
有外带消息通知
|
Win Event Notifer
- bool registerEventNotifier(QWinEventNotifier *notifier);
- void unregisterEventNotifier(QWinEventNotifier *notifier);
- void activateEventNotifiers();
这是windows下特有的一个。当某个事件内核对象被触发时,我们可以以异步的方式得到通知。
在是在
QEventDispatcherWin32::processEvents()
函数内,通过调用
MsgWaitForMultipleObjectsEx()
来实现的。
Qt 事件队列
恩,似乎还少点这部分的东西。Qt的事件都是要派发到 QObject::event() 这个函数中去的。
bool QCoreApplication::sendEvent ( QObject * receiver, QEvent * event )
直接将直接派发到 QObject::event()
而
void QCoreApplication::postEvent ( QObject * receiver, QEvent * event )
确实将事件放置到Qt的事件队列中。可是这些事件是怎么取出来,并派发到 QObject::event() 中去的呢?
负责这个工作的是:
void QCoreApplication::sendPostedEvents()
void QCoreApplication::sendPostedEvents ( QObject * receiver, int event_type )
将事件队列中的事件取出,并使用QCoreApplication::sendEvent ()将其派发出去。
恩,exec() 启动的事件循环调用 event dispatcher 的 processEvents(),该函数负责调用前面的QCoreApplication::sendPostedEvents()函数。
这样工作又转移到了一开始提到窗口回调函数中了。
分享到:
相关推荐
通过“STM32自学笔记”这样的资料,你可以系统地学习STM32的基础知识和实践技巧,逐步掌握单片机开发的全貌。在实践中,不断实验和调试,加深对外设的理解,是提升技能的关键。同时,参与社区交流,参考他人的项目,...
[STM32自学笔记].蒙博宇
本资源“《STM32自学笔记》随书共享资料”提供了全面的学习STM32开发所需的知识点,包括基础理论、实践应用和编程技巧。 1. **STM32内核结构**:STM32系列采用的是ARM Cortex-M系列处理器,如M0、M3、M4或M7,它们...
STM32 调试笔记 STM32 调试笔记是对 STM32 微控制器的调试过程的详细记录,涵盖了从准备工作到实际调试的各个步骤。本笔记旨在帮助开发者更好地理解 STM32 的工作原理和调试方法。 1. 调试 STM32 前的准备工作: ...
本资源“STM32自学笔记 随书资料”是一份全面的学习STM32开发的参考资料,旨在帮助初学者快速入门并深入理解STM32的工作原理和编程技巧。 一、STM32架构与特性 STM32系列涵盖了多种型号,主要基于Cortex-M0、M3、M4...
STM32编程笔记是针对嵌入式开发领域中广泛应用的STM32微控制器的学习资源,这份笔记详尽地涵盖了从硬件板子设计到软件工程构建的全过程。STM32是意法半导体(STMicroelectronics)推出的基于ARM Cortex-M内核的一...
本自学笔记主要围绕STM32的基础知识、开发环境搭建、程序编写和实践应用展开,旨在帮助初学者快速入门并掌握STM32的使用。 一、STM32基础 STM32系列涵盖多种内核类型,包括Cortex-M0、M3、M4和M7,不同内核提供了...
官方应用笔记是STM32开发的重要参考资料,它包含了详细的硬件接口使用、软件开发技巧以及特定功能的应用指南。 本文将围绕STM32官方应用笔记,深入探讨其在入门学习和实际项目开发中的关键知识点。 1. **STM32内核...
STM32 的所有应用笔记打包下载(共50份) 最最详细方便的下载。花了我一天的时间下载和整理。 大家记住:下载完记得打分和评价,除了可以取回自己的被扣的分数外,还额外增加1个积分的。不要把自己的分数浪费了哦! ...
本书《STM32自学笔记》由蒙博宇编著,是一本针对STM32微控制器初学者的自学指导书,该书详细介绍了STM32的原理及应用,并通过作者亲身体验和实践总结出的内容,为读者提供了一个清晰的学习路径。本书内容共分为七章...
51单片机C语言延时函数STM32单片机学习笔记51单片机C语言延时函数STM32单片机学习笔记51单片机C语言延时函数STM32单片机学习笔记51单片机C语言延时函数STM32单片机学习笔记51单片机C语言延时函数STM32单片机学习笔记...
STM32学习笔记是针对嵌入式系统开发者的一份详细教程,主要聚焦于基于ARM Cortex-M3内核的32位微控制器STM32。STM32系列由意法半导体(STMicroelectronics)开发,广泛应用于物联网、智能硬件、自动化设备、无人机、...
本文主要根据提供的“stm32F1读书笔记.zip”资料,围绕STM32F1的手册摘要、主要特性以及常见应用进行详述。 首先,STM32F1系列是STM32家族的一员,其核心为32位Cortex-M3处理器,运行速度高达72MHz,提供了强大的...
在“九九的STM32笔记”中,我们可以期待深入学习关于STM32的各种知识,包括基础概念、硬件接口、软件开发流程以及实际应用案例。 一、STM32基础 STM32系列涵盖了多个产品线,如STM32F0、STM32F10x、STM32F4等,它们...
STM32学习笔记详解 STM32是一款基于ARM Cortex-M内核的微控制器,由意法半导体(STMicroelectronics)公司生产。这份“STM32-learning-notes.rar”压缩包文件包含了一份作者原创的学习笔记,旨在帮助初学者或有经验...
STM32笔记.pdf
stm32自学教程。适合开发者,学生,单片机爱好者