MFC 全接触 (一)

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

None.gif class  CMyApp :  public  CWinApp
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
public:
InBlock.gif    
virtual BOOL InitInstance();
ExpandedBlockEnd.gif}
;
None.gif
None.gif
//  frame window class
None.gif
class  CMyFrame :  public  CFrameWnd
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
public:
InBlock.gif    CMyFrame();
InBlock.gif
protected:
InBlock.gif    
// "afx_msg" indicates that the function is part
InBlock.gif    
//  of the MFC library message dispatch system
InBlock.gif
    afx_msg void OnPaint();
InBlock.gif    DECLARE_MESSAGE_MAP()
ExpandedBlockEnd.gif}
;
   
    MyApp.cpp:

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

None.gif 
None.gifBEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
None.gif    ON_WM_PAINT()
None.gifEND_MESSAGE_MAP()
None.gif
None.gifCMyFrame::CMyFrame()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    Create(NULL, 
"MYAPP Application");
ExpandedBlockEnd.gif}

None.gif 
None.gif
void  CMyFrame::OnPaint()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    CPaintDC dc(
this);
InBlock.gif    dc.TextOut(
00"Hello, MFC!");
ExpandedBlockEnd.gif}


程序的静态分析:
        由于所有的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文件:

None.gifextern "C" int  WINAPI
None.gif_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
None.gif LPTSTR lpCmdLine, 
int
 nCmdShow)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
{
InBlock.gif 
// call shared/exported WinMain

InBlock.gif
 return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
ExpandedBlockEnd.gif}

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

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

None.gifint  AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
None.gif LPTSTR lpCmdLine, 
int
 nCmdShow)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
{
InBlock.gif ASSERT(hPrevInstance 
==
 NULL);
InBlock.gif
InBlock.gif 
int nReturnCode = -1
;
InBlock.gif CWinThread
* pThread =
 AfxGetThread();
InBlock.gif CWinApp
* pApp =
 AfxGetApp();
InBlock.gif
InBlock.gif 
// AFX internal initialization

InBlock.gif
 if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
InBlock.gif  
goto
 InitFailure;
InBlock.gif
InBlock.gif 
// App global initializations (rare)

InBlock.gif
 if (pApp != NULL && !pApp->InitApplication())
InBlock.gif  
goto
 InitFailure;
InBlock.gif
InBlock.gif 
// Perform specific initializations

InBlock.gif
 if (!pThread->InitInstance())
ExpandedSubBlockStart.gifContractedSubBlock.gif 
dot.gif
{
InBlock.gif  
if (pThread->m_pMainWnd !=
 NULL)
ExpandedSubBlockStart.gifContractedSubBlock.gif  
dot.gif
{
InBlock.gif   TRACE0(
"Warning: Destroying non-NULL m_pMainWnd "
);
InBlock.gif   pThread
->m_pMainWnd->
DestroyWindow();
ExpandedSubBlockEnd.gif  }

InBlock.gif  nReturnCode 
= pThread->ExitInstance();
InBlock.gif  
goto
 InitFailure;
ExpandedSubBlockEnd.gif }

InBlock.gif nReturnCode 
= pThread->Run();
InBlock.gif
InBlock.gifInitFailure:
InBlock.gif#ifdef _DEBUG
InBlock.gif 
// Check for missing AfxLockTempMap calls

InBlock.gif
 if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif 
dot.gif
{
InBlock.gif  TRACE1(
"Warning: Temp map lock count non-zero (%ld). "
,
InBlock.gif   AfxGetModuleThreadState()
->
m_nTempMapLock);
ExpandedSubBlockEnd.gif }

InBlock.gif AfxLockTempMaps();
InBlock.gif AfxUnlockTempMaps(
-1);
InBlock.gif
#endif

InBlock.gif
InBlock.gif AfxWinTerm();
InBlock.gif 
return nReturnCode;
ExpandedBlockEnd.gif}

在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),略有更改。

转载于:https://www.cnblogs.com/perhaps/archive/2004/08/04/29919.html

相关资源:java面试题以及技巧
已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库表。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列表: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、Mybatis、Mybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页