Lesson04_MFC骨干程序.doc_第1页
Lesson04_MFC骨干程序.doc_第2页
Lesson04_MFC骨干程序.doc_第3页
Lesson04_MFC骨干程序.doc_第4页
Lesson04_MFC骨干程序.doc_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Lesson 04 MFC骨干程序本课讲述一个完整的MFC应用程序骨干,包括工具栏、状态栏以及很重要的Document/View结构概念。一、Document/View支撑应用程序在程序中不论什么类型,数据总是有体有面,实际的数据数值就是体,显示在屏幕上(甚至打印机上)的画面就是面。“数值的处理”应该使用字节、整数、浮点数、链表、数组等数据结构,而“数值的表现”应该使用绘图工具,如坐标系统、笔刷颜色、点线圆弧、字形,如下图:图1 Document是数据的体,View是数据的面除了负责显示外,View还负责程序与使用者之间的交谈接口。使用者对数据的编辑、修改都需要依靠窗口上的鼠标和键盘操作才能完成,这些消息都由View接受后再通知Ducument,如下图: 图2 View负责与使用者接触 Document/View的价值在于,这些MFC类已经把一个应用程序所需的“数据处理与显示”的函数空壳都设计好了,都是虚函数,所以程序员可以(也应该)在派生类中改写它们。有关文件读写的操作在CDocument的Serialize函数中进行,有关画面显示的操作在CView的OnDraw或OnPaint函数中进行。二、MFC骨干程序以一个多文档程序Scribble为例,说明MFC骨干程序。图3是一个多文档应用程序所使用的MFC类的层次结构图:图3 多文档应用程序使用的MFC类1 Scribble程序中各类的相关数据如下:表1 MDI程序中的主要类类名称基类类声明于类定义于CScribbleAppCWinAppScribble.hScribble.cppCMainFrameCMDIFrameWndMainfrm.hMainfrm.cppCChildFrameCMDIChildWndChildfrm.hChildfrm.cppCScribbleDocCDocumentScribbleDoc.hScribbleDoc.cppCScribbleViewCViewScribbleView.hScribbleView.cppCAboutDlgCDialogScribble.cppScribble.cpp2 骨干程序(MDI)使用的所有MFC类表2 MDI程序使用的所有MFC类MFC类名称用户类名称功 能CWinAppCScribbleApp应用程序对象CMDIFrameWndCMainFrameMDI主窗口CMultiDocTemplate直接使用管理Document/ViewCDocumentCScribbleDoc文档,负责数据结构与文件操作CViewCScribbleView视图,负责数据的显示与打印CMDIChildWndCChildFrameMDI子窗口CToolBar直接使用工具栏CStatusBar直接使用状态栏CDialogCAboutDlg About对话框3 程序中的九个对象如图4 图4 Scribble程序中的九个对象注意:虚线框表示应用程序通常不必改写该基础类,可以直接用4 程序流程说明如下:(1)(4)theApp应用程序对象:AfxWinMain()内部执行与前一课相同。(5)改写InitInstance虚函数。(6)new一个CMultiDocTemplate对象,该对象规划Document、View以及Document Frame窗口三者之间的关系。(7)new一个CMyMDIFrameWnd对象,作为主窗口对象。(8)调用LoadFrame,产生主窗口并加挂菜单等元素,指定窗口标题、文件标题、文件扩展名等(关键在IDR_MAINFRAME常量)。LoadFrame内部将调用Create,后者将调用CreateWindowEx,于是触发WM_CREATE消息。(9)由于在CMainFrame之中拦截WM_CREATE(利用ON_WM_CREATE宏),所以WM_CREATE产生之际Framework会调用OnCreate。在此为主窗口挂上工具栏和状态栏。(10)回到InitInstance,执行ShowWindow显示窗口。(11)InitInstance结束,回到AfxWinMain,执行Run,进入消息循环。(12)消息经过Message Routing机制,在各类的Message Map中寻求其相应的处理程序。WM_COMMAND/ID_FILE_OPEN消息将由CWinApp:OnFileOpen函数处理,此函数由MFC提供,在显示过File Open对话框之后调用Serialize函数。(13)改写Serialize函数进行我们自己的读写操作。(14)WM_COMMAND/ID_APP_ABOUT消息将由OnAppAbout函数处理。(15)OnAppAbout函数利用CDialog的性质很方便地产生一个对话框。5 Document Template的意义程序每打开一份文件(数据),就会产生三份对象:(1) 一份Document 对象(数据内容)(2) 一份View对象(数据表象)(3) 一份CMDIChildWnd对象,其作为外框窗口(容纳数据表象)这三份对象由Document Template对象来管理,关键在CMultiDocTemplate:BOOL CScribbleApp:InitInstance()CMultiDocTemplate* pDocTemplate;pDocTemplate = new CMultiDocTemplate(IDR_SCRIBBTYPE,RUNTIME_CLASS(CScribbleDoc),RUNTIME_CLASS(CChildFrame), / custom MDI child frameRUNTIME_CLASS(CScribbleView);AddDocTemplate(pDocTemplate); 如果程序支持不同的数据格式,如TEXT和BITMAP,则需要不同的Document Template:BOOL CMyWinApp:InitInstance()CMultiDocTemplate* pDocTemplate;pDocTemplate = new CMultiDocTemplate(IDR_TEXTTYPE,RUNTIME_CLASS(CTextDoc),RUNTIME_CLASS(CChildFrame), / custom MDI child frameRUNTIME_CLASS(CTextView);AddDocTemplate(pDocTemplate); pDocTemplate = new CMultiDocTemplate(IDR_BMPTYPE,RUNTIME_CLASS(CBmpDoc),RUNTIME_CLASS(CChildFrame), / custom MDI child frameRUNTIME_CLASS(CBmpView);AddDocTemplate(pDocTemplate); CMultiDocTemplate的构造函数:CMultiDocTemplate( UINT nIDResource, CRuntimeClass* pDocClass,CRuntimeClass* pFrameClass,CRuntimeClass* pViewClass ); 参数:nIDResourceSpecifies the ID of the resources used with the document type. This may include menu, icon, accelerator table, and string resources. 注意:不同种类的资源可以使用相同的IDIDR_SCRIBBTYPE ICON DISCARDABLE resScribbleDoc.icoIDR_SCRIBBTYPE MENU PRELOAD DISCARDABLESTRINGTABLE PRELOAD DISCARDABLE BEGIN IDR_MAINFRAME Scribble IDR_SCRIBBTYPE nScribbnScribbnnnScribble.DocumentnScribb Document” ENDpDocClassPoints to the CRuntimeClass object of the document class. This class is a CDocument-derived class you define to represent your documents.pFrameClassPoints to the CRuntimeClass object of the frame-window class. This class can be a CMDIChildWnd-derived class, or it can be CMDIChildWnd itself if you want default behavior for your document frame windowspViewClassPoints to the CRuntimeClass object of the view class. This class is a CView-derived class you define to display your documents关于字符串资源:以n分隔为七个子字符串如本例中:nScribbnScribbnnnScribble.DocumentnScribb Document按顺序各子字符串意义:每个子字符串都可在程序进行过程中取得,调用CDocTemplate:GetDocString并在第二个参数中指定索引值(17)即可。最好以CDocTemplate所定义的七个常量代替索引值。CDocTemplate的七个常量定义:(文件:AFXWIN.H )#ifdef _AFXDLLclass CDocTemplate : public CCmdTarget#elseclass AFX_NOVTABLE CDocTemplate : public CCmdTarget#endifenum DocStringIndexwindowTitle, / default window titledocName, / user visible name for default documentfileNewName, / user visible name for FileNew/ for file based documents:filterName, / user visible name for FileOpenfilterExt, / user visible extension for FileOpen/ for file based documents with Shell open support:regFileTypeId, / REGEDIT visible registered file type identifierregFileTypeName, / Shell visible registered file type name;程序中可以象下面这样:CString strDefExt, strDocName;pDocTemplate-GetDocString(strDefExt, CDocTemplate:filterExt);pDocTemplate-GetDocString(strDocName, CDocTemplate:docName);七个子字符串的具体意义:Index意义1. CDocTemplate:windowTitle主窗口标题栏上的字符串,SDI程序要指定,MDI程序不需要指定,以IDR_MAINFRAME字符串为默认值。2. CDocTemplate:docName文件基底名,加流水号码为新文件名,未指定文件默认名称为“Untitled”3. CDocTemplate:fileNewName文件类型名称,程序支持多文件,此字符串会显示在新建文件对话框,否则不显示,新建文件时也不会显示对话框。4. CDocTemplate:filterName 打开文件时的过滤字符串5. CDocTemplate:filterExt文件扩展名,未指明时不能在打开文件对话框中处理该类文件6. CDocTemplate:regFileTypeId注册表中注册的文件类型,未指明则无法注册,鼠标拖放功能受影响7.CDocTemplate:regFileTypeName也是存储在注册表中的文件类型。6 Document/View设计(1)文件读写CDocument中的Serialize函数。(2)数据的显示与编辑等Document Frame窗口收到WM_PAINT消息,窗口内的View的OnPaint函数被调用,OnPaint又调用OnDraw。所以为了显示数据一般要改写OnDraw。OnPaint一般只输出到屏幕而不到打印机。为了接受编辑操作,一般在View中接受鼠标或键盘消息并处理。 例如:afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);afx_msg void OnMouseMove(UINT nFlags, CPoint point);7 主窗口的诞生建立MDI主窗口:new一个CMDIFameWnd对象;调用LoadFrame函数LoadFrame源代码如下:(文件:WINFRM.CPP)BOOL CFrameWnd:LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,CWnd* pParentWnd, CCreateContext* pContext)/ only do this onceASSERT_VALID_IDR(nIDResource);ASSERT(m_nIDHelp = 0 | m_nIDHelp = nIDResource);m_nIDHelp = nIDResource; / ID for help context (+HID_BASE_RESOURCE)CString strFullString;if (strFullString.LoadString(nIDResource)AfxExtractSubString(m_strTitle, strFullString, 0); / first sub-stringVERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);/ attempt to create the windowLPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);LPCTSTR lpszTitle = m_strTitle;if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault, pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext)return FALSE; / will self destruct on failure normally/ save the default menu handleASSERT(m_hWnd != NULL);m_hMenuDefault = :GetMenu(m_hWnd);/ load accelerator resourceLoadAccelTable(MAKEINTRESOURCE(nIDResource);if (pContext = NULL) / send initial updateSendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);return TRUE;窗口产生之际会发出WM_CREATE消息,CMainFrame:OnCreate会被执行,在那里进行工具栏和状态栏的建立。LoadFrame函数的参数(IDR_MAINFRAME)用来设定窗口所使用的资源。IDR_MAINFRAME ICON DISCARDABLE resScribble.icoIDR_MAINFRAME MENU PRELOAD DISCARDABLEIDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURESTRINGTABLE PRELOAD DISCARDABLE BEGIN IDR_MAINFRAME Scribble(将作为主窗口的标题) ENDLoadFrame执行如图5所示:图5 构建MDI主窗口8 工具栏和状态栏的产生(Toolbar&Statusbar)(1)工具栏和状态栏对象声明(2)OnCreate函数中与工具栏和状态栏的产生和设定有关的操作IDR_MAINFRAME在RC文件中代表两种与工具栏有关的资源:BITMAP和TOOLBAR状态栏中有关indicators的七种定义(文件:AFXRES.H) / Mode indicators in status bar - these are routed like commands#define ID_INDICATOR_EXT 0xE700 / extended selection indicator#define ID_INDICATOR_CAPS 0xE701 / cap lock indicator#define ID_INDICATOR_NUM 0xE702 / num lock indicator#define ID_INDICATOR_SCRL 0xE703 / scroll lock indicator#define ID_INDICATOR_OVR 0xE704 / overtype mode indicator#define ID_INDICATOR_REC 0xE705 / record mode indicator#define ID_INDICATOR_KANA 0xE706 / kana lock indicator例子程序中使用的三种:9 工具栏和状态栏的产生(Toolbar&Statusbar)每一个派生自CCmdTarget的类都可以有自己的Message Map用于处理消息。先在类声明处加DECLARE_MESSAGE_MAP宏,然后在.cpp文件中使用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP两个宏,宏中间的就是消息与处理函数的对应关系。例如CScribbleApp类中的消息映射:BEGIN_MESSAGE_MAP(CScribbleApp, CWinApp)/AFX_MSG_MAP(CScribbleApp)ON_COMMAND(ID_APP_ABOUT, OnAppAbout)/ NOTE - the ClassWizard will add and remove mapping macros here./ DO NOT EDIT what you see in these blocks of generated code!/AFX_MSG_MAP/ Standard file based document commandsON_COMMAND(ID_FILE_NEW, CWinApp:OnFileNew)ON_COMMAND(ID_FILE_OPEN, CWinApp:OnFileOpen)/ Standard print setup commandON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp:OnFilePrintSetup)END_MESSAGE_MAP()10标准菜单File/Edit/View/Window/help MDI程序一般会有两组菜单:一种是当没有任何子窗口(文件窗口)存在时出现(本例代码是IDR_MAINFRAME),另一组是当有任何子窗口(文件窗口)存在时出现(本例代码是IDR_SCRIBTYPE)。菜单内容命令项ID默认的处理函数预有关联FileNewID_FILE_NEWCWinApp:OnFileNewNoOpenID_FILE_OPENCWinApp:OnF

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论