QT源碼之Qt創(chuàng)建窗體的過(guò)程
QT源碼之Qt創(chuàng)建窗體的過(guò)程是本文要介紹的內(nèi)容。分析Qt的代碼也有一段時(shí)間了,以前在進(jìn)行QT源碼解析的時(shí)候總是使用ue,一個(gè)函數(shù)名在QTDIR/src目錄下反復(fù)的查找,然后分析函數(shù)之間的調(diào)用關(guān)系,效率實(shí)在是太低了,最近總結(jié)出一個(gè)更簡(jiǎn)便的方法,就是利用Qt Creator這個(gè)IDE。
帶來(lái)的好處是:
1、Qt Creator可以很方便的跟蹤代碼的調(diào)用,這樣大大提高了分析代碼的速度。
2、函數(shù)間的調(diào)用關(guān)系能更加直觀的找到。
3、便于對(duì)代碼的縱向關(guān)系的把握。
帶來(lái)的壞處:
1、只是展現(xiàn)了調(diào)用到的函數(shù)或者類的關(guān)系。
2、缺少對(duì)類、某一組類、函數(shù)間關(guān)系的整體把握。
上面總結(jié)一下自己在QT源碼解析時(shí)候用到的方法,下面開始步入正題。Qt創(chuàng)建窗體的過(guò)程,由于我對(duì)linux不是很熟悉,下面我所有的分析都是基于windows下的。關(guān)于windows下利用API創(chuàng)建窗體。我這里就不多解釋了,直接給出代碼,然后結(jié)合下面的代碼來(lái)分析一下Qt創(chuàng)建窗體的過(guò)程。
詳細(xì)的解釋請(qǐng)參考:
John Chen大牛的博文:WIN32 SDK界面編程
- view plaincopy to clipboardprint?
- #include <windows.h>
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("HelloWin") ;
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wc ;
- wc.style = CS_HREDRAW | CS_VREDRAW ;
- wc.lpfnWndProc = WndProc ;
- wc.cbClsExtra = 0 ;
- wc.cbWndExtra = 0 ;
- wc.hInstance = hInstance ;
- wc.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
- wc.lpszMenuName = NULL ;
- wc.lpszClassName = szAppName ;
- if (!RegisterClass (&wc))
- {
- MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ;
- return 0 ;
- }
- hwnd = CreateWindow (szAppName, // window class name
- TEXT (“hello”), // window caption
- WS_OVERLAPPEDWINDOW, // window style
- CW_USEDEFAULT, // initial x position
- CW_USEDEFAULT, // initial y position
- CW_USEDEFAULT, // initial x size
- CW_USEDEFAULT, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL) ; // creation parameters
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc ;
- PAINTSTRUCT ps ;
- RECT rect ;
- switch (message)
- {
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps) ;
- GetClientRect (hwnd, &rect) ;
- DrawText (hdc, TEXT ("the WM_PAINTmessage"), -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
- EndPaint (hwnd, &ps) ;
- return 0 ;
- case WM_DESTROY:
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
- #include <windows.h>
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("HelloWin") ;
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wc ;
- wc.style = CS_HREDRAW | CS_VREDRAW ;
- wc.lpfnWndProc = WndProc ;
- wc.cbClsExtra = 0 ;
- wc.cbWndExtra = 0 ;
- wc.hInstance = hInstance ;
- wc.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
- wc.lpszMenuName = NULL ;
- wc.lpszClassName = szAppName ;
- if (!RegisterClass (&wc))
- {
- MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ;
- return 0 ;
- }
- hwnd = CreateWindow (szAppName, // window class name
- TEXT (“hello”), // window caption
- WS_OVERLAPPEDWINDOW, // window style
- CW_USEDEFAULT, // initial x position
- CW_USEDEFAULT, // initial y position
- CW_USEDEFAULT, // initial x size
- CW_USEDEFAULT, // initial y size
- NULL, // parent window handle
- NULL, // window menu handle
- hInstance, // program instance handle
- NULL) ; // creation parameters
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc ;
- PAINTSTRUCT ps ;
- RECT rect ;
- switch (message)
- {
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps) ;
- GetClientRect (hwnd, &rect) ;
- DrawText (hdc, TEXT ("the WM_PAINTmessage"), -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
- EndPaint (hwnd, &ps) ;
- return 0 ;
- case WM_DESTROY:
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
先寫一個(gè)最簡(jiǎn)單的Qt程序
- view plaincopy to clipboardprint?
- #include <QtGui/QApplication>
- #include <QPushButton>
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- QPushButton w("hello kitty");
- w.show();
- return a.exec();
- }
- #include <QtGui/QApplication>
- #include <QPushButton>
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- QPushButton w("hello kitty");
- w.show();
- return a.exec();
- }
來(lái)分析一下這個(gè)窗體程序是如何創(chuàng)建的。
首先關(guān)于main函數(shù)和winmain函數(shù),為什么Qt的窗口程序是用main函數(shù)而非winmain,在我的另外一篇文章中有解釋:
QT源碼之QT創(chuàng)建窗口程序、消息循環(huán)和WinMain函數(shù) 這里不再解釋。
Windows窗體創(chuàng)建一定會(huì)調(diào)用RegisterClass這個(gè)函數(shù)的,我們?cè)赒TDIR/src里面搜索一下,有兩個(gè)文件有這個(gè)函數(shù)一個(gè)是qapplication_win.cpp另外一個(gè)是qeventdispatcher_win.cpp,兩個(gè)的作用不同,這次我們先研究qapplication_win.cpp中的RegisterClass函數(shù),因?yàn)檫@個(gè)是與窗體創(chuàng)建有關(guān)的。
下一篇QT源碼之Qt是如何處理windows消息 將會(huì)介紹qeventdispatcher_win.cpp中的RegisterClass的作用。
我們先將斷點(diǎn)設(shè)置在qapplication_win.cpp中的 qt_reg_winclass 函數(shù)里,然后開始調(diào)試,運(yùn)行到斷點(diǎn),然后我們看一下call stack如下圖:
下面紅色的框中為Call stack,我們可以看到函數(shù)調(diào)用的順序,真正的創(chuàng)建QPushButton是在show()方法中,show()方法又調(diào)用了setVisible方法…… ……
QtWndProc就是窗體的回調(diào)函數(shù),在RegisterClass的時(shí)候傳給WNDCLASS結(jié)構(gòu)的,QtWndProc同上面的API創(chuàng)建窗體的函數(shù)WndProc。
我們看一下QtWndProc的代碼,也是一個(gè)switch (message) 然后一堆case來(lái)處理消息,***也是調(diào)用DefWindowProc將不歸他處理的消息交還給系統(tǒng)。
小結(jié):QT源碼之Qt創(chuàng)建窗體的過(guò)程的內(nèi)容介紹完了,希望本文對(duì)你有多幫助?。?!