MFC实现原理

通过VC++ 新建一个MFC单文档应用程序,其工程名为mfcproject.新建后通过类视图可以看到一共有5个类:

CAboutDlg:对话框类,如关于对话框

CMainFrame:应用程序框架类,包括工具栏菜单等

CMfcprojectApp:应用程序类


CMfcprojectDoc:文档类


CMfcprojectView:也是和文档有关的视图类

1、mfcproject.cpp文件中定义了全局类 CMfcprojectApp theApp;在这个地方设置断点,调试运行可以发现整个程序首先执行到这个地方。

2、全局变量定义后将会调用CMfcprojectApp 类的构造函数

3、从mfcproject.h中可以发现 CMfcprojectApp继承自CWinApp类(在APPCORE.cpp中),根据继承性原理,程序将会首先调用CWinApp类的构造函数,如果细心地话会发现CWinApp的构造函数有参数,但CMfcprojectApp类构造函数并没有带参数,这是怎么回事呢?再仔细看下CWinApp类的构造函数:CWinApp(LPCTSTR lpszAppName = NULL); 看见了没这里的参数是默认值,这也就是为什么CMfcprojectApp构造函数没有带参数的缘故了

4、定义好全局变量以后,就要找主函数入口了,MFC程序的主函数入口为

 

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


 

 该函数在APPMODUL.cpp中,从这个函数可以看出真正的入口函数应该为AfxWinMain(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\n");
             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).\n",
             AfxGetModuleThreadState()->m_nTempMapLock);
     }
     AfxLockTempMaps();
     AfxUnlockTempMaps(-1);
 #endif
 
     AfxWinTerm();
     return nReturnCode;
 }


 

 关键的语句是line8获取子类实例,line19初始化子类,完成窗口注册,line20可以在这些行上设置断点

5、 由于pThred当前指向子类,InitInstance函数是虚函数,因此 pThread->InitInstance()将调用子类的CMfcprojectApp::InitInstance()


 

BOOL CMfcprojectApp::InitInstance()
{
    AfxEnableControlContainer();

    // Standard initialization
    // If you are not using these features and wish to reduce the size
    //  of your final executable, you should remove from the following
    //  the specific initialization routines you do not need.

#ifdef _AFXDLL
    Enable3dControls();            // Call this when using MFC in a shared DLL
#else
    Enable3dControlsStatic();    // Call this when linking to MFC statically
#endif

    // Change the registry key under which our settings are stored.
    // TODO: You should modify this string to be something appropriate
    // such as the name of your company or organization.
    SetRegistryKey(_T("Local AppWizard-Generated Applications"));

    LoadStdProfileSettings();  // Load standard INI file options (including MRU)

    // Register the application's document templates.  Document templates
    //  serve as the connection between documents, frame windows and views.

    CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
        IDR_MAINFRAME,
        RUNTIME_CLASS(CMfcprojectDoc),
        RUNTIME_CLASS(CMainFrame),       // main SDI frame window
        RUNTIME_CLASS(CMfcprojectView));
    AddDocTemplate(pDocTemplate);//新建一个单文档的模板,并将 doc,view,frame类添加到该模板中。

    // Parse command line for standard shell commands, DDE, file open
    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);

    // Dispatch commands specified on the command line
    if (!ProcessShellCommand(cmdInfo))//窗口的注册(不太确定)
        return FALSE;

    // The one and only window has been initialized, so show and update it.
    m_pMainWnd->ShowWindow(SW_SHOW);//显示窗口
    m_pMainWnd->UpdateWindow();//更新窗口 

    return TRUE;
}


 上述代码中红色部分是比较重要的地方,可以在这些地方设置断点。

 6、窗口注册会调用函数BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)在文件WINCORE.CPP中

 7、紧接着调用BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs),创建窗口


 

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    if( !CFrameWnd::PreCreateWindow(cs) )
        return FALSE;
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs
    //此处修改cs,实现用户自定义窗口
    return TRUE;
}



8、接下来调用line3父类的precreatewindow函数

9、由于窗口包括frame框架类,因此需要调用cfrmwnd的create函数(WINFRM.cpp中),这个函数又会调用Cfrmwnd的父类CWnd::CreateEx函数

10、注册完窗口后就会执行消息响应,消息响应是通过  AfxWinMain中nReturnCode = pThread->Run()实现的

11、用一个dowhile循环实现消息循环    PumpMessage()

大概的MFC实现就写到这,可能有很多不对的地方,等熟悉以后再来更新!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值