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程序的主函数入口为

1 extern   " C "   int  WINAPI
2 _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
3     LPTSTR lpCmdLine,  int  nCmdShow)
4 ExpandedBlockStart.gifContractedBlock.gif {
5    // call shared/exported WinMain
6    return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
7}

 该函数在APPMODUL.cpp中,从这个函数可以看出真正的入口函数应该为AfxWinMain(Winmain.cpp中)

 1  int  AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 2      LPTSTR lpCmdLine,  int  nCmdShow)
 3  {
 4      ASSERT(hPrevInstance  ==  NULL);
 5 
 6       int  nReturnCode  =   - 1 ;
 7      CWinThread *  pThread  =  AfxGetThread();
 8      CWinApp *  pApp  =  AfxGetApp(); //获取子类
 9 
10       //  AFX internal initialization
11       if  ( ! AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
12           goto  InitFailure;
13 
14       //  App global initializations (rare)
15       if  (pApp  !=  NULL  &&   ! pApp -> InitApplication())
16           goto  InitFailure;
17 
18       //  Perform specific initializations
19       if  ( ! pThread -> InitInstance()) //初始化注册窗口
20      {
21           if  (pThread -> m_pMainWnd  !=  NULL)
22          {
23              TRACE0( " Warning: Destroying non-NULL m_pMainWnd\n " );
24              pThread -> m_pMainWnd -> DestroyWindow();
25          }
26          nReturnCode  =  pThread -> ExitInstance();
27           goto  InitFailure;
28      }
29      nReturnCode  =  pThread -> Run();
30 
31  InitFailure:
32  #ifdef _DEBUG
33       //  Check for missing AfxLockTempMap calls
34       if  (AfxGetModuleThreadState() -> m_nTempMapLock  !=   0 )
35      {
36          TRACE1( " Warning: Temp map lock count non-zero (%ld).\n " ,
37              AfxGetModuleThreadState() -> m_nTempMapLock);
38      }
39      AfxLockTempMaps();
40      AfxUnlockTempMaps( - 1 );
41  #endif
42 
43      AfxWinTerm();
44       return  nReturnCode;
45  }
46 

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

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

 1 BOOL CMfcprojectApp::InitInstance()
 2 ExpandedBlockStart.gifContractedBlock.gif {
 3    AfxEnableControlContainer();
 4
 5    // Standard initialization
 6    // If you are not using these features and wish to reduce the size
 7    //  of your final executable, you should remove from the following
 8    //  the specific initialization routines you do not need.
 9
10#ifdef _AFXDLL
11    Enable3dControls();            // Call this when using MFC in a shared DLL
12#else
13    Enable3dControlsStatic();    // Call this when linking to MFC statically
14#endif
15
16    // Change the registry key under which our settings are stored.
17    // TODO: You should modify this string to be something appropriate
18    // such as the name of your company or organization.
19    SetRegistryKey(_T("Local AppWizard-Generated Applications"));
20
21    LoadStdProfileSettings();  // Load standard INI file options (including MRU)
22
23    // Register the application's document templates.  Document templates
24    //  serve as the connection between documents, frame windows and views.
25
26    CSingleDocTemplate* pDocTemplate;
27    pDocTemplate = new CSingleDocTemplate(
28        IDR_MAINFRAME,
29        RUNTIME_CLASS(CMfcprojectDoc),
30        RUNTIME_CLASS(CMainFrame),       // main SDI frame window
31        RUNTIME_CLASS(CMfcprojectView));
32    AddDocTemplate(pDocTemplate);
//新建一个单文档的模板,并将 doc,view,frame类添加到该模板中

33
34    // Parse command line for standard shell commands, DDE, file open
35    CCommandLineInfo cmdInfo;
36    ParseCommandLine(cmdInfo);
37
38    // Dispatch commands specified on the command line
39    if (!ProcessShellCommand(cmdInfo))
//窗口的注册(不太确定)
40        return FALSE;
41
42    // The one and only window has been initialized, so show and update it.
43    m_pMainWnd->ShowWindow(SW_SHOW);//显示窗口
44    m_pMainWnd->UpdateWindow();//更新窗口

45

46    return TRUE;
47}

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

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

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

1 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT &  cs)
2 ExpandedBlockStart.gifContractedBlock.gif {
3    if!CFrameWnd::PreCreateWindow(cs) )
4        return FALSE;
5    // TODO: Modify the Window class or styles here by modifying
6    //  the CREATESTRUCT cs
7    //此处修改cs,实现用户自定义窗口
8    return TRUE;
9}

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

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

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

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

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


 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/zqingnn/archive/2009/05/03/MFC.html

你可能感兴趣的:(MFC实现原理)