详解QT源码之QT创建窗口程序、消息循环和WinMain函数
创始人
2024-08-01 14:01:31
0

QT源码之QT创建窗口程序、消息循环和WinMain函数是本文要介绍对内容,使用QT也有一段时间了,有的时候需要跟踪代码到QT源码中去查找问题。在这里我将记录一下我跟踪QT源码学习到的一些知识。

我的开发环境是VC6.0+QT4.3.3。QT已经不为VC6.0提供addin了,所以有的时候我也会使用EclipseCDT来编写代码,因为有了QT for Eclipse的plugin写代码会方便一些。

我们在学习QT的时候,接触的***个程序就是下面的helloworld程序:

  1. view plaincopy to clipboardprint?  
  2. #include      
  3. #include      
  4.     
  5. int main(int argc, char *argv[])     
  6. {     
  7.     QApplication app(argc, argv);        
  8.     QPushButton hello("Hello world!");     
  9.     hello.resize(100, 30);       
  10.     hello.show();     
  11.     return app.exec();     
  12. }    
  13. #include  
  14. #include  
  15.  
  16. int main(int argc, char *argv[])  
  17. {  
  18.     QApplication app(argc, argv);   
  19.     QPushButton hello("Hello world!");  
  20.     hello.resize(100, 30);   
  21.     hello.show();  
  22.     return app.exec();  
  23. }  

这个程序的作用很多手册和文档都已经讲了,讲的也都很细致,非常不错。

但是喜欢钻研,深入的童鞋也许开始注意了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的构造函数:

  1. QApplication::QApplication(int &argc, char **argv, int _internal)  
  2.     : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))  
  3. { Q_D(QApplication); d->construct(); QApplicationPrivate::app_compile_version = _internal;} 

很明显,首先调用的是QApplicationPrivate的构造函数。大家注意第三个参数:QApplication::Type type

这事Type类型的定义:enum Type { Tty, GuiClient, GuiServer };

下面是代码注释中对Type类型的解释:

  1. \enum QApplication::Type  
  2.  
  3. \value Tty a console application  
  4. \value GuiClient a GUI client application  
  5. \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函数,在这个函数中我们看到了下面创建消息循环的代码

  1. QEventLoop eventLoop;  
  2. self->d_func()->in_exec = true;  
  3. int returnCode = eventLoop.exec(); 

在QCoreApplication.cpp中的注释是这样解释的:

  1. The application will enter  
  2. the event loop when exec() is called. exit() will not return  
  3. until the event loop exits, e.g., when quit() is called. 

到这里,main和WinMain函数到底是怎么回事,以及QT是怎么创建窗口消息循环的,我们已经非常清楚了。

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...