MFC一些理解

来源:互联网 发布:用java计算时间差 编辑:程序博客网 时间:2024/06/06 19:51

重点:

应用程序启动机制。

窗口处理。

动态创建,动态判断。

序列化。

消息映射。


应用程序启动

CwinApp构造中:将自己保存到变量当中。


WinMain


AFXWinMain:调用AfxWinInit初始化应用程序,调用pApp->InitApplication初始化MFC,调用pThread->InitInstance()(我们所重写的函数)来初始化操作。最后pThread->Run() 消息循环,退出处理AfxWinTerm。(pApp和pThread都是this)


窗口创建

窗口参数初始化(DefWindowProc被注册成窗口处理函数)

设置了新创建的hook(用于窗口创建时先调用hook函数)

将窗口对象和窗口句柄做映射关系保存。

创建窗口

卸载hook


消息映射



messageMap保存了父类全局函数(用于获取父类的消息)和自己所需要的消息。
在OnWndWsg函数中将使用,在该函数里首先获取了messageMap的指针,遍历所有消息,如果找不到,继续查找父类,还找不到,继续往上找,直到遇到null。

消息分类

自己定义的消息

WM_CREATE,WM_PAINT -》 窗口消息
菜单 工具栏 按钮 -》命令消息(OnWndWsg中调用OnCommand处理)
子窗口对父窗口(WM_NOTIFY) -》通知消息


运行时信息

维护了一个对象的类的相关信息,判断继承关系,类型关系。



判断对象的继承关系,类型关系:获取自己对象的CruntimeClass(通过RUNTIME_CLASS(MyClass)来获取)实例地址(每个类特有的)与比较的对象 比较CruntimeClass地址,如果相同,说明是同一个类(类型相同)。不等的话,可以通过CruntimeClass类的成员m_pfnGetBaseClass继续比较对象,如此循环,直到相等(说明有关系)或者直到NULL(说明没关系)。

动态创建

对象的CruntimeClass保存一个构建对象(staticCObject*CreateObject())的函数指针(m_pfnCreateObject),通过该函数来创建对象。

MFC文档


CframeWnd::LoadFrame函数中调用CreateEx,将CcreateContext实例 附加到cs.lpCreateParams;
WM_CREATE消息OnCreate函数中调用OnCreateClient,会根据传入的RuntimeClass信息,创建View并调用View的Create函数。
View的Create函数将CcreateContext实例附加到cs.lpCreateParams;在view的WM_CREATE消息处理函数中获取到CDocument实例对象地址,使用Cdocument的AddView将view的地址保存到Document中。最后将CDocument实例对象地址保存到view中。

WM_COMMAD消息派发

将消息发送到顶层窗口FrameWndFrameWnd首先将消息派发给活动的View对象,View对象派发给Cdocument对象。不能处理的话,将消息返回给FrameWnd处理,无法处理,派发给CWinApp,无法处理,丢弃消息。

单文档

创建单文档对象,传入到CwinApp,接着新建文档。


CsingleDocTemplate构造函数里保存三个 运行时类信息,接着调用AddDocTemple把模板添加到App当中。App把文档模板添加到m_pDocManager管理。

App调用OnFileNew函数来调用pDocManager的OnFileNew,接着在链表里拿取文档模板对象,调用模板的OpenDocumentFile函数打开新文档,接着使用CreateNewDocumnet创建文档对象,CreateNewFrame使用LoadFrame来创建。单文档和多文档最大的区别在于,单文档维护了一个文档对象,而多文档维护了一个文档链表。


序列化

需要重写Serialize,记得调用父类的Serialize。创建CArchive实例,存储对象。


_init_Student对象在程序启动时,调用构造函数将该类的CruntimeClass实例地址保存到AfxGetModuleState()变量中的链表里m_classList.

当我们调用<<操作符对实例对象地址操作时(需要是继承Cobject类),CArchive调用WriteObject函数来写入类的信息(类名称,编号),最后调用Serialize虚函数来保存对象数据。

当我们调用>>操作符对类指针操作时,调用的是我们声明的全局友元函数,首先调用ReadObject,从文件中读取类名称,编号,根据类名称在AfxGetModuleState()的链表里查找相应的CruntimeClass实例,并且判断下版本号;获取该实例后,使用CreateObjet函数来创建相应对象。最后调用对象的Serialize虚函数来读取对象的数据,将该创建的对象地址值赋予我们的指针。

版本信息IMPLEMENT_SERIAL宏第三个参数需要添加VERSIONABLE_SCHEMA控制类的版本,在我们读取数据时,还需要判断版本(CArchive有一个GetObjectSchema方法),来支持旧版本。

对话框的数据传送

UpdateData函数会调用DoDataExchange在里面会调用DDX_***函数然后根据控件ID调用GetDlgItem获取句柄,然后进行相应操作。









0 0
原创粉丝点击