MFC入门培训手册范本.doc
一.学习MFC所应具备的基础知识1.Win32程序基础.2.面向对象与C+语言基础.1.Win32程序基础一) 几个重要概念:API:系统开放出来给程序员调用的函数.SDK:开发工具包,以API编写的程序也叫SDK程序.MFC:是一个构建在Windows API上的C+类库.Application Framework:指一个关连,包装良好的类库(MFC就是一个FrameWork).GUI:MDI:SDI:UI:二)Windows 编程模型1)以消息为基础,事件为驱动.(message base, event driven)2)用Win32 实现”Hello World!”.3)消息映射模型(message map)-一个重要的MFC概念.1.定义一个消息实体typdef struct MSGMAP_ENTRY_UINT nMessage;LONG (*pfn) (HWND, UINT, WPARAM, LPARAM); MSGMAP_ENTRY ;2.把消息和消息处理函数关联起来.MSGMAP_ENTRY messageEntries =WM_CREATE, OnCreate,WM_PAINT, OnPaint,WM_SIZE, OnSize,WM_COMMAND, OnCommand,WM_CLOSE, OnClose,WM_DESTROY, OnDestroy;MSGMAP_ENTRY commandEntries =IDM_ABOUT, OnAbout,IDM_EXIT, OnExit,#define dim(x) (sizeof(x)/sizeof(x0);3.更好的消息处理函数LRESULT CALLBACK WndProc(HWND hWnd, UINT nMessage, WPARAM wParam,LPARAM lParam)int i;for (i = 0; i < dim(messageEntries); i +)if (nMessage = messageEntriesi.nMessage)return (*messageEntriesi.pfn)(hWnd,nMessage,wParam,lParam);return DefWindowProc(hWnd,nMessage,wParam,lParam);LONG OnCommand(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)int i;for(i = 0; i < dim(commandEntries); i +)if (nMessage = commandEntriesi.nMessage)return (*commandEntriesi.pfn)(hWnd,nMessage,wParam,lParam);return DefWindowProc(hWnd, nMessage,wParam,lParam);LONG OnCreate(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam).LONG OnAbout(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam).4.Windows 程序的生死5.空闲的处理while(1)if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)if (msg.message = WM_QUIT)break;TranslateMessage();DispatchMessage(); elseOnIdle();4)第一个MFC程序- “Hello World!”/Hello.hclass CMyApp : public CWinApppublic: virtual BOOL InitInstance ();class CMainWindow : public CFrameWndpublic: CMainWindow ();protected: afx_msg void OnPaint ();afx_msg void OnLButtonDown(UINT nFlags,CPoint point);afx_msg void OnLButtonUp(UINT nFlags,CPoint point);afx_msg void OnMouseMove(UINT nFlags,CPoint point);afx_msg void OnNcDestroy(); DECLARE_MESSAGE_MAP ();#include <afxwin.h>#include <math.h>#include "Hello.h"CMyApp myApp;/ CMyApp member functionsBOOL CMyApp:InitInstance () m_pMainWnd = new CMainWindow; m_pMainWnd->ShowWindow (m_nCmdShow); m_pMainWnd->UpdateWindow (); return TRUE;/ CMainWindow message map and member functionsBEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd) ON_WM_PAINT ()ON_WM_LBUTTONDOWN()ON_WM_LBUTTONUP()ON_WM_MOUSEMOVE()ON_WM_NCDESTROY()END_MESSAGE_MAP ()CMainWindow:CMainWindow () Create (NULL, _T ("The Hello Application");void CMainWindow:OnNcDestroy()delete this;2.面向对象与C+语言基础.1)成员变量与成员函数-封装class CShapeprivate:int m_nColor;public:virture void Display() cout << ”shapen”;int SetColor(int nColor) m_nColor = nColor;2)代码复用-继承class CSquare : CShapepublic:virtual void Display() cout << “squaren”;void SetPosition(int nLeft, int nTop, int nRight, int nBottom);3)this指针CSquare square1, square2;square1.SetColor(1);square2.SetColor(2);编译后CSquare:SetColor(1, (CSquare *)&square1);CSquare:SetColor(2, (CSquare *)&square2);CShape 编译后class CShape.public:int SetColor(int nColor, (CShape *)this) this->m_nColor = nColor;4)虚拟函数与多态1.如何实现这样一个动作:CShape shape5;/包含五个对象分别为正方形,矩形,椭圆行,圆形,三角行for (int i = 0; i < 5; i +)shapei.Display();/分别画出5种图形2.如何判断一个指针指向的函数CShape shape, *pShape;CSquare square, *pSquare;pShape = (CShape *)□pShape-> SetPosition();pSquare = (CShape *)&shape;pSquare->SetColor(3);pShape = new CShape();pShape->Display();pSquare->Display();pShape = (CShape *)□pShape->Display();/为什么5)类型与实例剖析1.虚函数表(VTABLE-虚函数的实现基础)每个含虚函数的对象都有一个虚函数表,在内存中所占空间如下:每一个由此派生的类都有一个这样的虚函数表。当调用虚函数时,首先透过vptr找到虚函数表,再从虚函数表中找出虚函数的地址。当从基类派生时会继承基类的虚函数表,而当派生类改写虚函数时,编译器会用派生类的虚函数地址改写虚函数表。6)类的静态成员(静态成员函数与静态成员变量)静态成员属于类,而不属于对象。所以可以在还没创建对象之前就处理静态成员。1.静态变量的初试化静态成员的初始化只能放在实现档中,类的外面。因为放在类的构造函数中或在头文件中都可能被多次调用。Int Cshape:m_nStatic = 0;main().2.静态函数因为静态函数在对象生成之前就已经存在,所以无法处理对象的非静态变量。7)各种对象的生存周期(构造函数与解析函数)1.在栈中的对象 void func()Static int i;i +;Cfoo foo;/对象在栈(stack)中2.在堆中的对象void func()Cfoo *pfoo = new Cfoo;/对象在堆(heap)中3.全局对象(包括全局静态对象)Cfoo foo;在进入程序入口点之前创建;退出程序之前释放。4.局部静态对象 void func()static Cfoo foo;/局部静态对象8)执行期间类型识别C+ 的实现方式#include <typeinfo.h>void process(CObject *pObject)if (typeid(CObject) = typeid(*pObject);else if (typeid(CDocument) = typeid(*pObject);else if (typeid(CMyDoc) = typeid(*pObject);MFC的实现方式DECLARE_DYNCREATE, IMPLEMENT_DYNCREATE与CRuntimeClass9)异常处理try,catch,throwTRYCATCH(type, object)AND_CATCH(type,object)END_CATCHCATCH_ALL(object)AND_CATCH_ALL(object)END_CATCH_ALLEND_TRYTHROW()THROW_LAST()10)template请参考C+手册二.MFC入门MFC概观一.MFC类的层次结构。1.CObject1)RTTI(执行期类型识别)CAge a;a.IsKindOf(RUNTIME_CLASS(CAge)2)Persistence(对象保存)DECLARE_SERIAL(CMYCLASS)IMPLEMENT_SERIAL(CMYCLASS, CBASECLASS, VERSIONABLE_SCHEMA | 2)void Cline:Serialize(CArchive &ar)Cobject:Serialize(ar);/must call parent's serialize firstif (ar.IsStoring()ar<<m_Point1;elsear>>m_Point1;版本控制如下:void CLine:Serialize (CArchive& ar) CObject:Serialize (ar); if (ar.IsStoring () ar << m_Point1<<m_Point2; else UINT nSchema = ar.GetObjectSchema (); switch (nSchema) case 1: / Version 1 CLine ar >> m_Point1; break; case 2: / Version 2 CLine ar >> m_Point1 >> m_Point2; break; default: / Unknown version AfxThrowArchiveException (CArchiveException:badSchema); break; PS.MFC的CArchive's 可以插入和提取CObject的指针, 但不能处理CObject对象。这意味着下面可以正常工作:CLine *pLine = new Cline(CPoint(0, 0), Cpoint(100, 50);ar << pLine;但下面不行CLine Line = Cline(CPoint(0, 0), Cpoint(100, 50);ar << Line;但可以采用下面的变通方法:/serializeCLine line(CPoint(0, 0), Cpoint(100, 50);ar << &line;/DeserializeCline *pLine;ar>>pLine;Cline line = *pLine; /CLine must has a copy constructordelete pLine;更通用的方法是直接调用对象的Serialize 方法:/SerializeCline line(CPoint(0,0), Cpoint(100,50);line.Serialize(ar);/DeserializeCline line;line.Serialize(ar);3)Dynamci Creation(动态生成)DECLARE_DYNAMIC(CMyClass)IMPLEMENT_DYNAMIC(CMyClass, CBaseClass)run-time access to the class name and its position in the hierarchydiagnostic dumpingeg:dynamically create an object given its run-time classCRuntimeClass *pRuntimeClass = RUNTIME_CLASS(CMyClass);Cobject *pObject = pRuntimeClass->CreateObject();ASSERT(pObject->IsKindOf(RUNTIME_CLASS(CMyClass);4)Diagnostic(错误诊断)You must supply a CdumpContext argument here the dump output will go. The Debug version of MFC supplies a predefined CdumpContext object name afxDump that sends output to the debugger WindowCperson *pMyPerson = new Cperson;#ifdef _DEBUGpMyPerson->Dump(afxDump)#endif/dump to fileCFile f;if ( !f.Open(“dump.txt”, Cfile:modeCreate | Cfile:modeWrite)afxDump << “unable to open file” << “n”;exit(1);CDumpContext dc(&f);eg: a simple Class derive from Cobject override the Serialize functionnone override the Serialize function, use user defined function instead.Please refer to sample MFC-1作业:完善MFC-1中CShape, CRectangle, CEllipse类具有以上功能。2.MFC中宏介绍和常用全局函数介绍1)AfxGetAppAfxMessageBoxAfxGetMainWndAfxGetInstanceAfxRegisterClasseg:取得应用程序路径全名GetModuleFileName(AfxGetInstance(), szPath, _MAX_PATH);2)两种消息以WM开头的Windows 消息和各种菜单,控件消息(BN_CLICK)ON_WM_PAINT () 直接对应WM_PAINON_MESSAGE 自定义消息的处理afx_msg LRESULT OnMyMessage(HWND, nMessage, WPARAM, LPARAM);ON_COMMAND处理菜单加速键消息 afx_msg void OnMyCommand();ON_COMMAND_EX 处理函数返回TRUE代表该消息已处理,不再往下传,带一个COMMAND Id参数afx_msg BOOL OnMyCommandEx(UINT nID);控件发送给父窗体的通知消息ON_CONTROL(wNotificationCode, id, fx)eg:处理按钮的按下ON_BN_CLICKED(IDC_BUTTON_DEFAULTSETTINGS, CCommPropertyDlg:OnBnClickedButtonDefaultsettings)与下面语句是等同的ON_CONTROL(BN_CLICKED, IDC_BUTTON_DEFAULTSETTINGS, CCommPropertyDlg:OnBnClickedButtonDefaultsettings)SDK的做法是SendMessage WM_COMMAND 给父窗体,控件ID和信息包含在WPARAM,LPARAM 中。WM_NOTIFY-ON_NOTIFY() 一个更高级的消息,提供更多的信息。WPARAM contain the control IDLPARAM contain a point to NMHDR struct or some large struct that has an NMHDR struct as its first member.3)message reflectionA control send notify message to his parent window, and his parent resend the message to the control.-for code reusage purpose.Eg:1)CYellowEditWM_CTLCOLOR演试CYellowEdit 处理WM_CTLCOLOR 和父窗体处理WM_CTLCOLOR.2)自定义消息二.SDI/DIALOG1.构成这些筐架的类及主要成员1)DIALOG的运行过程m_pMainWndtheApp如何修改及处理SystemMenu。如何替换主对话框消息映射和数据交换CWinAppCWnd2)SDICFrameWnd,CView,CDocument之间的关系(CMyDoc *)(CMainFrame *)AfxGetMainWnd()->GetActiveDocument()(CMainFrame *)(CMainFrame *)AfxGetMainWnd()->GetActiveFrame()(CMyView *)(CMainFrame *)AfxGetMainWnd()->GetActiveView()(CMainFrame *)(CMainFrame *)AfxGetMainWnd()->GetActiveWindow()(CMyApp *)AfxGetApp()CFrameWnd 元素CStautsBarCtoolBarCMenu作业:1)不用IDE的功能自己动手作出Dlg/SDI(CFramwWnd Cview)筐架2)并加上CMenu,CToolBar,CStatusBar(要有实际功能)2.常用功能,类及控件的介绍Ctime/CTimeSpanCString(Multi byte char, Wide char, Unicode)CArray(数组操作)Simple value types(CFileTime, CPoint, CSize)CFile文件操作目录操作注册表操作GetPrivateProfileString/WritePrivateProfileString各种常用控件(CEdit, CButton, CStatic, CComboBox, CListCtrl, .)控件在Win32编程中的使用.3.高级控件CToolBarCStatusBarCPropertySheetCPropertyPage4.Collection Class5.CDC(图形设备环境)作业:综合以上功能用MFC实现一个应用。三.MFC高级应用1.自绘控件2.多线程(互斥体,事件,信号量,临界区)3.对象的保存与恢复四.DOCUMENT-VIE-FRAME架构(MDI)的研究参考书Win32编程Windows核心编程MFC编程Programming Windows With MFC Second Edition-jeff prosise深入浅出MFC编程-侯捷C+语言:thinking in C+Effective C+-Scoot Meyers