MFC 详解一之重要的类
来源:互联网 发布:ikbc c87换mac键位 编辑:程序博客网 时间:2024/06/06 07:42
最近好久没用vs下的mfc工程了,感觉对于mfc越来越感到莫名的陌生不了解,网上也看到好多关于mfc的深入了解的博客,其中liyi268这位前辈对于mfc六大机制总结的很到位,还有就是《深入浅出 MFC》侯俊杰的这本书更是没话说,一直犹豫要不要写mfc方面的博客,最终想想为什么不写呢,也许自身的水平有限,也许投入写mfc博客的时间会比较长,但是自身总结一方面能加深印象,促使自己更加深入的了解,一方面也希望大神们给予指证,发现一些自身没发现的问题。
正文开始前,想先总结下mfc类层次关系中几个重要的类和它里面一些重要的函数作用
一:CObject :
CObject 是大多数MFC类的根类或基类。CObject类有很多有用的特性:对运行时类信息的支持,对动态创建的支持,对串行化的支持,对象诊断输出,以下是摘自mfc里的CObject类的一部分
class AFX_NOVTABLE CObject{public:virtual CRuntimeClass * GetRuntimeClass() const; // (1)public:// 与运行时类信息、串行化相关的函数BOOL IsSerializable() const;BOOL IsKindOf(const CRuntimeClass* pClass) const;// (2)// Overridablesvirtual void Serialize(CArchive& ar);// #if defined(_DEBUG) || defined(_AFXDLL)virtual void AssertValid() const;//virtual void Dump(CDumpContext& dc) const;#endifpublic:static const CRuntimeClass classCObject; #ifdef _AFXDLLstatic CRuntimeClass* PASCAL _GetBaseClass();static CRuntimeClass* PASCAL GetThisClass();#endif};
接下来对CObject做一些简单的解析
(1): CRuntimeClass在MFC中定义为一个数据结构,在文件AFX.H中声明,它是用来串起MFC从CObject继承下来的所有类(相当于一根绳,只要你牵住绳的一头你就可以得到绳上的所有数据)通过关联(即通过链表的方法连接起来)CRuntimeClass对象从而能在运行时得到类的实例或者它的基类
每个从CObject中派生的类都有一个CRuntimeClass对象同它关联以完成在运行时得到类实例的信息或者是它的基类。 在afx.h中CRuntimeClass的定义如下:
struct CRuntimeClass{LPCSTR m_lpszClassName; //类名int m_nObjectSize; //包含CRuntimeClass对象的类sizeof的大小UINT m_wSchema; // 分类编号(对不可分类的类,该值为-1)。CObject* (PASCAL* m_pfnCreateObject)(); // 指向一个建立实例的构造函数,创建一个类的对象,抽象类则返回NULL,运行时类型识别时返回的是NULL,而动态创建有效// CObject*(* m_pfnCreateObject)(); 指向函数的指针 如:int (*fn)();#ifdef _AFXDLLCRuntimeClass* (PASCAL* m_pfnGetBaseClass)();//是一个指向函数的指针,该函数返回基类的CRuntimeClass结构。 #elseCRuntimeClass* m_pBaseClass; // 如果你的应用程序是静态地链接到MFC的,则是一个指向基类的CRuntimeClass结构的指针。#endif//以上m_pBaseClass的指针(函数)是MFC运行时确定类层次的关键,它一个简单的单向链表CObject* CreateObject(); //这个函数给予CObject派生类运行时动态建立的能力,从CObject派生的类可以支持动态创建,这是在运行时创建一个指定类的对象的能力//例如,文档,视和框架类就应该支持动态创建。CreateObject成员函数可以用来实现这个功能,在运行时为这些类创建对象。BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const; //判断是不是一个基类的子类//使用它可以判断某类是否是从pBaseClass指向的类在派生来。*/void Store(CArchive& ar) const;static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);CRuntimeClass* m_pNextClass; // linked list of registered classes};
m_pBaseClass指向基类的CRuntimeClass结构指针,通过m_pNextClass就可以将类型关系连接起来,只要拿住表头pFirstClass就能拿到整一张关系
继承链表
而GetRuntimeClass()这函数,就可以拿到这跟绳子的头。
(2)Iskindof() ,能在执行期侦测某个对象是否属于某种类
它将参数所指定的某个CRuntimeClass
BOOL CObject::IsKindof(const CRuntimeClass *pClass) const{CRuntimeClass * pClassThis = GetRuntimeClass();while(pClassThis != NULL){if(pClass == pClassThis){return TRUE;}pClassThis = PClassThis->m_pBaseClass;}return FALSE;}
注意的是追踪路线,是靠m_pBaseClass,并不是m_pNextClass,
例如:CView * PView = new CView();
PView ->IsKindof(RUNTIME_CLASS(CWinApp));
IsKindof()函数内的参数就是 &CWinApp::classCWinApp,而GetRuntimeClass()先取得的是&CView::classCView,之后(CView,CWnd,CCmdTarget,CObject)循序向上查找
二:CCmdTarget
该类派生于CObject,它封装了MFC的消息映射机制,希望接收系统事件和窗口消息的类都从它派生,如CDocument和CWnd分支。此外,在系统繁忙,无法响应窗口消息时,鼠标光标应该显示为沙漏形等待状态,CCmdTarget类封装了3个成员函数完成该功能。封装COM的 IDispatch接口是它的另一项主要功能。IDispatch是COM的标准接口,不含指针操作的语言(如VB)以及描述性语言(如Web脚本语言和VBA)都通过该接口操作COM组件。CCmdTarget类以一种类似消息映射的机制提供IDispatch接口,所以使用MFC可以轻松地编写AUTOMATION客户程序和组件,
对于Com编程,以前在基于Directshow播放器中有用到过,这里简单提一下,具体Com细节待总结后再分享出来,所谓COM(Componet Object Model,组件对象模型),是一种说明如何建立可动态互变组件的规范,可以将一个单独的复杂程序划分为多个独立的模块进行开发,这里的每一个独立模块都是一个自给自足的组件,可以采取不同的开发语言去设计每一个组件,在运行时将这些组件通过接口组装起来以形成所需要的应用程序,遵循COM标准的任何一个组件都是可以被用来组合成应用程序的。至于对组件采取的是何种编程语言则是无关紧要的,可以自由选取,真正意义上的组件,应具备如下特征:
1) 实现了对开发语言的封装。
2) 以二进制形式发布。
3) 能够在不妨碍已有用户的情况下被升级。
4) 在网络上的位置必须能够被透明的重新分配。
总结下CCmdTarget这个类的作用:
1)消息发送,virtual BOOL OnCmdMsg(UINT nID,int nCode,void* pExtra,AFX_CMDHANDLERINFO* pHandlerInfo );
在运行时,OnCmdMsg把命令分派到其它对象上或者调用CCmdTarget::OnCmdMsg(此函数进行真正的消息映射查找)自己处理命令。MFC应用程序通过BEGIN_MESSAGE_MAP,END_MESSAGE_MAP()这两个宏,会为CCmdTarget派生类创建一个称为<消息映射表>的<静态数据结构>,该消息映射结构将消息映射到对象所对应的消息处理函数上,当从根据消息队列中取得该消息时,就会根据这张映射结构通知相应的消息函数处理消息。
2)设置光标,成员含数BeginWaitCursor()将光标改为沙漏形状,提示程序正在进行某种操作。当操作完成时,含数EndWaitCursor()用于将光标改回到 BeginWaitCursor()之前的形状。当处于等待状态时由于某些外部操作改变了光标形状后,含数 RestoreWaitCursor()用于将光标还原为等待状态3
3)支持自动化:CCmdTarget类支持程序通过Com接口进行交互操作
三:CWinThread
class CWinThread : public CCmdTarget{public:CWinThread();BOOL CreateThread(DWORD dwCreateFlags = 0, UINT nStackSize = 0,LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);// AttributesCWnd* m_pMainWnd; // 保存指向应用程序的主窗口的指针(usually same AfxGetApp()->m_pMainWnd)CWnd* m_pActiveWnd; // 指向容器应用程序的主窗口BOOL m_bAutoDelete; // 指定线程结束时是否要销毁对象 HANDLE m_hThread; // 当前线程的句柄DWORD m_nThreadID; // 当前线程的ID// OperationsDWORD SuspendThread();//增加一个线程的挂起计数DWORD ResumeThread();//减少一个线程的挂起计数 BOOL PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam);//向另外的CWinThread对象传递一条消息// Overridablesvirtual BOOL InitInstance();//重载以实现线程实例的初始化virtual int Run(); //线程的具有消息收发功能的控制函数,可重载以定制缺省的消息循环virtual BOOL PreTranslateMessage(MSG* pMsg);//在消息被发送到Windows函数TranslateMessage和DispatchMessage之前过滤消息virtual BOOL OnIdle(LONG lCount); // 重载以进行线程特定的空闲操作 virtual int ExitInstance(); // 重载以进行线程终止时的清理工作 // Advanced: handling messages sent to message filter hookvirtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg);//在特定的消息到达应用程序之前截获消息virtual CWnd* GetMainWnd();};上面载录的是一些相对重要的函数方法,基本上一个派生CWinThread的子类,里面重写InitInstance(),ExitInstance(),Run()父类的虚函数,再调用CreateThread()方法;就会进到子类重写的Run()函数,进行线程处理,而里面加个标志位就能进行线程循环,而重写PreTranslateMessage(MSG * pMsg)函数,在对消息DispatchMessage派发消息之前就能截取所有消息。
四:CWinApp
AfxGetApp 返回指向应用程序的CWinApp对象的指针.
AfxGetInstanceHandle 返回应用程序的实例的句柄.
GfxGetResoureHandle 返回程序的资源的句柄.
AfxGetAppName 返回应用程序的名称.
五:CDocument
在文档/视图结构中,文档的主要任务通常是对数据库进行管理和维护,数据将保存在文档类的成员变量中,视图通过对这些变量的访问来获取或送回数据,并能通过这种方式来更新并显示数据。
文档还负责将数据存储到永久的存储介质中,通常是磁盘或数据库,这个存取过程称之为串行化。
此外,文档还可以处理来自菜单、工具栏、加速键等对象的命令消息(WM_ COMMAND)。除WM_COMMAND外,文档不能处理其他的Window消息。
程序框架提供了两个文档模板类:CSingleDocTemplate和CMultiDocTemplate,分别用于支持SDI应用程序和MDI应用程序。
SDI应用程序一次只能使用一种类型的文件,如Windows中的画图、记事本等。
MDI应用程序则可以同时使用多种类型的文件,如Word、Excel等。
六:CWnd
CWnd类提供了微软基础类库中所有窗口类的基本功能HWND Handle;
pCWnd=FromHandle(Handle);
Handle=GetSafeHwnd(pCWnd);
- MFC 详解一之重要的类
- MFC几个重要的基类
- 2.C++的重要性质(深入浅出MFC之读书笔记)
- Java重要类详解之ArrayList类
- Java重要类之LinkList类详解
- 学习NS2重要要把握几个重要的类一
- MFC的四个重要类之间的关系
- 重要的属性一
- c++之重要的关键字(一)---static
- Android之6.0上的重要变化(一)
- lwip学习笔记之几个重要的数据结构详解
- MFC的CString类详解
- MFC之集合类(一)
- MFC几个比较重要的全局函数
- MFC中三个重要的宏
- MFC之CAsyncSocket详解
- MFC之CAsyncSocket详解
- MFC之CAsyncSocket详解
- PHP代码优化24条真经
- 求出所有不同的二叉搜索树(BST)
- imageNamed与imageWithContentsOfFile加载图片的区别
- 猴子搬香蕉问题
- Android的线程与进程
- MFC 详解一之重要的类
- jQuery.ajax向后台传数组
- HTML5新特性——HTML5 地理定位
- sqlserver 检查表索引及sql语句执行情况
- Linux那些事儿 之 戏说USB(13)接口是设备的接口(二)
- Ogre 3D与材质 -----OGRE 3D 1.7 Beginner‘s Guide中文版 第七章
- erase用法注意事项
- iOS UIControl事件详解,按钮事件详解:UIControlEvent
- C语言 一个球从100米高的自由落下,每次落地后反跳回原高度的一半,再落下,再反弹。求第 10次落地时,共经过多少米,第10次反弹多高