首先来一张类结构层次图

然后我们进入讨论的正题吧!

 

 CWinApp* pApp = AfxGetApp(),GfxGetApp是取得当前CMyApp的对象的一个函数 这样我们用当前的App对象(派生类)附值给CWinApp指针(父类)。这样下面pApp.InitInstance()

调用的就是派生类的因为它是虚函数,如果派生类没有重写那就调用基类一层一层往上找

标号为3,4处:

            首先InitApplication和InitInstance都是虚函数所以如果子类APP也就是自己的程序对这两个函数重载那么实际上运行的是自己的App类定义重写后的函数,一般情况下我们不重载InitApplication这个函数,但是InitInstance是一个空的虚函数,所以我们的程序一定要重载它!所以这里我们的pApp->InitInstance()是调用的CMyWinApp->InitInstance()这个函数。

InitInstance()这个函数是初始化窗口的,在本例子里更是在App类里面调用初始化的是一个主窗口,在win32程序中它是用CreateWindow(...)创建窗口中,但在mfc中我们用不着这么做,只要初始化相关窗口类(基类为CWnd)的实例就会调用相关类型的Create()的,图中初始化的是CMyFrameWnd这个类的对象的,当然我们可以用别的窗口类比如说对话框类。   

      在win32程序中我们把"注册窗口类"的相关操作放在InitApplication这个函数里面,但是MFC中不是这样的,让我们看看这个函数吧:

你看这个函数并没有注册窗口类,那么我们程序运行完这个函数就运行到 InitInstance中开始初始化相关的类型的窗口了,按道理说createwindow()前一定要先注册窗口类的啊?没有窗口类名称怎么创建窗口呢?还有窗口过程也没指名啊?这就到了问题的关键点了:

程序进入到了InitInstance()中--〉CMyFrameWnd对象的构造函数--〉这个窗口的Create()函数---〉然后不知道是怎么指定的就到了CMYFrameWnd::CreateEx()-->因为这个类没有重写这个函数就到了CWnd::CreateEx() ,其实就是这个构造函数构造我们现在要创建的这个窗口的!让我们看看真身:

我们看到这里给窗口类的结构体cs先附了一些东西但缺少窗口类名和窗口过程的指向这两个东西,然后由于这个函数在子类CFrameWnd中被重写所以进入CFrameWnd::PreCreateWindow(cs)中,玄机就在这个函数了,这个函数将给cs没有附的窗口类名和窗口过程的指向附值。这个过程比较繁琐。我这里就描述一下吧,深入浅出中很详细的。

在这个函数中判断cs这个窗口类是不是进行注册过的,如果进行注册过就什么都不做,如果没有注册就调用一个函数来对cs的窗口类型和窗口过程附值然后注册它,简写一个这个函数:

BOOL AFXAPI AfxEndDeferRegisterClass(short cs)
{
cs.lpfnWndProc = DefWindowProc;//现在窗口过程用DefWindowProc,一会在AfxHookWindowCreate(this)中进行了改写
cs.hInstance = AfxGetInstanceHandle();
cs.hCursor = afxData.hcurArrow;
//这里根据判断不同类型的窗口注册了几种不同窗口类(比如工具条之类的好像和其它的窗口类不一样),我们这里先不管//,只写出WND这个类是怎么注册的
cs.style = CS_DBLCIKS|CS_HREDRAW|CS_VREDRAW;
cs.lpzClassName = _afxwnd;//_afxwnd
bResult = AfxRegisterClass(&cs);//要的就是这个AfxRegisterClass,这下子是真的注册成功了。
}
这下子我们要创建的这个窗口的窗口类型就注册成功了,现在可以用这个窗口类进行创建窗口了!但还要注意在CreateWindowEx之前还有AfxHOOKWindowCreate(this)这个函数之前还有一个叫做AfxHookWindowCreate(this)这个函数,这是一个钩子函数,作用是利用SetWindowLong设置窗口过程为AfxWndProc,然后AfxWndProc()-->AfxCallWndProc-->WindowProc .没错!当捕捉到该窗口类对象的消息后首先就跑到WindowProc里了!

AfxHOOKWindowCreate(this)运行完了!那么创建一个窗口的"前戏"就都ok了!下面就走到CreateWindowEx创建这个窗口了~!~

注意:本例子讲的是程序从进入主函数到它的第一个窗口----主窗口创建的详细流程,这个主窗口是一个CFrameWnd类的实例。我想说的是其它Wnd类的子类的初始化也应该是这样,比如说我们创建一个对话框CMyDialog,也是大概上面所述的那个流程,我们一初始化CMyDialog就会走到CDialog::CreateEx()这个函数然后PreCreateWindow中注册窗口类指定类名和窗口过程函数,然后CreateWindowEX..........反正这都封装好了!我们只要初始化就行了!

 

 

 

posted on 2008-09-18 16:52  NANLEE  阅读(3825)  评论(0编辑  收藏  举报