zoukankan      html  css  js  c++  java
  • QT创建窗口程序、消息循环和WinMain函数(为主线程建立了一个QEventLoop,并执行exec函数)

    使用QT也有一段时间了,有的时候需要跟踪代码到QT的源码中去查找问题。在这里我将记录一下我跟踪QT源码学习到的一些知识。

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

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

    1. #include
    2. #include
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication app(argc, argv);
    6. QPushButton hello("Hello world!");
    7. hello.resize(100, 30);
    8. hello.show();
    9. return app.exec();
    10. }

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

    但是喜欢钻研,深入的童鞋也许开始注意了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.sina.com.cn/s/blog_a401a1ea0101e6yp.html

  • 相关阅读:
    总结下目前维护团队中用到的一些技术和工具
    一次修改时间导致的ORACLE 实例崩溃
    ruby 用watir 登录 CU的代码
    最近好烦.真的好烦
    Lucene.Net学习
    项目上线了,心情好爽
    轻松掌握XMLHttpRequest对象[转]
    微软发布3款SQL Injection攻击检测工具
    Domino开发
    用在JavaScript的RequestHelper [转]
  • 原文地址:https://www.cnblogs.com/findumars/p/6025122.html
Copyright © 2011-2022 走看看