MFC单文档视图穷追猛打_第1页
MFC单文档视图穷追猛打_第2页
MFC单文档视图穷追猛打_第3页
MFC单文档视图穷追猛打_第4页
MFC单文档视图穷追猛打_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

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

文档简介

1、MFC单文档视图穷追猛打目录第一章找回WinMain函数 2第二章InitApplication()函数 2第三章InitInstance ()函数 3第一节:new CSingleDocTemplate 3第二节:AddDocTemplate(pDocTemplate); 5第三节:ProcessShellCommand(cmdInfo) 5第一段AfxGetApp()->OnCmdMsg() 6第二段OnFileNew(); 6第四节 :m_pMainWnd->ShowWindow(SW_SHOW)

2、; /显示窗口 8第五节 :m_pMainWnd-> UpdateWindow (); /重画窗口 8第四章pApp->Run函数 8第五章总结 8  本文将针对一个单文档来描述MFC的文档/视图结构,他直接打开MFC的源代码进行分析,在分析过程中去掉了无关的部分。所以第一步就是要创建一个称为First得工程,文档类型是单文档,下文将围绕这个工程来讲的。第一章找回WinMain函数首先在VC的安装路径中找到WINMAIN.CPP文件,AfxWinMain函数就是VC编译器的入口,去掉一些不重要的东西后得到如下得程序。int AFXA

3、PI AfxWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)int nReturnCode = -1;CWinApp* pApp = AfxGetApp(); /获取应用程序类的指针与文档视图无关。AfxWinInit(hInstance, hPrevInstance,lpCmdLine,nCmdShow); /与文档视图无关。pApp->InitApplication();  /初始化应用程序详见下文。pApp->InitInstance();

4、60;    /最重要下面祥述nReturnCode = pApp->Run();/消息循环直到应用程序被关闭。与文档视图无关。AfxWinTerm();      /与文档视图无关。return nReturnCode;/整个应用结束。下面分节讲述。第二章InitApplication()函数在文件Appcore.cpp文件中InitApplication如下:BOOL CWinApp:InitApplication() if (CDocManager:pStaticDocManager != N

5、ULL)   /这段和我们关系不大,暂时不理它   if (m_pDocManager = NULL)   m_pDocManager = CDocManager:pStaticDocManager;  CDocManager:pStaticDocManager = NULL;  if (m_pDocManager != NULL)  m_pDocManager->AddDocTemplate(NULL); else  

6、CDocManager:bStaticInit = FALSE;  /*我们的程序将会执行到这句,表示文档类用动态方式创建,也就是说用RUNTIME_CLASS来创建的(详见下文)。*/ return TRUE;  说明:CDocManager类是一个不公开的类,他主要用来管理多文档模板对象的,对于单文档只有一个文档模板这个类不是很重要,但还是用它管理文档模板的;本文只在相关之处作说明。bStaticInit是它的一个静态成员。第三章InitInstance ()函数  它一般被重载,在First工程中,InitInstance中和文档视图类有关的程序有

7、下面的一些: CSingleDocTemplate* pDocTemplate;  /定义指针 pDocTemplate = new CSingleDocTemplate(  IDR_MAINFRAME,  RUNTIME_CLASS(CFirstDoc),  RUNTIME_CLASS(CMainFrame),  RUNTIME_CLASS(CFirstView);    /这条语句的作用见第一段 AddDocTemplate(pDocTemp

8、late); CCommandLineInfo cmdInfo;    /定义一个对象 ParseCommandLine(cmdInfo);    /解析命令行并发送参数,与文档视图无关 if (!ProcessShellCommand(cmdInfo)   /这是最重要的详见的三段  return FALSE; m_pMainWnd->ShowWindow(SW_SHOW);      /显示窗口&

9、#160;m_pMainWnd->UpdateWindow();第一节:new CSingleDocTemplatenew CSingleDocTemplate其实就是创建一个CSingleDocTemplate对象并调用他的构造函数,要讲清楚这句话,首先必须明白RUNTIME_CLASS结构,RUNTIME_CLASS结构定义如下:#define RUNTIME_CLASS(class_name) (CRuntimeClass*)(&class_name:class#class_name)于是这句话展开后如下(关于符合#的具体意义参见MSDN): pDocTempla

10、te = new CSingleDocTemplate(IDR_MAINFRAME,(CRuntimeClass*)(&CFirstDoc:classCFirstDoc),(CRuntimeClass*)(&CMainFrame:classCMainFrame),(CRuntimeClass*)(&CFirstView:classCFirstView);这时我们会发现CfirstDoc,CmainFrame,CfirstView各会多冒出一个静态成员出来,它究竟在哪里呢?查看这三个类的定义我们会发现每个类定义都有一个宏DECLARE_DYNCREATE,在实现文件中有另

11、外一个宏IMPLEMENT_DYNCREATE。下面把这些宏的展开情况列出如下:(1)文档类DECLARE_DYNCREATE(CFirstDoc) 展开后为:public:   static const CRuntimeClass classCFirstDoc; /这就是上面所说的那个静态成员 virtual CRuntimeClass* GetRuntimeClass() const;  static CObject* PASCAL CreateObject();IMPLEMENT_DYNCREATE(CFirstDoc, CDocument)

12、60; 展开后为: CObject* PASCAL CFirstDoc:CreateObject()   return new CFirstDoc;  const CRuntimeClass CFirstDoc:classCFirstDoc=   "CFirstDoc", sizeof(class CFirstDoc), 0xFFFF, CFirstDoc:CreateObject,    (CRuntimeClass*)(&CDocument:classCDocument),

13、 NULL ; CRuntimeClass* CFirstDoc:GetRuntimeClass() const    return (CRuntimeClass*)(&CFirstDoc:classCFirstDoc); (2)视图类DECLARE_DYNCREATE(CFirstView)  展开后为:public:   static const CRuntimeClass classCFirstView;  virtual CRuntimeClass* GetRuntimeClass() const; 

14、0;static CObject* PASCAL CreateObject();IMPLEMENT_DYNCREATE(CFirstView, CView)  展开后为: CObject* PASCAL CFirstView:CreateObject()   return new CFirstView;  const CRuntimeClass CFirstView:classCFirstView =   " CFirstView ", sizeof(class CFirstView), 0xFFFF,

15、CFirstView:CreateObject,    (CRuntimeClass*)(&CView:classCView), NULL ; CRuntimeClass* CFirstView:GetRuntimeClass() const    return (CRuntimeClass*)(& CFirstView:classCFirstView); (3)主框架类DECLARE_DYNCREATE(CMainFrame)  展开后为:public:   static const C

16、RuntimeClass classCMainFrame;  virtual CRuntimeClass* GetRuntimeClass() const;  static CObject* PASCAL CreateObject();IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)  展开后为: CObject* PASCAL CMainFrame:CreateObject()   return new CMainFrame;  const CRuntimeClass CMainFram

17、e:classCMainFrame =   "CMainFrame", sizeof(class CMainFrame), 0xFFFF, CMainFrame:CreateObject,    (CRuntimeClass*)(& CFrameWnd:classCFrameWnd), NULL ; CRuntimeClass* CMainFrame:GetRuntimeClass() const    return (CRuntimeClass*)(&CMainFrame:cl

18、assCMainFrame);   这些宏首先在你的定义文件中定义一个以class+类名为名字的静态变量。然后定义一个返回这个静态变量的函数GetRuntimeClass并在实现文件中实现之。最后定义并实现一个创建对象的函数CreateObject。好了,我们现在就来看看CSingleDocTemplate对象的构造函数做了些什么:下面是他的实现CSingleDocTemplate:CSingleDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, C

19、RuntimeClass* pViewClass)  : CDocTemplate(nIDResource, pDocClass, pFrameClass, pViewClass) m_pOnlyDoc = NULL;它主要是初始化他的父类CDocTemplate,CDocTemplate做了些什么?如下:<1>把资源ID及文档、框架、视图的三个CRuntimeClass结构的静态成员的地址(也就是传进来的四个参数) 保存了起来。<2>LoadTemplate();/为指定的文档模板对象装载资源至此这个new语句总算讲完了。第二节:AddD

20、ocTemplate(pDocTemplate);下面是他的实现函数void CWinApp:AddDocTemplate(CDocTemplate* pTemplate) if (m_pDocManager = NULL)m_pDocManager = new CDocManager; /*创建一个文档管理类,对于单文档常常只有一个文档模板用CDocManager类并不是很重要,我们可以忽略这句*/ m_pDocManager->AddDocTemplate(pTemplate); /*把文档模板指针保存在CDocManager实例中由CDocManager去管理他

21、,我们只要知道有这个事就行了*/第三节:ProcessShellCommand(cmdInfo)   这个函数发送的一个命令就是FileNew其他的暂时不管他,其实所有的文档类,框架类,视图类都是在这个函数中创建的,在第一段中已经讲到应用程序类将上三个类的CRuntimeClass一个静态成员地址保存起来了,关于CRuntimeClass结构的具体功能参照MSDN。ProcessShellCommand描述如下:BOOL CWinApp:ProcessShellCommand(CCommandLineInfo& rCmdInfo) BOOL bResult

22、 = TRUE; switch (rCmdInfo.m_nShellCommand)  case CCommandLineInfo:FileNew:  if (!AfxGetApp()->OnCmdMsg(ID_FILE_NEW, 0, NULL, NULL)   OnFileNew();  if (m_pMainWnd = NULL)   bResult = FALSE;  break; case CCommandLineInf

23、o:FileOpen:  if (!OpenDocumentFile(rCmdInfo.m_strFileName)   bResult = FALSE;  break;./还有很多消息处理略去  return bResult;第一段AfxGetApp()->OnCmdMsg()AfxGetApp()->OnCmdMsg主要是派发命令消息,跟我们关系最大的消息是菜单命令ID_FILE_NEW,下面讲述他的处理函数OnFileNew第二段OnFileNew(); OnFileNew只是

24、简单的调用文档管理对象的同名函数,他的描述如下:void CWinApp:OnFileNew() if (m_pDocManager != NULL)  m_pDocManager->OnFileNew();/只是调用CDocManager:OnFileNew文档管理类的OnFileNew去掉一些没用的东西后实现如下:void CDocManager:OnFileNew() CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();/*获得第一个文档模板,对于单文档只有一个文

25、档模板*/ if (m_templateList.GetCount() > 1)/对单文档这段没用   CNewTypeDlg dlg(&m_templateList);  int nID = dlg.DoModal();  if (nID = IDOK)   pTemplate = dlg.m_pSelectedTemplate;  else   return;     / non

26、e - cancel operation  pTemplate->OpenDocumentFile(NULL);/*其实是调用CSingleDocTemplate:OpenDocumentFile函数下面祥述这里,因为在CDocTemplate 类中这个函数是一个纯虚函数*/下面简述pTemplate->OpenDocumentFile(NULL);这个函数,这是最重要的一个函数,他执行了如下6个步骤:<1>pDocument = CreateNewDocument();/创建一个新文档   CDocument* pDocumen

27、t = (CDocument*)m_pDocClass->CreateObject();/*这是才真正的创建文档对象,这里创建的文档对象就是上面RUNTIME_CLASS(CFirstDoc),中的对象这是MFC开发人员想出来的一种运行时创建对象的方法,应该说比较不错的,不知道C+Builder的是怎样构造的。*/  AddDocument(pDocument);  /把创建的对象指针记录下来,以后还要用的。<2> pFrame = CreateNewFrame(pDocument, NULL);  /*根据新文档指针创建新文档框架,这

28、个比较重要下一段描述*/<3>SetDefaultTitle(pDocument);  /设置缺省标题,不重要的<4>pDocument->OnNewDocument()   /清除老文档内容 DeleteContents();   /删除原来的内容而不管是否存盘 SetModifiedFlag(FALSE);   /清除曾经修改过的标记<5>pThread->m_pMainWnd = pFrame;  /框架窗口作为的指针作为主窗口的指针<

29、.6>InitialUpdateFrame(pFrame, pDocument, bMakeVisible);   /*使框架中的视图窗口接受到OnInitialUpdat的调用,并作原始更新。*/至此第一段的OnFileNew函数总算讲完。下面讲<2> CreateNewFrame函数CreateNewFrame是CDocTemplate的成员函数如下3个步骤:<2.1>CCreateContext context;    /创建CcreateContext对象.也就是我们重载LoadFrame函数的那个Ccre

30、ateContext的来源*/context.m_pCurrentFrame = pOther;  /保存当前框架,一般为NULLcontext.m_pCurrentDoc = pDoc;     /保存文档对象指针context.m_pNewViewClass = m_pViewClass;  /保存视图对象指针context.m_pNewDocTemplate = this;       /保存文档模板的指针。<2.2>CFrameWnd* pFrame =

31、(CFrameWnd*)m_pFrameClass->CreateObject(); /真正创建框架的对象<2.3>pFrame->LoadFrame(m_nIDResource,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,      NULL, &context)   /加载资源,这是最重要的,下面讲述<2.3.1> GetIconWndClass(dwDefaultStyle, nIDResource)   /加载资源并注册窗口

32、   AfxFindResourceHandle  :LoadIcon  /加载光标资源  CREATESTRUCT cs;  /创建一个CREATESTRUCT结构实例  PreCreateWindow(cs);   /*调用窗口预创建函数,这个函数我们可以重载的  根据cs调用 AfxRegisterWndClass注册框架窗口*/<2.3.2> Create()  /创建框架窗口,后面祥述,此处暂时不讲。<2.3

33、.3> m_hMenuDefault = :GetMenu(m_hWnd);  /获取并保存菜单句柄<2.3.4> LoadAccelTable(MAKEINTRESOURCE(nIDResource);  /装载加速键表  下面讲Create函数,如下4个步骤:  <2.3.2.1>hMenu = :LoadMenu(hInst, lpszMenuName);  /加载菜单<2.3.2.2>CREATESTRUCT cs;  /创建一个CREATESTRUCT结构实例cs.lpCreateParams = lpParam;  /(此时的lpParam就是<2.1>建的context对象指针)<2.3.2.3> PreCreateWindow(cs);  /调用窗口预创建函数,这个函数我们可以重载的,又调用一次<2.3.2.4>调用API函数:CreateWindowEx真正创建框架窗口,创建过程中会发出W

温馨提示

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

评论

0/150

提交评论