QT窗口创建过程Word文档格式.docx

上传人:b****5 文档编号:19282321 上传时间:2023-01-05 格式:DOCX 页数:10 大小:232.81KB
下载 相关 举报
QT窗口创建过程Word文档格式.docx_第1页
第1页 / 共10页
QT窗口创建过程Word文档格式.docx_第2页
第2页 / 共10页
QT窗口创建过程Word文档格式.docx_第3页
第3页 / 共10页
QT窗口创建过程Word文档格式.docx_第4页
第4页 / 共10页
QT窗口创建过程Word文档格式.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

QT窗口创建过程Word文档格式.docx

《QT窗口创建过程Word文档格式.docx》由会员分享,可在线阅读,更多相关《QT窗口创建过程Word文档格式.docx(10页珍藏版)》请在冰豆网上搜索。

QT窗口创建过程Word文档格式.docx

11.} 

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

但是喜欢钻研,深入的童鞋也许开始注意了intmain(intargc,char*argv[]),这个main函数是标准的main函数,而windows应用程序的入口是winmain函数,而main函数是命令行程序的入口。

win下窗口程序都有RegisterClass,和消息循环,QT是如何RegisterClass和创建消息循环的?

下面我们将来一起学习一下QT的源码来解释一下这个main函数和整个窗口程序的创建过程:

设置好路径后,我们先F10一下,看看这个程序到底是从哪里开始运行的。

程序跳到了/winmain/qtmain_win.cpp文件的WinMain函数中,再看这个文件上面的宏定义:

#definemainqMain

继续看:

在WinMain函数中调用了我们自己定义的main函数:

intresult=main(argc,argv.data());

哇塞,原来如此啊。

原来我们写的main函数是假的。

哈哈。

再来看一下QT是如何创建窗体和消息循环的

首先我们来到QApplication的构造函数:

QApplication:

:

QApplication(int&

argc,char**argv,int_internal)

:

QCoreApplication(*newQApplicationPrivate(argc,argv,GuiClient))

{Q_D(QApplication);

d->

construct();

QApplicationPrivate:

app_compile_version=_internal;

}

很明显,首先调用的是QApplicationPrivate的构造函数。

大家注意第三个参数:

Typetype

这事Type类型的定义:

enumType{Tty,GuiClient,GuiServer};

下面是代码注释中对Type类型的解释:

/enumQApplication:

Type

/valueTtyaconsoleapplication

/valueGuiClientaGUIclientapplication

/valueGuiServeraGUIserverapplication(forQtforEmbeddedLinux)

当程序运行到hello.show()的时候调用了QWidgetPrivate:

create_sys函数。

在这里我们看到调用了类似RegisterClass的函数:

QStringwindowClassName=qt_reg_winclass(q);

这里的q是指向QWidget的指针(我们先忽略掉这里)。

以及包括后面的CreateWindow,ShowWindow等等我们熟悉的WindowsAPI函数

constQStringqt_reg_winclass(QWidget*w)函数的原型是在qapplication_win.cpp中定义的。

我们转到qt_reg_winclass函数的实现中。

我们就看到了windows的API函数RegisterClass和窗口消息处理函数:

wc.lpfnWndProc 

=(WNDPROC)QtWndProc;

我们看一下QtWndProc的实现,原来窗口消息都是在这里进行处理的啊!

至于最后一句app.exec();

调用了QCoreApplication的Exec函数,在这个函数中我们看到了下面创建消息循环的代码

QEventLoopeventLoop;

self->

d_func()->

in_exec=true;

intreturnCode=eventLoop.exec();

在QCoreApplication.cpp中的注释是这样解释的:

Theapplicationwillentertheeventloopwhenexec()iscalled.exit()willnotreturnuntiltheeventloopexits,e.g.,whenquit()iscalled.

到这里,main和WinMain函数到底是怎么回事,以及QT是怎么创建窗口和消息循环的,我们已经非常清楚了。

2.Qt创建窗体的过程

前言:

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

带来的好处是:

1. 

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

2. 

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

3. 

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

带来的坏处:

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

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

上面总结一下自己在QT源码解析时候用到的方法,下面开始步入正题。

Qt创建窗体的过程,由于我对linux不是很熟悉,下面我所有的分析都是基于windows下的。

关于windows下利用API创建窗体。

我这里就不多解释了,直接给出代码,然后结合下面的代码来分析一下Qt创建窗体的过程。

详细的解释请参考:

JohnChen大牛的博文:

WIN32SDK界面编程

windows.h>

2.LRESULT 

CALLBACK 

WndProc 

(HWND, 

UINT, 

WPARAM, 

LPARAM) 

;

3.int 

WINAPI 

WinMain 

(HINSTANCE 

hInstance, 

HINSTANCE 

hPrevInstance, 

4. 

PSTR 

szCmdLine, 

int 

iCmdShow) 

static 

TCHAR 

szAppName[] 

TEXT 

("

HelloWin"

) 

HWND 

hwnd 

MSG 

msg 

11. 

WNDCLASS 

wc 

12. 

wc.style 

CS_HREDRAW 

CS_VREDRAW 

13. 

14. 

wc.cbClsExtra 

15. 

wc.cbWndExtra 

16. 

wc.hInstance 

hInstance 

17. 

wc.hIcon 

LoadIcon 

(NULL, 

IDI_APPLICATION) 

18. 

wc.hCursor 

LoadCursor 

IDC_ARROW) 

19. 

wc.hbrBackground 

(HBRUSH) 

GetStockObject 

(WHITE_BRUSH) 

20. 

wc.lpszMenuName 

NULL 

21. 

wc.lpszClassName 

szAppName 

22. 

if 

(!

RegisterClass 

(&

wc)) 

23. 

24. 

MessageBox 

This 

program 

requires 

Windows 

NT!

), 

szAppName, 

MB_ICONERROR) 

25. 

26. 

27. 

28. 

CreateWindow 

(szAppName, 

// 

window 

class 

name 

29. 

(“hello”), 

caption 

30. 

WS_OVERLAPPEDWINDOW, 

style 

31. 

CW_USEDEFAULT, 

initial 

position 

32. 

33. 

size 

34. 

35. 

NULL, 

parent 

handle 

36. 

menu 

37. 

instance 

38. 

NULL) 

creation 

parameters 

39. 

ShowWindow 

(hwnd, 

40. 

UpdateWindow 

(hwnd) 

41. 

while 

(GetMessage 

msg, 

0, 

0)) 

42. 

43. 

TranslateMessage 

msg) 

44. 

DispatchMessage 

45. 

46. 

msg.wParam 

47. 

48.} 

49.LRESULT 

(HWND 

hwnd, 

UINT 

message, 

WPARAM 

wParam, 

LPARAM 

lParam) 

50.{ 

51. 

HDC 

hdc 

52. 

PAINTSTRUCT 

ps 

53. 

RECT 

rect 

54. 

switch 

(message) 

55. 

56. 

case 

WM_PAINT:

57. 

BeginPaint 

&

ps) 

58. 

GetClientRect 

rect) 

59. 

DrawText 

(hdc, 

the 

WM_PAINTmessage"

-1, 

rect,DT_SINGLELINE 

DT_CENTER 

DT_VCENTER) 

60. 

EndPaint 

61. 

62. 

WM_DESTROY:

63. 

PostQuitMessage 

(0) 

64. 

65. 

66. 

DefWindowProc 

67.} 

先写一个最简单的Qt程序:

QtGui/QApplication>

a(argc, 

w("

hello 

kitty"

w.show();

a.exec();

10.} 

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

首先关于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函数里,然后开始调试,运行到断点,然后我们看一下callstack如下图:

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

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

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

解析QdateTime

本篇主要侧重于通过分析一个问题来解析QDateTime的代码

问题提出:

前几天一个朋友问我一个QDateTime的问题:

QDateTimed=QDateTime:

fromString("

Mon,26Apr2010,08:

21:

03"

"

ddd,dMMMyyyy,hh:

mm:

ss"

这种格式返回的QDateTime总是null。

问题分析:

于是我亲自试验了一下,没错,果然是null

Q_ASSERT(d.isNull());

然后拿出QtAssistant,自己对照QDateTime的format格式看了一下,format的字符串的确没有任何错误,那错误到底出在哪里呢?

于是开始调试跟踪,看看这个问题到底是出在什么地方。

第一个疑点出现在这里:

注意QLocale:

system();

这个地方。

然后继续跟踪发现第二个疑点:

看清楚了么?

看不清楚没有关系,我已经圈出来了。

在QDateTimeParser:

fromString函数中t是我们要解析的字符串,而val是一个1900-1-1的QDateTime值,看看他俩什么区别(就是上图圈出来的那两部分)?

没错,一个是英文的,一个是中文的。

真相距离我们越来越近了,接下来继续跟踪。

findDay函数for循环这一部分的意思就是循环比较”星期一”到”星期日”和传入的字符串”星期几”这一部分是否相等,传入的字符串中”星期几”这一部分时”mon”,显然不会相等了。

于是我们找到了错误的根源。

错误是找到了,但是我们该如何解决这个错误呢?

根据上面提到的两个疑点,我们判断可能跟QLocale有关。

我的系统是简体中文版的winxp,系统缺省的defaultLocale语言就是chinese,国家就是china。

问题解决:

所以解决这个问题有两个办法:

装个英文版的系统。

上面的代码肯定可以正确执行。

想办法修改QLocale,或者看看QLocale有没有提供相应的方法。

办法1显然是不好办了,那就只好寻找办法2了。

首先查找QLocale帮助,发现有一个setDefault()方法。

我们设置了之后起作用么?

看看图1中的代码defaultLocale=QLocale:

这里defaultLocale又被重置了,所以即使我们设置了也不会起作用的。

继续看帮助:

发现QLocale有一个toDateTime方法:

QDateTimeQLocale:

toDateTime(constQString&

string,constQString&

format)const

没错,就是他了。

下面,我们构造一个语言是英文的QLocale,然后toDateTime就可以了。

QLocalelo(QLocale:

C);

QDateTimed=lo.toDateTime("

Q_ASSERT(d.isValid());

总结:

QDateTime的format格式与QLocale无关,但是format的结果是与QLocale相关的。

QDateTime用的是系统的时区,所以在用utc的时候也要注意。

以前用wx的时候好像也遇到过类似的问题,时间很久了,就忘记了,当时也没有总结,只是大体记得处理这种问题的过程。

依稀记得好像delphi的某个控件也是要修改system中时间,日期的format格式的,具体怎么回事也想不起来了。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1