读书时间 2011/10/23

来源:互联网 发布:删失数据如何处理 编辑:程序博客网 时间:2024/05/16 02:33


Chap 6. 框架中的窗口

1. 窗口框架总结

* example.cpp中定义theApp
CMyApp theApp;
Q:此步骤中,有没有任何初始化动作完成?

A:Yes。对模块变量参数进行初始化,在THREAD_LOCAL中保存,如主窗口指针等等。


* WinMain.cpp中的WinMain()是入口

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, int nCmdShow)
{
    ASSERT(hPrevInstance == NULL);

    int nReturnCode = -1;
    CWinThread* pThread = AfxGetThread();    ////// 这些函数生效的原因是在WinApp::WinApp()中相关thread/app指针已经存储在THREAD_LOCAL中
    CWinApp* pApp = AfxGetApp();

    // 类库框架内部的初始化
    if(!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
        goto InitFailure;

    // 应用程序的全局初始化
    if(pApp != NULL && !pApp->InitApplication())
        goto InitFailure;

    // 主线程的初始化:完成窗口类注册,窗口生成,窗口显示/更新
    if(!pThread->InitIntance())
    {
        nReturnCode = pThread->ExitInstance();
        goto InitFailure;
    }

    // 开始与用户交互,运行消息循环
    nReturnCode = pThread->Run();

InitFailure:
    return nReturnCode;
}

注:若CMyApp对象未定义,在主线程初始化的时候会出错,原因其实是pthread为空指针:Access Violation.


* CMyApp::InitInstance()

BOOL CMyApp::InitInstance()
{
    m_pMainWnd = new CMyWnd;
    ::ShowWindow(*m_pMainWnd, this->m_nCmdShow);
    ::UpdateWindow(*m_pMainWnd);
    return TRUE; // 返回TRUE进入消息循环
}

注:CMyWnd()实例化的时候,完成对窗口类注册


* CMyWnd::CMyWnd()

CMyWnd::CMyWnd()
{
    LPCTSTR lpszClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,
        ::LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_3DFACE+1));

    CreateEx(WS_EX_CLIENTEDGE, lpszClassName,
        "框架程序创建的窗口", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL);
}

注1:AfxRegisterWndClass()完成窗口类注册,并把窗口函数指向::DefaultWindowProc

注2:CreateEx()通过hook,完成了当前生成窗口函数的修改,指向::AfxWndProc函数,此函数实现了消息处理函数的分派 --------- 即调用CWnd::WindowProc()函数的功能


* WINCORE.CPP::AfxWndProc()

///////////////////////////////////////////////
// 分发消息

LRESULT __stdcall AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
    CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
    ASSERT(pWnd != NULL);
    ASSERT(pWnd->m_hWnd == hWnd);
    return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
}


2. 消息映射


* CCmdTarget

#_AFXWIN.h

////////////////////////////////////////////////////
// CCmdTarget类(命令目标)

class CCmdTarget : public CObject
{
    DECLARE_DYNCREATE(CCmdTarget);
public:
    CCmdTarget();

    DECLARE_MESSAGE_MAP()
};

#cmdtarg.cpp

CCmdTarget::CCmdTarget()
{ }


/////////////////////////////////
// 实现消息映射的代码
const AFX_MSGMAP* CCmdTarget::GetMessageMap () const
{
    return &CCmdTarget::messageMap ;
}
const AFX_MSGMAP CCmdTarget::messageMap =
    { NULL, &CCmdTarget::_messageEntries[0] };
const AFX_MSGMAP_ENTRY CCmdTarget::_messageEntries[] =
{
    // 一个消息也不处理
    { 0, 0, 0, 0, 0, (AFX_PMSG)0 }
};
注:由于CCmdTarget是顶层类,没有父类,故不能使用BEGIN_MESSAGE_MAP()及END_MESSAGE_MAP()两个宏。