MFC笔记之----程序框架浅析、消息映射

MFC的框架原理

1.唯一的一个WinApp实例

举例:我新建一个名称是lesson4的MFC工程,那么在Clesson4App类的实现文件中,框架自动声明一个全局变量:

Clesson4App theApp;

所有的MFC有且只有一个CWinApp实例,并且这个实例是放在AfxWinMain()之前的,也就是说,在进入传统的WinMain()之前,这个对象已经被构造出来。

2.AfxWinMain()

进入AfxWinMain()后首先获取Clesson4App对象的指针,调用InitInstance()函数进行窗口类注册与创建,显示,然后调用CWinApp的Run()函数进行消息循环。

/*
winmain.cpp
*/
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    _In_ LPTSTR lpCmdLine, int nCmdShow)
{
    int nReturnCode = -1;
    CWinThread* pThread = AfxGetThread();//CWinApp由CWinThread派生
    CWinApp* pApp = AfxGetApp();         //这两行的指针都指向框架创建的Clesson4App

    // 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())          //这里调用Clesson4App的InitInstance()
    {
        /*.....省略....*/
    }
    nReturnCode = pThread->Run();           //消息循环

InitFailure:
    AfxWinTerm();                          //初始化失败
    return nReturnCode;
}

3.Clesson4App::InitInstance()

这个函数用于把向导生成的CMainFrame类,文档类,视类组建成文档模板类,然后分别创建并显示,更新。
InitInstance()函数是CWinApp类的一个虚函数,MFC框架向导已经在生成的Clesson4App里重写了这个函数:

BOOL Clesson4App::InitInstance()
{

      /*此处省略。。。。。。。。*/
    SetRegistryKey(_T("应用程序向导生成的本地应用程序"));//操作注册表
    LoadStdProfileSettings(4);                     // 加载标准 INI 文件选项(包括 MRU)
    /*此处省略。。。。。。。。*/

    // 注册应用程序的文档模板。文档模板
    // 将用作文档、框架窗口和视图之间的连接
    CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
        IDR_MAINFRAME,
        RUNTIME_CLASS(Clesson4Doc),
        RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
        RUNTIME_CLASS(Clesson4View));
    if (!pDocTemplate)
        return FALSE;
    AddDocTemplate(pDocTemplate);


        /*此处省略。。。。。。。。*/

    // 唯一的一个窗口已初始化,因此显示它并对其进行更新
    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();

    return TRUE;
}

4.注册窗口类AfxEndDeferRegisterClass()

/*
wincore.cpp
*/
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
{

    fToRegister &= ~pModuleState->m_fRegisteredClasses;

    LONG fRegisteredClasses = 0;

    WNDCLASS wndcls;
    memset(&wndcls, 0, sizeof(WNDCLASS));   // 清空wndcls
    wndcls.lpfnWndProc = DefWindowProc;     //赋默认消息处理函数
    wndcls.hInstance = AfxGetInstanceHandle();
    wndcls.hCursor = afxData.hcurArrow;

    INITCOMMONCONTROLSEX init;
    init.dwSize = sizeof(init);

//判断向导的窗口类,然后赋值
    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;
    }
/*省略。。。。。。。。*/

    pModuleState->m_fRegisteredClasses |= fRegisteredClasses;
// 返回向导指定的窗口类
    return (fToRegister & fRegisteredClasses) == fToRegister;
}

Windows Message

typedef struct tagMSG 
{ 
HWND hwnd; 
UINT message; 
WPARAM wParam; 
LPARAM lParam; 
DWORD time; 
POINT pt; 
} MSG, *PMSG; 

hwnd指向了具体的窗口,而CWnd类对象有一个成员变量m_hwnd,所以消息触发以后传递给窗口基类,

LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // OnWndMsg does most of the work, except for DefWindowProc call
    LRESULT lResult = 0;
    if (!OnWndMsg(message, wParam, lParam, &lResult))
        lResult = DefWindowProc(message, wParam, lParam);
    return lResult;
}

BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    LRESULT lResult = 0;
    union MessageMapFunctions mmf;
    mmf.pfn = 0;
    CInternalGlobalLock winMsgLock;
    // special case for commands
    if (message == WM_COMMAND)
    {
        if (OnCommand(wParam, lParam))
        {
            lResult = 1;
            goto LReturnTrue;
        }
        return FALSE;
    }

    // special case for notifies
    if (message == WM_NOTIFY)
    {
        NMHDR* pNMHDR = (NMHDR*)lParam;
        if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
            goto LReturnTrue;
        return FALSE;
    }

    // special case for activation
    if (message == WM_ACTIVATE)
        _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));

    // special case for set cursor HTERROR
    if (message == WM_SETCURSOR &&
        _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
    {
        lResult = 1;
        goto LReturnTrue;
    }

CWnd::OnWndMsg()进行消息判断 ON_COMMAND ON_NOTIFY查看是否有消息处理函数与触发的WM_XXXX对应

你可能感兴趣的:(学习笔记,框架,mfc)