posts - 256, comments - 1315, trackbacks - 41, articles - 8
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

MFC 全接触 (一)

Posted on 2004-08-04 01:59 FantasySoft 阅读(2294) 评论(5)  编辑 收藏 所属分类: All About SoftOnly Windows

        以前对于MFC的了解十分肤浅,只知道MFC = Microsoft Foundation Class,后来还道听途说了很多关于她的风流韵事。有人说她如维纳斯一般美丽,也有人说她和犹大一般丑恶。现在为了手头上的事情,我要从新认识这位也许风华不在的女子了,不管她长得如何,我都得去揭开她那对于我来说神秘的面纱。
        还是从打招呼开始吧,以免把她吓着了。于是,我战战兢兢的跟MFC say hello[1]了。
        MyApp.h:

class CMyApp : public CWinApp
{
public:
    
virtual BOOL InitInstance();
}
;

// frame window class
class CMyFrame : public CFrameWnd
{
public:
    CMyFrame();
protected:
    
// "afx_msg" indicates that the function is part
    
//  of the MFC library message dispatch system
    afx_msg void OnPaint();
    DECLARE_MESSAGE_MAP()
}
;
   
    MyApp.cpp:

#include <afxwin.h> // MFC library header file declares base classes
#include "myapp.h"
 
CMyApp theApp; 
// the one and only CMyApp object
 
BOOL CMyApp::InitInstance()
{
    m_pMainWnd 
= new CMyFrame();
    m_pMainWnd
->ShowWindow(m_nCmdShow);
 
    m_pMainWnd
->UpdateWindow();
    
return TRUE;
}

 
BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
    ON_WM_PAINT()
END_MESSAGE_MAP()

CMyFrame::CMyFrame()
{
    Create(NULL, 
"MYAPP Application");
}

 
void CMyFrame::OnPaint()
{
    CPaintDC dc(
this);
    dc.TextOut(
00"Hello, MFC!");
}


程序的静态分析:
        由于所有的windows程序都开始于WinMain()函数,而在这段程序中并没有看到这个函数,事实上这
个函数被封装到了MFC中了;CMyApp继承于类CWinApp,而CWinApp又继承于CWinThread。因此CWinThread是CMyApp的超类,m_pMainWnd 是定义在类CWinThread中的访问控制为public的CWnd*。在头文件及源文件中,宏定义也用到了多次,如afx _msg,它仅仅是一个占位符,以说明该函数是属于消息处理函数;而DECLARE_MESSAGE_MAP()、BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)和END_MESSAGE_MAP()更是暗藏玄机。

程序的动态分析:
        说实在的,这个简单的程序已经运行了很多次了,以前都是一带而过,而现在仔细想想,里面却包含了很多自
己完全不知道的东西,那么就干脆来一次最彻底的接触。于是按下了F11的快捷键,进行Step Into Debug。
        首先黄色箭头停在了APPMODUL.cpp文件中,而不是我所预料的那样出现在MyApp.cpp文件:

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

 return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

看来程序的入口就在这里了。_tWinMain的函数体只是简单的调用了AfxWinMain函数。OK,F11 again。

       
黄色箭头来到了WINMAIN.cpp文件中:

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方法中,
        首先,通过调用AfxGetThread方法获得一个CWinThread的类指针。继续step into 到
AfxGetThread方法,可以看到该方法包含了获取当前进程指针的语句,如果得到的进程指针为空的话,则调用AfxGetApp以返回一个CWinThread的类指针。当执行了获取当前进程指针的语句后,可以发现返回的CWinThread类指针对应的类为CMyApp;
        接着,通过调用AfxGetApp()获得一个CWinApp的类指针。我们可以发现pThread和pApp这两个指针对应着相同的地址,即都是CMyApp类指针对应的类亦为CMyApp;
        在调用了两个MFC本身提供的初始化方法之后,调用了在CMyApp中实现的InitInstance方法;紧跟着就是一个十分重要的方法了—— Run。step into到Run方法,我们可以看到Run方法中包含了一个无限的循环,在这个循环当中,不断的从消息队列中获取消息并分发消息,直到获取的消息为退出(WM_QUIT)的时候才终止。
         调试花了不少的时间,机子还宕掉了一回,这下总算约莫看见了MFC的背影了,让我们下次再续吧。
        
         Reference: [1] 源代码摘自Programming Microsoft Visual C++ (Fifth Edtion),略有更改。

Feedback

#1楼    回复  引用  查看    

2004-08-04 08:34 by jiezhi [未注册用户]
写得不错

#2楼    回复  引用  查看    

2005-05-10 13:09 by kong1234_51 [未注册用户]
挺好的。

#3楼    回复  引用  查看    

2005-08-04 09:24 by 命运有自己的梦!      
一直想学,但又一直没有下决心学,现在又有想学的冲动了!

#4楼 [楼主]   回复  引用  查看    

2005-08-04 14:42 by FantasySoft      
大家怎么都翻出了我一年前的Post了,继续FT中......

To 命运有自己的梦!: MFC是一个不错的框架,阅读框架的代码会让你对Windows编程有进一步的了解。 Anyway,有些东西是不会过时的。

#5楼    回复  引用  查看    

2006-07-09 02:29 by flyingxu [未注册用户]
CMyFrame::CMyFrame()
{
Create(NULL, "MYAPP Application");
}
这种写法蛮奇怪的

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2005-09-21 14:55 编辑过
 
另存  打印
最新IT新闻:
· 万名Linux使用者向暴雪请愿Linux版《Diablo III》
· 56.com我乐网将全面转行 退出视频行业
· Joost借道TOM在线 将正式进军中国
· 微软副总裁公开承认Vista存在问题
· 互联网DNS存在重大漏洞 黑客可能控制网络流量