QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数
版权声明
请尊重原创作品。转载请保持文章完整性,并以超链接形式注明原始作者“tingsking18”和主站点地址,方便其他朋友提问和指正。
QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数
使用QT也有一段时间了,有的时候需要跟踪代码到QT的源码中去查找问题。在这里我将记录一下我跟踪QT源码学习到的一些知识。
我的开发环境是VC6.0+QT4.3.3。QT已经不为VC6.0提供addin了,所以有的时候我也会使用EclipseCDT来编写代码,因为有了QT for Eclipse的plugin写代码会方便一些。
我们在学习QT的时候,接触的第一个程序就是下面的helloworld程序:
- #include <QApplication>
- #include <QPushButton>
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- QPushButton hello("Hello world!");
- hello.resize(100, 30);
- hello.show();
- return app.exec();
- }
这个程序的作用很多手册和文档都已经讲了,讲的也都很细致,非常不错。
但是喜欢钻研,深入的童鞋也许开始注意了int main(int argc, char *argv[]),这个main函数是标准的main函数,而windows应用程序的入口是winmain函数,而main函数是命令行程序的入口。win下窗口程序都有RegisterClass,和消息循环,QT是如何RegisterClass和创建消息循环的?
下面我们将来一起学习一下QT的源码来解释一下这个main函数和整个窗口程序的创建过程:
设置好路径后,我们先F10一下,看看这个程序到底是从哪里开始运行的。
程序跳到了/winmain/qtmain_win.cpp文件的WinMain函数中,再看这个文件上面的宏定义:#define main qMain
继续看:在WinMain函数中调用了我们自己定义的main函数:int result = main(argc, argv.data());
哇塞,原来如此啊。原来我们写的main函数是假的。哈哈。
再来看一下QT是如何创建窗体和消息循环的
首先我们来到QApplication的构造函数:
QApplication::QApplication(int &argc, char **argv, int _internal)
: QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
{ Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;}
很明显,首先调用的是QApplicationPrivate的构造函数。大家注意第三个参数:QApplication::Type type
这事Type类型的定义:enum Type { Tty, GuiClient, GuiServer };
下面是代码注释中对Type类型的解释:
/enum QApplication::Type
/value Tty a console application
/value GuiClient a GUI client application
/value GuiServer a GUI server application (for Qt for Embedded Linux)
当程序运行到hello.show()的时候调用了QWidgetPrivate::create_sys函数。
在这里我们看到调用了类似RegisterClass的函数:QString windowClassName = qt_reg_winclass(q);
这里的q是指向QWidget的指针(我们先忽略掉这里)。
以及包括后面的CreateWindow,ShowWindow等等我们熟悉的WindowsAPI函数
const QString qt_reg_winclass(QWidget *w) 函数的原型是在qapplication_win.cpp中定义的。我们转到qt_reg_winclass函数的实现中。我们就看到了windows的API函数RegisterClass和窗口消息处理函数:wc.lpfnWndProc = (WNDPROC)QtWndProc;
我们看一下QtWndProc的实现,原来窗口消息都是在这里进行处理的啊!
至于最后一句app.exec(); 调用了QCoreApplication的Exec函数,在这个函数中我们看到了下面创建消息循环的代码
QEventLoop eventLoop;
self->d_func()->in_exec = true;
int returnCode = eventLoop.exec();
在QCoreApplication.cpp中的注释是这样解释的:
The application will enter
the event loop when exec() is called. exit() will not return
until the event loop exits, e.g., when quit() is called.
到这里,main和WinMain函数到底是怎么回事,以及QT是怎么创建窗口和消息循环的,我们已经非常清楚了。
参考:http://blog.csdn.net/tingsking18/article/details/4737925
---------------------------------------------------------------------------
QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数的更多相关文章
- QT源码解析(七)Qt创建窗体的过程,作者“ tingsking18 ”(真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法)
前言:分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法, ...
- QT创建窗口程序、消息循环和WinMain函数(为主线程建立了一个QEventLoop,并执行exec函数)
使用QT也有一段时间了,有的时候需要跟踪代码到QT的源码中去查找问题.在这里我将记录一下我跟踪QT源码学习到的一些知识. 我的开发环境是VC6.0+QT4.3.3.QT已经不为VC6.0提供addin ...
- AOP源码解析之二-创建AOP代理前传,获取AOP信息
AOP源码解析之二-创建AOP代理前传,获取AOP信息. 上篇文章对AOP的基本概念说清楚了,那么接下来的AOP还剩下两个大的步骤获取定义的AOP信息,生成代理对象扔到beanFactory中. 本篇 ...
- Qt源码解析之-从PIMPL机制到d指针
一.PIMPL机制 PIMPL ,即Private Implementation,作用是,实现 私有化,力图使得头文件对改变不透明,以达到解耦的目的 pimpl 用法背后的思想是把客户与所有关于类的私 ...
- Spring IoC源码解析——Bean的创建和初始化
Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...
- 是否应该学习qt源码(碰到问题的时候,或者文档对函数描述不清楚的时候,可以看一下)
是否应该学习qt源码 如果你想调用某个函数,但是文档并没有清晰描述这个函数的功能的时候,你就需要去阅读源码,看看Qt究竟是怎么实现的.比如用QNetworkAccessManager发送一个QHttp ...
- Spring源码解析 – AnnotationConfigApplicationContext容器创建过程
Spring在BeanFactory基础上提供了一些列具体容器的实现,其中AnnotationConfigApplicationContext是一个用来管理注解bean的容器,从AnnotationC ...
- Fabric1.4源码解析:客户端创建通道过程
在使用Fabric创建通道的时候,通常我们执行一条命令完成,这篇文章就解析一下执行这条命令后Fabric源码中执行的流程. peer channel create -o orderer.example ...
- 【源码解析】Flink 滑动窗口数据分配到多个窗口
之前一直用翻滚窗口,每条数据都只属于一个窗口,所有不需要考虑数据需要在多个窗口存的事情. 刚好有个需求,要用到滑动窗口,来翻翻 flink 在滑动窗口中,数据是怎么分配到多个窗口的 一段简单的测试代码 ...
随机推荐
- 查找指定表的字段not null约束,并生成删除Sql
SElECT 'ALTER TABLE '+OBJECT_NAME(c.parent_obj)+' DROP CONSTRAINT '+ c.name FROM sys.sysconstraints ...
- mysql基本知识---20151127-1
2015年11月27日,作为PHPer的我开始全面学习mysql数据库. 基本语法: 1.连接服务器: mysql>mysql -h host -u root -p 回车 输入密码(本地环境可以 ...
- Python 初学——V_Rename(第一个完整的python程序)
我在大一的时候就对python非常感兴趣,就是一直没有时间和机会去学习下,只是了解些表面的东西,今天早上整理电脑的时候发现文件夹里面的文件名是这样子的,有点小不舒服,特别想去除重复的"Str ...
- JDBC 基本操作: CRUD
Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可. Statement对象的executeUpdate方法,用于向 ...
- 【nodejs】json value出现 undefined 将会无法解析 问题来了
如果 value 的值就要 undefined 怎处理呢?
- ios/mac/COCOA系列 -- UIALertVIew 学习笔记
最近在学习ios开发,学习的书籍<ios7 Pragramming cookbook>,做笔记的目的以后方便查看.笔记形式是小例子,将书上的例子书写完整. UIAlertViewClass ...
- UIScrollView显示超出屏幕大小的内容
1:UIScrollView在初始化的时候可以指定frame,它的frame和其他控件不太一样的地方是: 它的frame指的的“可视大小”,也就是我们指定多大的frame来看一张图片,当然最大就是屏幕 ...
- MySQL、SqlServer、Oracle三大主流数据库分页查询
在这里主要讲解一下MySQL.SQLServer2000(及SQLServer2005)和ORCALE三种数据库实现分页查询的方法.可能会有人说这些网上都有,但我的主要目的是把这些知识通过我实际的应用 ...
- 2109&2535: [Noi2010]Plane 航空管制 - BZOJ
Description世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上, ...
- 【BZOJ】【1051】【HAOI2005】受欢迎的牛
按B->A连边,tarjan缩点,然后找入度为0的连通分量,如果有1个,则ans=size[i],如果大于一个则ans=0: 当然如果按A->B连边就是找出度为0的(表示没有被它喜欢的,这 ...