Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > MFC程序框架剖析
【标  题】:MFC程序框架剖析
【关键字】:MFC
【来  源】:http://blog.csdn.net/mqt_2003/archive/2006/11/28/1418730.aspx

MFC程序框架剖析

Your Ad Here

MFC程序框架剖析

                                                          作者:ECNU)孟庆涛  Email:mqt-2003@163.com

1:程序的“导火索”---theApp

CjjjApp theApp;

在声明对象的同时,调用其构造函数。按C++的语法,首先要调用其基类Cwinapp的构造函数. 这个文件主要用于应用程序的一些初始化操作。

class CWinApp : public CWinThread

{

    DECLARE_DYNAMIC(CWinApp)

public:

// Constructor

    CWinApp(LPCTSTR lpszAppName = NULL); 

…………

}

 

CWinApp::CWinApp(LPCTSTR lpszAppName)

{

    if (lpszAppName != NULL)

       m_pszAppName = _tcsdup(lpszAppName);

    else

       m_pszAppName = NULL;

    // initialize CWinThread state

    AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();

    AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;

    ASSERT(AfxGetThread() == NULL);

    pThreadState->m_pCurrentWinThread = this;

    ASSERT(AfxGetThread() == this);

    m_hThread = ::GetCurrentThread();

    m_nThreadID = ::GetCurrentThreadId();

    // initialize CWinApp state

    ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please

    pModuleState->m_pCurrentWinApp = this;

    ASSERT(AfxGetApp() == this);

    // in non-running state until WinMain

    m_hInstance = NULL;

    m_hLangResourceDLL = NULL;

    m_pszHelpFilePath = NULL;

    m_pszProfileName = NULL;

    m_pszRegistryKey = NULL;

    m_pszExeName = NULL;

    m_pRecentFileList = NULL;

    m_pDocManager = NULL;

    m_atomApp = m_atomSystemTopic = NULL;

    m_lpCmdLine = NULL;

    m_pCmdInfo = NULL;

    // initialize wait cursor state

    m_nWaitCursorCount = 0;

    m_hcurWaitCursorRestore = NULL;

    // initialize current printer state

    m_hDevMode = NULL;

    m_hDevNames = NULL;

    m_nNumPreviewPages = 0;     // not specified (defaults to 1)

    // initialize DAO state

    m_lpfnDaoTerm = NULL;   // will be set if AfxDaoInit called

    // other initialization

    m_bHelpMode = FALSE;

    m_eHelpType = afxWinHelp;

    m_nSafetyPoolSize = 512;        // default size

}

2:theApp之后的隐藏代码,由他控制整个程序的流程。

_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPTSTR lpCmdLine, int nCmdShow)

{

    // call shared/exported WinMain

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

}

 

其中有宏定义:#define _tWinMain   wWinMain

 

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPTSTR lpCmdLine, int nCmdShow)

{

    ASSERT(hPrevInstance == NULL);

    int nReturnCode = -1;

    CWinThread* pThread = AfxGetThread();// CWinApp是从CWinThread派生的,

    CWinApp* pApp = AfxGetApp();  //实质上就是pThread==pApp

    // 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())   //注意多态性  virtual BOOL InitInstance();

                                   //又因为pThread==pApp,所以调用pApp-> InitInstance()

    {

       if (pThread->m_pMainWnd != NULL)

       {

           TRACE(traceAppMsg, 0, "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)

    {

       TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",

           AfxGetModuleThreadState()->m_nTempMapLock);

    }

    AfxLockTempMaps();

    AfxUnlockTempMaps(-1);

#endif

    AfxWinTerm();

    return nReturnCode;

}

由上面的程序可以看到几个很重要的函数

1AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))

       goto InitFailure;

 (2) pApp->InitApplication())

 (3) pThread->InitInstance()

 (4) pThread->Run()

其中12 也是完成程序的一些初始化工作,4 主要是为了处理消息,3呢,很关键,我们运行时看到的窗口就是从这里产生。下面一一介绍

3:程序自动产生的InitInstance()函数

以下是自动生成的InitInstance()源程序:

BOOL CjjjApp::InitInstance()

    {

    // 如果一个运行在 Windows XP 上的应用程序清单指定要

    // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,

    //则需要 InitCommonControls()。否则,将无法创建窗口。

    InitCommonControls();

    CWinApp::InitInstance();

    // 初始化 OLE

    if (!AfxOleInit())

    {

       AfxMessageBox(IDP_OLE_INIT_FAILED);

       return FALSE;

    }

    AfxEnableControlContainer();

    // 标准初始化

    // 如果未使用这些功能并希望减小

    // 最终可执行文件的大小,则应移除下列

    // 不需要的特定初始化例程

    // 更改用于存储设置的注册表项

    // TODO: 应适当修改该字符串,

    // 例如修改为公司或组织名

    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

    LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)

    // 注册应用程序的文档模板。文档模板

    // 将用作文档、框架窗口和视图之间的连接

    CMultiDocTemplate* pDocTemplate;

    pDocTemplate = new CMultiDocTemplate(IDR_jjjTYPE,

       RUNTIME_CLASS(CjjjDoc),

       RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架

       RUNTIME_CLASS(CjjjView));

    if (!pDocTemplate)

       return FALSE;

    AddDocTemplate(pDocTemplate);

    // 创建主 MDI 框架窗口

    CMainFrame* pMainFrame = new CMainFrame;

    if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))

       return FALSE;

    m_pMainWnd = pMainFrame;

    // 仅当具有后缀时才调用 DragAcceptFiles

    //  MDI 应用程序中,这应在设置 m_pMainWnd 之后立即发生

    // 分析标准外壳命令、DDE、打开文件操作的命令行

    CCommandLineInfo cmdInfo;

    ParseCommandLine(cmdInfo);

    // 调度在命令行中指定的命令。如果

    // /RegServer/Register/Unregserver /Unregister 启动应用程序,则返回 FALSE

    if (!ProcessShellCommand(cmdInfo))   //引发窗口注册

       return FALSE;

    // 主窗口已初始化,因此显示它并对其进行更新

    pMainFrame->ShowWindow(m_nCmdShow);

    pMainFrame->UpdateWindow();

    return TRUE;

}

 

其中,注册窗口用到了一下函数,比较长,如下:

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

{

    // mask off all classes that are already registered

    AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

    fToRegister &= ~pModuleState->m_fRegisteredClasses;

    if (fToRegister == 0)

       return TRUE;

    LONG fRegisteredClasses = 0;

    // common initialization

    WNDCLASS wndcls;

    memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults

    wndcls.lpfnWndProc = DefWindowProc;    //窗口处理函数

    wndcls.hInstance = AfxGetInstanceHandle();

    wndcls.hCursor = afxData.hcurArrow;

 

    INITCOMMONCONTROLSEX init;

    init.dwSize = sizeof(init);

 

    // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go

    if (fToRegister & AFX_WND_REG)

    {

       // Child windows - no brush, no icon, safest default class styles

       wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

       wndcls.lpszClassName = _afxWnd;

       if (AfxRegisterClass(&wndcls))

           fRegisteredClasses |= AFX_WND_REG;

    }

    if (fToRegister & AFX_WNDOLECONTROL_REG)

    {

       // OLE Control windows - use parent DC for speed

       wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

       wndcls.lpszClassName = _afxWndOleControl;

       if (AfxRegisterClass(&wndcls))

           fRegisteredClasses |= AFX_WNDOLECONTROL_REG;

    }

    if (fToRegister & AFX_WNDCONTROLBAR_REG)

    {

       // Control bar windows

       wndcls.style = 0;   // control bars don't handle double click

       wndcls.lpszClassName = _afxWndControlBar;

       wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

       if (AfxRegisterClass(&wndcls))

           fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;

    }

    if (fToRegister & AFX_WNDMDIFRAME_REG)

    {

       // MDI Frame window (also used for splitter window)

       wndcls.style = CS_DBLCLKS;

       wndcls.hbrBackground = NULL;

       if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))

           fRegisteredClasses |= AFX_WNDMDIFRAME_REG;

    }

    if (fToRegister & AFX_WNDFRAMEORVIEW_REG)

    {

       // SDI Frame or MDI Child windows or views - normal colors

       wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

       wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

       if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))

           fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;

    }

    if (fToRegister & AFX_WNDCOMMCTLS_REG)

    {

       // this flag is compatible with the old InitCommonControls() API

       init.dwICC = ICC_WIN95_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);

       fToRegister &= ~AFX_WIN95CTLS_MASK;

    }

    if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)

    {

       init.dwICC = ICC_UPDOWN_CLASS;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG)

    {

       init.dwICC = ICC_TREEVIEW_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TREEVIEW_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_TAB_REG)

    {

       init.dwICC = ICC_TAB_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_TAB_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG)

    {

       init.dwICC = ICC_PROGRESS_CLASS;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PROGRESS_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG)

    {

       init.dwICC = ICC_LISTVIEW_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LISTVIEW_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG)

    {

       init.dwICC = ICC_HOTKEY_CLASS;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_HOTKEY_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_BAR_REG)

    {

       init.dwICC = ICC_BAR_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_BAR_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG)

    {

       init.dwICC = ICC_ANIMATE_CLASS;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ANIMATE_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG)

    {

       init.dwICC = ICC_INTERNET_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_INTERNET_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_COOL_REG)

    {

       init.dwICC = ICC_COOL_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_COOL_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG)

    {

       init.dwICC = ICC_USEREX_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_USEREX_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_DATE_REG)

    {

       init.dwICC = ICC_DATE_CLASSES;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_DATE_REG);

    }

    if (fToRegister & AFX_WNDCOMMCTL_LINK_REG)

    {

       init.dwICC = ICC_LINK_CLASS;

       fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_LINK_REG);

    }

 

 

    // save new state of registered controls

    pModuleState->m_fRegisteredClasses |= fRegisteredClasses;

 

    // special case for all common controls registered, turn on AFX_WNDCOMMCTLS_REG

    if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_WIN95CTLS_MASK)