QT源码之Qt创建窗体的过程

移动开发
本人介绍的是QT源码之Qt创建窗体的过程,利用Qt Creator中的IDE,创建过程在文章中有详细的介绍,先来看内容。

QT源码之Qt创建窗体的过程是本文要介绍的内容。分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法,就是利用Qt Creator这个IDE。

带来的好处是:

1、Qt Creator可以很方便的跟踪代码的调用,这样大大提高了分析代码的速度。

2、函数间的调用关系能更加直观的找到。

3、便于对代码的纵向关系的把握。

带来的坏处:

1、只是展现了调用到的函数或者类的关系。

2、缺少对类、某一组类、函数间关系的整体把握。

上面总结一下自己在QT源码解析时候用到的方法,下面开始步入正题。Qt创建窗体的过程,由于我对linux不是很熟悉,下面我所有的分析都是基于windows下的。关于windows下利用API创建窗体。我这里就不多解释了,直接给出代码,然后结合下面的代码来分析一下Qt创建窗体的过程。

详细的解释请参考:

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) ;  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.

先写一个最简单的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();  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

来分析一下这个窗体程序是如何创建的。

首先关于main函数和winmain函数,为什么Qt的窗口程序是用main函数而非winmain,在我的另外一篇文章中有解释:

QT源码之QT创建窗口程序、消息循环和WinMain函数  这里不再解释。

Windows窗体创建一定会调用RegisterClass这个函数的,我们在QTDIR/src里面搜索一下,有两个文件有这个函数一个是qapplication_win.cpp另外一个是qeventdispatcher_win.cpp,两个的作用不同,这次我们先研究qapplication_win.cpp中的RegisterClass函数,因为这个是与窗体创建有关的。

下一篇QT源码之Qt是如何处理windows消息 将会介绍qeventdispatcher_win.cpp中的RegisterClass的作用。

我们先将断点设置在qapplication_win.cpp中的 qt_reg_winclass 函数里,然后开始调试,运行到断点,然后我们看一下call stack如下图:

下面红色的框中为Call stack,我们可以看到函数调用的顺序,真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法…… ……

QT源码之Qt创建窗体的过程

QtWndProc就是窗体的回调函数,在RegisterClass的时候传给WNDCLASS结构的,QtWndProc同上面的API创建窗体的函数WndProc。

我们看一下QtWndProc的代码,也是一个switch (message) 然后一堆case来处理消息,***也是调用DefWindowProc将不归他处理的消息交还给系统。

小结:QT源码之Qt创建窗体的过程的内容介绍完了,希望本文对你有多帮助!!!

责任编辑:zhaolei 来源: CSDN博客
相关推荐

2011-06-23 11:16:39

Qt Excel

2011-06-23 15:32:05

Qt Windows消息

2011-06-23 14:05:32

Qt 事件机制

2011-06-23 13:25:42

QT 源码 窗口

2011-07-01 17:36:23

Qt

2011-06-23 14:40:13

Qt 信号

2011-06-23 13:38:27

QT 元对象 信号

2011-06-20 16:38:33

Qt QWidget Qt4.5

2011-06-28 16:18:24

Qt QObject

2011-06-20 13:05:53

Qt 4.7 Qt Quick

2011-06-16 11:28:48

Qt QApplicati

2017-02-27 11:48:58

JVM源码分析Java

2011-09-06 15:38:20

QT安装

2011-06-20 13:54:41

Qt 动态 切换

2011-06-10 12:44:09

2011-06-23 14:27:48

QT QLibrary 动态库

2011-06-20 15:52:14

Qt Designer 控件

2011-06-24 17:38:09

Qt 坐标 事件

2011-06-10 11:05:05

Qt Quick QML

2011-06-21 14:53:25

QT 界面美化 QStyle
点赞
收藏

51CTO技术栈公众号