窗体的创建过程
首先推荐一个网站(https://code.woboq.org/),可以直接看QT所有类的源码,想看什么直接在里面搜索就可以看到,非常好用且方便;比如想QWidget的源码,就在网站里搜索QWidget,然后选择qwidget.cpp,就可以看到QWidget的源码实现,下面所贴的源码都是在这个网站上copy来的。
1. 首先进入main方法后,经过层层调用,最终会调用 QWidgetPrivate::create_sys ()方法,中间的调用层次我已省略,有兴趣的可以自己去看看,在生成窗口的同时,系统会为这个窗口生成并维护一个消息队列
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
//...经过多层调用后会进入下面这个函数,中间的调用层次我已省略,有兴趣的可以自己去看看
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
{
//...为了方便观察,我把一些代码删掉了,看下面的关键代码就行
QString windowClassName = qt_reg_winclass(q); //qt_reg_winclass方法在下面贴出
if (!window) // always initialize
initializeWindow = true;
if (popup)
flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
//...删除了中间代码,这些代码主要是设置一些窗口的相关flags、style
if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
Q_ASSERT(q->internalWinId());
ShowWindow(q->internalWinId(), SW_SHOW); //到此就创建完了一个窗口
}
}
2. 下面来看窗体注册函数qt_reg_winclass(QWidget *)
,这个函数的主要作用就是调用windows api,进行窗口的注册,让系统生成一个窗口;wc.lpfnWndProc = (WNDPROC)QtWndProc;
这一行代码是重点,把QtWndProc注册到系统;QtWndProc
是系统消息处理回调函数,系统处理完消息后会调用这个函数,这个函数里再对系统处理过的消息进行分类处理
const QString qt_reg_winclass(QWidget *w)
{
//...省略代码
#ifndef Q_WS_WINCE
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
#else
WNDCLASS wc;
#endif
wc.style = style;
wc.lpfnWndProc = (WNDPROC)QtWndProc; //重点:把消息处理回调函数注册到系统
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = qWinAppInst();
if (icon) {
wc.hIcon = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
#ifndef Q_WS_WINCE
if (wc.hIcon) {
int sw = GetSystemMetrics(SM_CXSMICON);
int sh = GetSystemMetrics(SM_CYSMICON);
wc.hIconSm = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, sw, sh, 0);
} else {
wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
wc.hIconSm = 0;
}
#endif
} else {
wc.hIcon = 0;
#ifndef Q_WS_WINCE
wc.hIconSm = 0;
#endif
}
wc.hCursor = 0;
#ifndef Q_WS_WINCE
HBRUSH brush = 0;
if (w &&