申明:本文是我看了孙鑫老师的VC++视频教程后的总结,相当于学习笔记吧,纯粹是为了方便自己。同时也希望能对大家学习vc++有所帮助。至于文中的内容如果有什么错误或不           妥,欢迎指出。欢迎加我的QQ:124561376进行讨论,共同学习。

由于这是笔记,所以阅读起来可能有点凌乱,所以详细请看“孙鑫老师的VC++视频教程”,

1.  无论是用win32 SDK编写的应用程序还是MFC应用程序,程序的入口都是WinMain;在MFC中程序的入口函数为:_tWinMain,这个函数被微软隐藏在源文件文件:AppModule.cpp中。

  为了能找到MFC的运行流程的脉络,我们可以让程序处于调试模式,单步跟踪程序的运行状况。下面首先列举出将要跟踪的函数和类及其所在的源文件中。

        函数————————————————>所在源文件

        —————————————>

        AfxWinMain—————————————>WinMain.cpp

        CWinApp类—————————————>AppCode.cpp

        CreateEx——————————————>WinCode.cpp(调用API函数CreateWindowEx,进行窗口创建,他是CreateWindow的扩展函数,同是API函数)

        AfxEndDeferRegisterClass——————>WinCode.cpp(注册窗口类)

        AfxDeferRegisterClass————————>AfxIMPL.h(因为这个函数是一个宏,他是在这个头文件中定义的,他实际上就是AfxEndDeferRegisterClass)

        Create————————————————>WinFrm.cpp(调用CreateEx函数)

        CFrameWnd::PreCreateWindow————>WinFrm.cpp(是虚函数。窗体创建前,在子类的PreCreateWindow中可以修改窗体的样式。在窗口创建前做一些准备工作。)

        CFrameWnd::LoadFrame———————>WinFrm.cpp(调用Create函数,创建窗口)

 这些文件的位置在:VC++环境安装位置\Microsoft Visual Studio\VC98\MFC\SRC,进入后可点击搜索——>“文件包含一个词或一个词组”,输入函数类容....

2. 首先创建SDI程序(单文档程序)作为测试程序。每一个MFC程序都有且仅有一个全局变量theApp,他表示当前应用程序模块。

  整个MFC程序的执行顺序大致为:

  首先是全局构造

CObject构造函数à CCmdTarget àCWinThreadàCWinAppà theApp构造函数

然后进入WinMain函数

WinMainàAfxWinMainàAfxWinInitàtheApp.InitApplicationàtheApp.InitInstance

接着执行线程过程。

theApp.Run()

最后清理

AfxWinTerm

我们首先进入文件AppModule.cpp,找到_tWinMain,函数定义为:

代码
1_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
2    LPTSTR lpCmdLine, int nCmdShow)
3{
4    // call shared/exported WinMain
5    return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
6}

发现就一个函数:AfxWinMain,我们在进入这个函数。他的主要定义如下:

代码

   在AfxWinMain中,AfxWinInitpApp->InitApplication(),主要做的事情是:初始化应用程序内部的环境,完成MFC自己内部的一些设置等。这个函数和外部没多大干系。应用程序的很多工作都是在pThread->InitInstance()中完成,类比上节课的知识,他主要做的事情是:

  a.设计窗口类:WNDCLASS

  b.注册窗口类:RegisterClass

  c.创建窗口类:CreateWindow

  d.显示窗口类:ShowWindow

  e.更新窗口类:UpdateWindow

然后又到nReturnCode = pThread->Run();这是一个消息循环,处理系统消息。

有上面可以看出,在AfxWinMain中的执行流程和Win32下的流程差不多(第一节课讲的内容)。

3.  我们首先看pThread->InitInstance(),这是由虚函数,而pThread指向的是theApp,所以其处他所调用的是子类C***App类中的函数,C***App的InitInstance函数我们可以修改他,先看看他的Code大体是什么样子的:

 

代码

 说明:

对于上面代码中的函数ProcessShellCommand完成的功能,我个人分析是:
  a.设计窗口类:WNDCLAS
  b.注册窗口类:RegisterClass
  c.创建窗口类:CreateWindow
他不是一个虚函数,而且在CWinThread中没有这个成员函数,所以在其处调用的ProcessShellCommand一定是早已经在CwinApp中定义好的函数,他所应该完成的工作都已经定制好的了。
这是我个人的观点,老师在视频中并没有说明。因为这三个工作肯定在C***App::InitInstance()中完成,通过跟踪,发现只可能在这里面完成的。

 

  那么ProcessShellCommand是如何完成这个功能的呢? 首先可以肯定的调用线路是:CFrameWnd::LoadFrame()——>Cwnd::Create()——>Cwnd::CreateEx()——>::CreateWindowEx();其中“——>”表示调用关系。可见创建窗口主要是在CFrameWnd::LoadFrame()中完成的。

另外,我根据老师说明,从函数ProcessShellCommand进入进行跟踪,发现如下的一条线路通向CFrameWnd::LoadFrame(),在其列举出仅供参考,线路如下(其中“——>”表示调用关系):

ProcessShellCommand()——>OnCmd()——>AfxDispatchCmdMsg()——>pfn_Command()——>OFileNew()——>OpenDocumentFile()——>CreateNewFrame()——>LoadFrame()

  在跟踪过程中,我发现系统多次调用PreCreateWindow、CreateEx、AfxEndDeferRegisterClass ,但是那好像都是都是注册工具栏、状态栏等的(实际上工具栏、状态栏等都是窗口),

没有发现注册主窗口,可能是跟丢了...

  那现在看看CreateEx这个函数:

代码

 注意上面PreCreateWindow的功能。

我们在看看AfxEndDeferRegisterClass的代码:

代码

 

接下来的类容就是一些零散的笔记了

1.      在Win32 SDK 或者MFC中,函数后面加"Ex"的一般表示为另一个函数的扩展函数,如CreateWindowEx为CreateWindow的扩展函数.

 

2.     在MFC中定义了一下用于应用程序框架类的全局函数,这些全局函数都是以AFX开头的,在程序中都可以调用.

3.一般我们看到的"一个窗口",实际上他可能有多个窗口组成,如单文档程序,里面的就有两个窗口:CMainFrame和CView.

4.     AfxGetAppAfxGetThread 返回的都是theApp对象.

5.   在MFC程序中当调用的API函数或者全局函数和MFC中的成员函数或者成员变量在名字上有冲突时,可以在API函数或者全局函数前面加上"::",表示他们是API函数或者全局函数;

6.  当一个窗口销毁时,CWnd对象不一定立即被销毁,因为销毁窗口(DestroyWindow())只是将窗口句柄置为NULL,而CWnd对象只是包含了一个窗口句柄,CWnd对象的成员句柄不知为空后,Cwnd对象可能还会存在。

 

posted on 2009-11-28 05:16  !-_-木糖-_-!  阅读(1589)  评论(0编辑  收藏  举报