詳解QT源碼之QT創(chuàng)建窗口程序、消息循環(huán)和WinMain函數
QT源碼之QT創(chuàng)建窗口程序、消息循環(huán)和WinMain函數是本文要介紹對內容,使用QT也有一段時間了,有的時候需要跟蹤代碼到QT的源碼中去查找問題。在這里我將記錄一下我跟蹤QT源碼學習到的一些知識。
我的開發(fā)環(huán)境是VC6.0+QT4.3.3。QT已經不為VC6.0提供addin了,所以有的時候我也會使用EclipseCDT來編寫代碼,因為有了QT for Eclipse的plugin寫代碼會方便一些。
我們在學習QT的時候,接觸的***個程序就是下面的helloworld程序:
- view plaincopy to clipboardprint?
- #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();
- }
- #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,和消息循環(huán),QT是如何RegisterClass和創(chuàng)建消息循環(huán)的?
下面我們將來一起學習一下QT的源碼來解釋一下這個main函數和整個窗口程序的創(chuàng)建過程:
設置好路徑后,我們先F10一下,看看這個程序到底是從哪里開始運行的。
程序跳到了\winmain\qtmain_win.cpp文件的WinMain函數中,再看這個文件上面的宏定義:#define main qMain
繼續(xù)看:在WinMain函數中調用了我們自己定義的main函數:int result = main(argc, argv.data());
哇塞,原來如此啊。原來我們寫的main函數是假的。哈哈。
再來看一下QT是如何創(chuàng)建窗體和消息循環(huán)的。
首先我們來到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函數,在這個函數中我們看到了下面創(chuàng)建消息循環(huán)的代碼
- 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是怎么創(chuàng)建窗口和消息循環(huán)的,我們已經非常清楚了。