关闭

MFC学习步步高02

970人阅读 评论(1) 收藏 举报

本人同意他人对我的文章引用,但请在引用时注明出处,谢谢.作者:蒋志强 

学习MFC的必要知识 有2个:

1,WIN 32编程的基础

2,C++面向对象编程的基础(对继承,虚函数,多态的掌握)

如果还没有同时具备这两个基础知识,开始MFC编程的学习只能打击我们学习的激情.对于WIN 32编程的基础知识,可多可少,但我们至少要了解消息循环,消息处理,窗口创建,句柄等WIN32 API编程的基本知识(当然了解越多WIN32编程知识对我们学习MFC越有帮助).如果还没有这方面的知识,就马上去看看Charles Petzold的那本经典之作<windows程序设计>吧.我已经把这本的中文电子版上传,可以在这个URL http://d.download.csdn.net/down/256525/gamer_gerald 下载

下面我们开始MFC的学习.MFC提供三种类型的应用程序编程:Dialog Based;SingleDocument;Mutiple Document.

MFC的程序框架提供View/Document的组织方式,将程序分成两大部分,数据部分和数据显示部分.将数据和数据显示分开,让程序结构更合理.SingleDocument和MutipleDocument就是View/Document结构的程序框架,还有一种DialogBased程序是针对更简单的程序,没有提供框架支持的文档和视图结构.

我们选择使用Single Document类型的程序来学习,掌握Single Document后稍加推广很容易理解Mutiple Document结构;将Single Document的文档处理结构删除简化后就是Dialog based的程序结构.所以我们从Single Document入手.

任何的MFC程序都有一个从CWinApp类继承下来的子类,名字是C工程名App.这个类代表应用程序,该类负责程序的消息循环,在任何一个MFC程序中有且只有一个CWinApp类的对象.该对象的声明不在任何类里面,所以是一个全局对象变量.全局变量在程序进入入口函数前,就已经实例化,分配内存空间产生CWinApp对象了.

在MFC框架下直接找不到WinMain函数,但Win32程序一定有入口WinMain函数,MFC程序也仅仅对Win32 API做了封装,本质上也是Win32程序,所以一定有WinMain函数.在MFC程序中,WinMain函数实际上被隐藏到了MFC的代码中.

在VC6中,按F10键单步执行,直接就到了WinMain函数的入口的地方,在MFC的源代码中有个APPMODUL.CPP文件,WinMain函数就在这里面.单步执行由于是一条条语句执行,程序运行的第一个到的地方就是WinMain.所有按F10马上就找到了.这里的MFC源代码如下

extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, 
int nCmdShow);

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, 
int nCmdShow)
{
    
// call shared/exported WinMain
    return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

这里的_tWinMain是一个宏(#define _tWinMain   wWinMain).这里的wWinMain就是我们在WIN32 API中的WinMain函数.在_tWinMain中只有一条语句,调用AfxWinMain.在MFC中凡是以Afx开头的函数,都是MFC以全局函数形式提供的函数,可以在任何地方调用.(我们以前也讲过以::符号开始可以直接调用Win32 API).现在我们到AfxWinMain里面去看看. 

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, 
int nCmdShow)
{
    ASSERT(hPrevInstance 
== NULL);

    
int nReturnCode = -1;
    CWinThread
* pThread = AfxGetThread();
    CWinApp
* pApp = AfxGetApp();

    
// AFX internal initialization
    if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
        
goto InitFailure;

    
// App global initializations (rare)
    if (pApp != NULL && !pApp->InitApplication())
        
goto InitFailure;

    
// Perform specific initializations
    if (!pThread->InitInstance())
    
{
        
if (pThread->m_pMainWnd != NULL)
        
{
            TRACE0(
"Warning: Destroying non-NULL m_pMainWnd ");
            pThread
->m_pMainWnd->DestroyWindow();
        }

        nReturnCode 
= pThread->ExitInstance();
        
goto InitFailure;
    }

    nReturnCode 
= pThread->Run();

InitFailure:
#ifdef _DEBUG
    
// Check for missing AfxLockTempMap calls
    if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
    
{
        TRACE1(
"Warning: Temp map lock count non-zero (%ld). ",
            AfxGetModuleThreadState()
->m_nTempMapLock);
    }

    AfxLockTempMaps();
    AfxUnlockTempMaps(
-1);
#endif

    AfxWinTerm();
    
return nReturnCode;
}

 

 在AfxWinMain中首先定义了  CWinThread类型指针 pThread 和 CWinApp类型指针 pApp,并且使用Afx开头的全局函数获得程序线程及应用程序指针.

 

我们可以在MFC类层次图中看到CWinApp是CWinThread的子类.CWinApp是程序中负责消息循环代表程序的类,所以这个时候,也就是程序的线程.所以这个时候pThread 和CWinApp指针实际上都指向的是同一个对象,就是进入WinMain入口函数之前创建的全局CWinApp对象.我们可以在VC6中调试程序验证,它们就是同一个对象.见下图:

这两个指针都指向的同一个地址.

因为CWinApp类的对象在进入WinMain之前就已经创建了,所以我们可以进入WinMain后肯定可以得到这个对象.

我们先休息一下,下次继续学习,今天国庆节日,放松一下.

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:92732次
    • 积分:1122
    • 等级:
    • 排名:千里之外
    • 原创:29篇
    • 转载:0篇
    • 译文:1篇
    • 评论:88条
    最新评论