《2022年深入浅出MFC学习笔记.docx》由会员分享,可在线阅读,更多相关《2022年深入浅出MFC学习笔记.docx(34页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选学习资料 - - - - - - - - - 第三章: MFC 六大关键技术之仿真:类型识别 深化懂得 MFC的内部运行原理,是本次学习深化浅出 MFC的 主要目的;要仿照的六大技术包括:1:MFC程序的初始化过程;2:RTTI(Runtime type identification )运行时类型识别;3:Dynamic creation 动态创建 4:Persistence永久储存 5:消息映射 6:消息传递;RTTI运行时类型识别)能够侦测某个对象是否属于某种类;即判定某一对象 IsKindOf所属的类是否是父类或当前类;要达到动态类型识别的才能, 必需在构建类继承体系时记录必要的信息
2、,这被称为类型型录表;类型型录表的每个元素为class CRuntimeClass public : MFC以链表的方式建立了此表;CRuntimeClass类型,其定义为:LPCSTR m_lpszClassName; / 对象所属类名 Int m_nObjectSize;/ 对象大小UINT m_wSchema; / 模式号名师归纳总结 - - - - - - -第 1 页,共 21 页精选学习资料 - - - - - - - - - CObject *PASCAL*m_pfnCreateObject;/ 构建函数抽象类为NULL CRuntimeClass *pBaseClasss;/
3、基类 CRuntimeClass对象指针; Static CRuntimeClass *pFirstClass;/ 链表头指针; CRuntimeClass *m_pNextClass;/ 下一指针;; MFC使用此类作为每个类的成员变量 了自己的 CRuntimeClass成员变量;使用宏定义为每个类定义DECLAR_DYNAMIC 和 IMPLENMENT_DYNAMIC宏使用这两个宏将CRuntimeClass对象不知不觉放到类之中;DECLARE_DYNMIC 宏定义如下:public : static CRuntimeClass class #class_name const ; v
4、irtual CRuntimeClass *GetRuntimeClass#用来告知编译器把两个字符串连接起来;假如使用这个宏: DELCARE_DYNMIC(CView);那么预编译器将生成以下代码:public : 名师归纳总结 static CRuntimeClass classCView; 第 2 页,共 21 页- - - - - - -精选学习资料 - - - - - - - - - virtual CRuntimeClass*GetRuntimeClassconst ; 以上代码仅仅是在类中定义CRuntimeClass对象,并定义一个返回 CRuntimeClass对象地址的函
5、数;留意 CRuntimeClass是 static 的,也就是说同一种类继承体系的对象共享一个CRuntimeClass对象;初始化对象的内容以及建立类型型录表需要使用 IMPLEMENT_DYNMIC宏;_IMPLEMENT_RUNTIMECLASSclass_name,base_class_name,0xFFFF,NULL; _IMPLEMENT_RUNTIMECLASS又是一个宏,它定义如下: base_class_name,wSchema,pfnNew static char _lpsz#class_name=#class_name; CRuntimeClass class_name
6、: class #class_name= _lpsz#class_name, sizeof class_name, wSchema,pfnNew, RUNTIME_CLASSbase_class_name,NULL ; 名师归纳总结 static AFX_CLASSINIT _init#class_name 第 3 页,共 21 页 & class_name:class #class_name; - - - - - - -精选学习资料 - - - - - - - - - CRuntimeClass *class_name:GetRuntimeClass const return &class_
7、name:class#classname; &class_name: class #class_name; AFX_CLASSINIT是一个类,看着跟宏定义似的,这样做很简单让人困惑;它用于将本节点连接到类型型录表,定义如下:class AFX_CLASSINIT public : AFX_CLASSINITCRuntimeClass*pNewClass / 构造函数 pNewClass-m_pNextClass=CRuntime:pFirstClass; CRuntimeClass:pFirstClass =pNewClass; ; 用法:class CWnd: public CCmdTar
8、get 名师归纳总结 - - - - - - -第 4 页,共 21 页精选学习资料 - - - - - - - - - public : DECLARE_DYNAMICCWnd; ; IMPLEMENT_DYNMICCWnd,CCmdTarget; 代码绽开后为;class CWnd: public CCmdTarget public: CRuntimeClass classCView; conststaticvirtual CRuntimeClass*GetRuntimeClass; staticchar _lpszCWnd=CWnd; CRuntimeClass CWnd:classCW
9、nd= _lpszCView , sizeofCWnd , FFFF,NULL , &Wnd:classCWnd , NULL; ; 名师归纳总结 static AFX_CLASSINIT _init_CWnd&CWnd:classCWnd; 第 5 页,共 21 页- - - - - - -精选学习资料 - - - - - - - - - Return &CWnd:classCWnd; 定义宏的过程很复杂, 但是一旦定义好之后, 在使用时仅仅两句 话就可以完成定义 CRuntimeClass对象并且连接类型型录链表的工 作;CObject 是全部类的基类,也是链表的头,此类应特殊定义,不 能
10、在 CObject内使用定义好的宏;class CObject public: CRuntimeClass*GetRuntimeClassconst ; virtualstatic CRuntimeClass classCObject; ; static char szCobject= CObject ; struct CRuntimeClass CObject:classCObject= szCObject ,sizeofCObject,0xFFFF,NULL, NULL,NULL ; 名师归纳总结 static AFX_CLASSINIT _init_CObject&Cobject:cla
11、ssObject; 第 6 页,共 21 页- - - - - - -精选学习资料 - - - - - - - - - CRuntimeClass *CObject:GetRuntimeClass const return &CObject:classCObject; 由于 CRuntimeClass对象是 static 成员变量,因此需要在类外初始 化;假如遗忘初始化将会报链接错误;CRuntimeClass*CRuntimeClass :pFirstClass=NULL;建好了类类型路表,要实现IsKindOf功能很简单;第一在CObject加上一个 IsKindOf函数,于是全部继承自此
12、类的类都具有类型识别的功 能;能够将某个 CRuntimeClass对象与类类型型录中的元素进行比较;如:class CObject public: const CRuntimeClass*pClassconstbool IsKindOf CRuntimeClass *pClassThis=GetRuntimeClass; while pClassThis if pClassThis=pClass 名师归纳总结 - - - - - - -第 7 页,共 21 页精选学习资料 - - - - - - - - - return true ; pClassThis=pClassThis-m_pBas
13、eClass; / 沿着基类查找; returnfalse; ;假如我们调用 CWnd *cw=new CWnd; cw-IsKindOfRUNTIME_CLASSCFrameWnd; RUNTIME_CLASS实际就是 &CFrameWnd:classCFrameWnd,它就是 CFrameWnd 的 static 的 CRuntimeClass类型成员;函数内利用GetRuntimeClass取得本类的 CRuntimeClass对象的地址,即&CWnd :classCWnd,然后进行比较;由于每一类型共用一个 static 的CRuntimeClass对象,因此属于同于类的 相同;动态创
14、建CRuntimeClass对象的地址每一类的构建函数可以记录在类型别录中,当获得一个类名称,通过查找类别型录表找出对应的元素,象;然后调用其构建函数产生新对在 CRuntimeClass中 m_pfnCreateObject即为构建函数首地址;为了实现动态创建,需要添加两个宏:名师归纳总结 - - - - - - -第 8 页,共 21 页精选学习资料 - - - - - - - - - DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE ;如: DECLARE_DYNCREATEclass_name static CObject *PASCAL CreateOb
15、ject; CObject*PASCAL class_name:CreateObject returnnew classname; _IMPLEMENT_RUNTIMECLASSclass_name,base_class_name, 0xFFFF,class_name:CreateObject 以 CFrameWnd 为例,以下程序代码:class CFrameWnd: public CWnd public : DECLEARE_DYNCREATECFrameWnd; ; IMPLEMENT_DYNCREATECFrameWnd,CWnd;绽开如下:名师归纳总结 - - - - - - -第
16、9 页,共 21 页精选学习资料 - - - - - - - - - class CFrame: public CWnd public: CRuntimeClass classCFrameWnd; const ; staticvirtual CRuntimeClass *GetRuntimeClassstatic CObject *PASCAL CreateObject; ; CObject _PASCAL CFrameWnd:CreateObject return new CFrameWnd; staticchar _lpszCFrameWnd=CFrameWnd ; CRuntimeCla
17、ss CFrameClass:classCFrameWnd= _lpszCFrameWnd,sizeofCFrameWnd,0xFFFF,CFrameWnd:CreateObject,RUNTIME_CALSSCWnd,NULL; static AFX_CLASSINIT _init_CFrameWnd &CFrameWnd:classCFrameWnd; CRuntimeClass*CFrameWnd:GetRunimeClass const return &CFrameWnd:classCFrameWnd; 留意对象构建函数为 static函数;名师归纳总结 - - - - - - -第
18、10 页,共 21 页精选学习资料 - - - - - - - - - 为了支持动态创建需要在CRuntimeClass内添加两个函数:CreateObject和 CRuntimeClass:Load 成员函数;CObject *CRuntimeClass: CreateObject Ifm_pfnCreateObject=NULL / 不支持动态创建; throw runtime_error 此类不支持动态创建 ; Return NULL; CObject*pObject=*m_pfnCreateObject; Return pObject; CRuntimeClass*PASCL CRun
19、timeClass:Load Char szClassName64; CRuntimeClass*pClass coutszClassName; for pClass=pFirstClass;pClass;pClass=pClass-m_pNextClass if strcmpszClassName,pClass-m_lpszClassName=0 名师归纳总结 - - - - - - -第 11 页,共 21 页精选学习资料 - - - - - - - - - return pClass; return NULL; 以下为类型识别及动态创建的完整代码:#include #include#in
20、cludeusing namespace std; class CObject; class CRuntimeClass public : char * m_lpszClassName; / 对象所属类名int m_nObjectSize; / 对象大小int m_wSchema; / 模式号 CObject*PASCAL*m_pfnCreateObject; / 构建函数 , 抽象类为 NULL CRuntimeClass *m_pBaseClasss; / 基类 CRuntimeClass 对象指针;static CRuntimeClass *pFirstClass; / 链表头指针; s
21、tatic CRuntimeClass *m_pNextClass; / 下一指针;public : CObject*CreateObject if m_pfnCreateObject=NULL coutreturn 该类型不支持动态创建! ! endl; NULL; CObject*pClass=*m_pfnCreateObject; return pClass; static CRuntimeClass*Load 名师归纳总结 - - - - - - -第 12 页,共 21 页精选学习资料 - - - - - - - - - couts; for CRuntimeClass*pClass
22、=pFirstClass;pClass;pClass=pClass-m_pBaseClasss if pClass-m_lpszClassName=s return pClass; return NULL; ; class AFX_CLASSINIT public : AFX_CLASSINITCRuntimeClass*pNewClass / 构造函数 pNewClass-m_pNextClass=CRuntimeClass:pFirstClass; CRuntimeClass:pFirstClass =pNewClass; ; /*/ /* 动态类型识别宏定义 / 与 CRuntimeCl
23、ass 类中的构建函数相区分;此处的 CreateObject 函数在每个类中都以static 成员函数存在,用以 / 初始化类型型录表,而 CRuntimeClass 中的 CreateObject 用于调用每个类的构建函数;仅 仅是函数名相同罢了;*/*/public : static CRuntimeClass Class#class_name; const ; virtual CRuntimeClass*GetRuntimeClass DECLARE_DYNAMICclass_name 名师归纳总结 static CObject*PASCAL CreateObject; 第 13 页,
24、共 21 页- - - - - - -精选学习资料 - - - - - - - - - &class_name:Class#class_name class CRuntimeClass class_name:Class#class_name = sizeof class_name,wSchema,pfnNew,RUNTIME_CLASSbase_class_name,NULL; static AFX_CLASSINIT _init#class_name RUNTIME_CLASSclass_name; CRuntimeClass *class_name:GetRuntimeClass cons
25、t return &class_name:Class#class_name; / 此处将 class_name 写成了 classname 花了一两天才查出来;啊啊啊啊啊;20220605 _IMPLEMENT_RUNTIMECLASSclass_name,base_class_name,0xFFFF,NULL CObject*PASCAL class_name:CreateObjectreturnnew class_name; _IMPLEMENT_RUNTIMECLASSclass_name,base_class_name,0xFFFF,class_name:CreateObje ct /
26、*/* 对 CObject特殊处理; */*/ class CObject public : CObject /coutCObject constructor.endl; CObject /coutCObject destructor.m_pBaseClasss 名师归纳总结 - - - - - - -第 14 页,共 21 页精选学习资料 - - - - - - - - - if pThis=pClass return true ; returnfalse; ; class CRuntimeClass CObject: ClassCObject= CObject, sizeofCObject
27、,0xFFFF,NULL,NULL,NULL ; static AFX_CLASSINIT _init_CObject&CObject: ClassCObject; CRuntimeClass *CObject:GetRuntimeClass return &CObject:ClassCObject; CRuntimeClass*CRuntimeClass:pFirstClass=NULL; /*/ /* */ /*/class CCmdTarget:public CObject DECLARE_DYNCREATECCmdTarget public : CCmdTarget /coutCCmd
28、Target constructor.endl; /CreateObject; CCmdTarget /coutCCmdTarget destructor.endl; ; IMPLEMENT_DYNCREATECCmdTarget,CObject ; class CWnd: public CCmdTarget 名师归纳总结 - - - - - - -第 15 页,共 21 页精选学习资料 - - - - - - - - - DECLARE_DYNCREATECWnd public : CWnd /coutCWnd constructorendl; CWnd /coutCWnd destruct
29、orendl; public : virtual bool Create coutCWnd:Createendl; CreateEx; return true ; bool CreateEx coutCWnd:CreateExendl; PreCreateWindow; return true ; virtual bool PreCreateWindow coutCWnd:PreCreateWindowendl; returntrue ; ; IMPLEMENT_DYNCREATECWnd,CCmdTarget class CView :public CWnd DECLARE_DYNCREAT
30、ECView public : CView /coutCView constructorendl; CView /coutCView destructorendl; 名师归纳总结 - - - - - - -第 16 页,共 21 页精选学习资料 - - - - - - - - - ; IMPLEMENT_DYNCREATECView,CWnd class CFrameWnd: public CWnd DECLARE_DYNCREATECFrameWnd public : CFrameWnd /coutCFrameWnd constructorendl; CFrameWnd /coutCFram
31、eWnd destructorendl; public : virtual bool Create coutCFrameWnd:Createendl; CreateEx; return true ; virtual bool PreCreateWindow coutCFrameWnd:PreCreateWindowendl; returntrue ; ; IMPLEMENT_DYNCREATECFrameWnd,CWnd class CWinThread:public CCmdTarget public : CWinThread /coutCWinThread constructorendl;
32、 CWinThread /coutCWinThread destructorendl; 名师归纳总结 public: 第 17 页,共 21 页- - - - - - -精选学习资料 - - - - - - - - - virtual bool InitInstance coutCWinThread:InitInstanceendl; returntrue ; virtual bool Run coutCWinThread:Runendl; returntrue ; ; class CWinApp: public CWinThread public : CWinApp /coutCWinApp
33、 Constructor endl; m_currentApp=this; CWinApp /coutCWinApp destructor endl; virtual bool InitApplication coutCWinApp:InitApplicationendl; returntrue ; virtual bool InitInstance coutCWinApp:InitInstanceendl; returntrue ; virtual bool Run cout CWinApp:Run endl; return CWinThread:Run; public : CWinApp*
34、m_currentApp; CFrameWnd*m_currentFrameWnd; ; 名师归纳总结 class CDocument:public CCmdTarget 第 18 页,共 21 页- - - - - - -精选学习资料 - - - - - - - - - public : CDocument /coutCDocument constructor endl; CDocument /coutCDocunment destructor endl; ; class CMyFrameWnd: public CFrameWnd DECLARE_DYNCREATECMyFrameWnd p
35、ublic : CMyFrameWnd /coutCMyFrameWnd constructor endl; Create; CMyFrameWnd /coutCMyFrameWnd destructor endl; ; IMPLEMENT_DYNCREATECMyFrameWnd,CFrameWnd class CMyWinApp: public CWinApp public : CMyWinApp /coutCMyWinApp constructor endl; CMyWinApp /coutCMyWinApp destructor endl; public : bool InitInstance 名师归纳总结 coutCMyWinApp:InitInstanceendl; 第 19 页,共 21 页 m_currentFrameWnd=new CMyFrameWnd; - - - - - - -精选学习资料 - - - - - - - - - return true ; ; CMyWinApp myApp; CWinApp*AfxGetApp ret