MFC框架

来源:互联网 发布:横滨玛丽知乎 编辑:程序博客网 时间:2024/05/19 23:13

MFC 就把有着相当固定行为之 WinMain 内部动作包装在 CWinApp 中,把有着相当固定行为之 WndProc 内部动作包装在 CFrameWnd 中。也就是说:

    CWinApp 代表程序本体

    CFrameWnd 代表一个框架窗口(Frame Window)


CwinApp——取代 WinMain 的地位

CWinApp 的派生对象被称为application object,可以想见,CWinApp 本身就代表一个程序本体。一个程序的本体是什么?回想第1章的SDK 程序,与程序本身有关而不与窗口有关的数据或动作有些什么?系统传进来的四个WinMain 参 数 算 不 算 ?InitApplication 和InitInstance 算不算?消息循环算不算?都算,是的,以下是MFC 4.x 的CWinApp声明(节录自AFXWIN.H): 

几乎可以说CWinApp 用来取代WinMain在SDK程序中的地位。这并不是说MFC程序没有WinMain(稍后我会解释),而是说传统上  SDK 程序的 WinMain 所完成的工作现在由CWinApp 的三个函数完成:

virtual BOOL InitApplication();

virtual BOOL InitInstance();

virtual int  Run();

WinMain 只是扮演役使它们的角色


CFrameWnd-取代 WndProc 的地位

CFrameWnd 主要用来掌握一个窗口,几乎你可以说它是用来取代SDK程序中的窗口函数的地位


在程序启动之初,由于theApp是全局的,CWinApp将首先调用构造函数,内部就是设置一些线程的this指针。

然后启动_tWinMain函数,继而调用AfxWinMain

AfxWinMain主要实现:

CWinApp* pApp = AfxGetApp();

pApp->InitApplication();

pApp->InitInstance();

nReturnCode = pApp->Run(); 

其实就相当于调用:

CMyWinApp::InitApplication();

CMyWinApp::InitInstance();

CMyWinApp::Run();

    因而导至调用:

CWinApp::InitApplication();//因为CMyWinApp并没有改写InitApplication

CMyWinApp::InitInstance(); //因为 CMyWinApp改写了InitInstance

CWinApp::Run();           //因为 CMyWinApp并没有改写 Run


AfxWinMain流程:

AfxWinInit->AFX 内部初始化动作,主要是创建一个线程,该线程会设置窗口钩子

CWinApp::InitApplication:做些内部管理动作

CDialog::DoMdal(或者CFrameWnd的Create):注册创建窗口

Run():内部即是消息循环


来龙去脉总整理

前面各节的目的就是如何将表面上看来不知所以然的MFC程序对映到我们在SDK程序设计中学习到的消息流动观念,从而清楚地掌握MFC程序的诞生与死亡。让我对MFC程序的来龙去脉再做一次总整理。

程序的诞生:

    Application object 产生,内存于是获得配置,初值亦设立了。

    AfxWinMain 执行AfxWinInit,后者又调用AfxInitThread,把消息队列尽量加大到96。

    AfxWinMain执行InitApplication。这是CWinApp 的虚函数,但我们通常不改写它。

    AfxWinMain执行InitInstance。这是CWinApp的虚函数,我们必须改写它。

    CMyWinApp::InitInstance 'new' 了一个CMyFrameWnd 对象。

    CMyFrameWnd 构造函数调用Create,产生主窗口。我们在Create 参数中指定的窗口类是NULL, 于是MFC根据窗口种类 , 自行为我们注册一个名为"AfxFrameOrView42d" 的窗口类。

  回到InitInstance中继续执行ShowWindow,显示窗口。

  执行UpdateWindow,于是发出WM_PAINT。

  回到AfxWinMain,执行Run,进入消息循环。

程序开始运作:

   程序获得WM_PAINT 消息(藉由CWinApp::Run 中的::GetMessage 循环)。

    WM_PAINT经由::DispatchMessage送到窗口函数CWnd::DefWindowProc 中。

    CWnd::DefWindowProc 将消息循环过消息映射表格(Message Map)。

  循环过程中发现有吻合项目,于是调用项目中对应的函数。此函数是应用程序利用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间的宏设立起来的。

  标准消息的处理例程亦有标准命名,例如WM_PAINT必然由OnPaint处理。


如果你的MFC 程序也想处理idle time,只要改写CWinApp 派生类的  OnIdle 函数即可。这个函数的类型如下:

virtual BOOL OnIdle(LONG lCount);

lCount是系统传进来的一个值,表示自从上次有消息进来,到现在,OnIdle 已经被调用了多少次


原创粉丝点击