首页 > 编程知识 正文

MFC 单文档应用程序 基本框架结构,安卓应用程序结构

时间:2023-05-03 15:57:13 阅读:201590 作者:4740

本文将剖析基于MFC的框架程序,探讨MFC框架程序的内部组织结构,MFC是微软为了简化程序员的开发工作而设计的一套c++类集合,利用这些类有

效地帮助程序员完成windows应用程序开发。

主要类之间的关系 CTestApp类处理消息,将收到的消息分发给相应的对象。 CMainFrame是视图CTestView的父窗口,视图CTestView就显示在CMainFrame的客户区中。 视图类CTestView用来显示文档类CTestDoc中的数据,并根据对视图类的操作修改文档类的数据。一个视图类只能跟一个文档类相联系,而一个文档类可以跟多个视图类相联系 CFrameWnd类:代表了程序的主框架窗口。封装了窗口的注册、创建、显示、刷新、等等窗口操作。 //1.创建一个代表框架窗口的类对象CFrameWnd *pFrame = new CFrameWnd;//在框架窗口和主程序类之间建立联系this->m_pMainWnd = pFrame;//2.创建窗口pFrame->Create(nullptr, L"MFC");//3.显示窗口pFrame->ShowWindow(SW_SHOW);//4.刷新窗口pFrame->UpdateData(); 1、代码结构

 

我们利用VS2008 IDE创建一个名为Test的工程,程序类型选择为单文档,其他默认不变,最终会生成一套代码,这套代码可以直接运行。在生成的单

文档应用程序中,都有五个类,部分类名和工程名相关联。图1展示了IDE向导生成的代码结构示意图以及对应的类功能。

 

在MFC程序有且仅有一个从应用程序类(CWinApp)派生的类,而且仅有一个该派生类的实例化对象;我们发现该程序中确实存在一个theApp的全局变量,该全局变量就代表了这个应用程序本身;win32和MFC应用程序实例表示区别如下:

知识点:

        1.Afx前缀的函数代表应用程序框架(Application Framework)函数,属于全局函数,它们可以在程序的任何地方被调用。

        2.以域作用符“::”开始的表示的函数,表明该函数是一个全局函数。

         

2、MFC运行流程

 

现在直接给出MFC程序执行顺序,但着重分析其运行机制和功能分析,其流程是“theApp全局对象定义---->TestApp构造函数--->WinMain函数”。在执行theApp对象的构造函数之前先执行CWinApp基类的构造函数,从而把我们自己创建的类和MFC类相关联起来了。

 

流程详解:

1.全局变量定义;程序入口函数WinMain加载时,系统先为全局对象分配内存空间,从而利用theApp完成应用程序的启动。

2.创建对象时会调用对象的构造函数;theApp是子类CTestApp是实例对象,子类继承于CWinApp,因此会先调用基类的构造函数,再调用子类的构造函数,从而完成应用程序的初始化工作,例如基类中保存theApp的this指针。

3.进入WinMain函数;在AfxWinMain函数中可以获取子类的this指针,利用此指针调用InitApplication、InitInstance、Run等函数,从而完成窗口类的注册,创建,消息循环、显示,更新。

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,_In_ LPTSTR lpCmdLine, int nCmdShow){ASSERT(hPrevInstance == NULL);int nReturnCode = -1;CWinThread* pThread = AfxGetThread();CWinApp* pApp = AfxGetApp();// AFX internal initializationif (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))goto InitFailure;// App global initializations (rare)if (pApp != NULL && !pApp->InitApplication())goto InitFailure;// Perform specific initializationsif (!pThread->InitInstance()){if (pThread->m_pMainWnd != NULL){TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWndn");pThread->m_pMainWnd->DestroyWindow();}nReturnCode = pThread->ExitInstance();goto InitFailure;}nReturnCode = pThread->Run();InitFailure:#ifdef _DEBUG// Check for missing AfxLockTempMap callsif (AfxGetModuleThreadState()->m_nTempMapLock != 0){TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).n",AfxGetModuleThreadState()->m_nTempMapLock);}AfxLockTempMaps();AfxUnlockTempMaps(-1);#endifAfxWinTerm();return nReturnCode;}

调用InitApplication、InitInstance、Run等函数,从而完成窗口类的注册,创建,消息循环、显示,更新。

4.进入消息循环,响应各种消息,直到退出;MFC程序实际上是采用消息映射机制,来完成各种消息的处理,收到WM_QUIT消息时,退出消息循环。

                                                                                      图2 MFC 运行流程示意图

3、代码跟踪

vs2005可能无法链接到网络中的symbol,可以使用VS2015进行Debug调试的!

下面将给出MFC运行过程的代码跟踪,主要列出MFC框架涉及到的主要函数以及所在的文件名,具体的代码流程可以自行debug跟踪,并利用调用栈

完成函数跟踪。细致函数跟踪和分析,这不详细给出,代码跟踪,如图3所示。

相关的源码文件位置是:...VCatlmfcsrcmfc;            

          

appmodul.cpp中的AfxWinMain()函数将会进入winmain.cpp函数中执行具体内容。 

 

4、主框架窗口/视图窗口

我们创建的MFC程序除了主框架窗口外,还有一个窗口就是视类窗口,对应的是CView类。框架窗口是视类窗口的一个父窗口,它们的关系如图4.红色包围的是主框架窗口,蓝色包围的是视窗口。

5、文档/视类结构


微软在设计基础类库时,采用数据存储和数据显示分离的模式,数据存储由CDocument类完成,数据显示和修改由CView类完成。

在CTestApp的Initstance方法中定义一个单文档模板对象指针,该对象就把文档类对象、框架类对象、视窗类对象有机地组织在一起,接着利用AddDocTemplate函数把这个单文档模板添加到文档模板中,从而把这个三个类组织成为一个整体,源码如下:

BOOL CTestButtonApp::InitInstance(){// InitCommonControlsEx() is required on Windows XP if an application// manifest specifies use of ComCtl32.dll version 6 or later to enable// visual styles. Otherwise, any window creation will fail.INITCOMMONCONTROLSEX InitCtrls;InitCtrls.dwSize = sizeof(InitCtrls);// Set this to include all the common control classes you want to use// in your application.InitCtrls.dwICC = ICC_WIN95_CLASSES;InitCommonControlsEx(&InitCtrls);CWinApp::InitInstance();// Initialize OLE librariesif (!AfxOleInit()){AfxMessageBox(IDP_OLE_INIT_FAILED);return FALSE;}AfxEnableControlContainer();// Standard initialization// If you are not using these features and wish to reduce the size// of your final executable, you should remove from the following// the specific initialization routines you do not need// Change the registry key under which our settings are stored// TODO: You should modify this string to be something appropriate// such as the name of your company or organizationSetRegistryKey(_T("Local AppWizard-Generated Applications"));//加载标准 INI 文件选项(包括 MRU)注册应用程序的文档模板。文档模板将用作文档、框架窗口和视图之间的连接LoadStdProfileSettings(4); //定义一个单文档模板对象指针,该对象就把文档类对象、框架类对象、视窗类对象有机地组织在一起CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CTestButtonDoc),RUNTIME_CLASS(CMainFrame), // main SDI frame windowRUNTIME_CLASS(CTestButtonView));if (!pDocTemplate)return FALSE;//把这个单文档模板添加到文档模板中,从而把这个三个类组织成为一个整体AddDocTemplate(pDocTemplate);// Parse command line for standard shell commands, DDE, file openCCommandLineInfo cmdInfo;ParseCommandLine(cmdInfo);// Dispatch commands specified on the command line. Will return FALSE if// app was launched with /RegServer, /Register, /Unregserver or /Unregister.if (!ProcessShellCommand(cmdInfo))return FALSE;// The one and only window has been initialized, so show and update itm_pMainWnd->ShowWindow(SW_SHOW);m_pMainWnd->UpdateWindow();// call DragAcceptFiles only if there's a suffix// In an SDI app, this should occur after ProcessShellCommandreturn TRUE;}

 

5、窗口类、窗口类对象和窗口

 

C++窗口类对象和窗口并不是一回事,它们之间唯一的关系式C++窗口类对象内部定义了一个窗口句柄变量,保存了与这个c++窗口

类对象相关的那个窗口句柄。窗口销毁时,与之对应的c++窗口类对象销毁与否,要看其生命周期是否结束。但是c++窗口类对象销

毁时,与之关联的窗口也将销毁。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。