MFC-原理分析

 
MFC-原理分析


MFC只留出API供我们调用,我们使用其接口比较简单,但其内部封装及其复杂,要想成为真正的MFC高手,还是得对其内部的封装有所了解,下面就以一个简单的例子,作为对MFC内部结构探讨的开始。

C++代码 复制代码  收藏代码
  1. //HELLO.h   
  2. class CMyApp : public CWinApp   
  3. {   
  4. public:   
  5.     virtual BOOL InitInstance ();   
  6. };   
  7.   
  8. class CMainWindow : public CFrameWnd   
  9. {   
  10. public:   
  11.     CMainWindow ();   
  12.   
  13. protected:   
  14.     afx_msg void OnPaint ();   
  15.     DECLARE_MESSAGE_MAP ()   
  16. };   
  17.   
  18. //HELLO.cpp   
  19. #include <afxwin.h>   
  20. #include "Hello.h"   
  21.   
  22. CMyApp myApp;   
  23.   
  24. /   
  25. // CMyApp member functions   
  26.   
  27. BOOL CMyApp::InitInstance ()   
  28. {   
  29.     m_pMainWnd = new CMainWindow;   
  30.     m_pMainWnd->ShowWindow (m_nCmdShow);   
  31.     m_pMainWnd->UpdateWindow ();   
  32.     return TRUE;   
  33. }   
  34.   
  35. /   
  36. // CMainWindow message map and member functions   
  37.   
  38. BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)   
  39.     ON_WM_PAINT ()   
  40. END_MESSAGE_MAP ()   
  41.   
  42. CMainWindow::CMainWindow ()   
  43. {   
  44.     Create (NULL, _T ("The Hello Application"));   
  45. }   
  46.   
  47. void CMainWindow::OnPaint ()   
  48. {   
  49.     CPaintDC dc (this);   
  50.        
  51.     CRect rect;   
  52.     GetClientRect (&rect);   
  53.   
  54.     dc.DrawText (_T ("Hello, MFC"), -1, &rect,   
  55.         DT_SINGLELINE | DT_CENTER | DT_VCENTER);   
  56. }  


这个程序及其简单,就是输出"Hello, MFC"。

一、程序的入口

这个程序怎样运行的呢?它即没有main,也没有winmain,以及其他的函数入口,那么它是如何运行,难道会从天而降一个入口函数?

其实这个程序的入口在这里:

_tWinMain->AfxWinMain

-->int AFXAPI AfxWinMain()//位于:WINMAIN.cpp
{
    CWinApp* pApp=AfxGetApp();//pApp指向CMyWinApp.
    AfxWinInit(...);
    pApp->InitApplication();
    pApp->InitInstance();
    nReturnCode = pApp->Run();
    return 0;
}
其中AfxGetApp();//pApp指向CMyWinApp.就是取得CMyWinApp对象,所以AfxWinMain中的
    pApp->InitApplication();
    pApp->InitInstance();
    nReturnCode = pApp->Run();

就相当与:
    CMyWinApp->InitApplication();
    CMyWinApp->InitInstance();
    nReturnCode = CMyWinApp->Run();

也就是:
    CWinApp->InitApplication();//CMyWinApp并没有改写InitApplication()
    CMyWinApp->InitInstance();//CMyWinApp改写了InitInstance()
    nReturnCode = CWinApp->Run();//CMyWinApp并没有改写Run()

所以其入口函数的调用顺序为:
_tWinMain->AfxWinMain ->    CWinApp->InitApplication();
                            CMyWinApp->InitInstance();
                            CWinApp->Run();

这样便进入到当前程序里。

二、如何产生窗口

C++代码 复制代码  收藏代码
  1. BOOL CMyApp::InitInstance ()   
  2. {   
  3.     m_pMainWnd = new CMainWindow;   
  4.     m_pMainWnd->ShowWindow (m_nCmdShow);   
  5.     m_pMainWnd->UpdateWindow ();   
  6.     return TRUE;   
  7. }  


1. m_pMainWnd = new CMainWindow;
其中m_pMainWnd 是CWnd对象指针:CWnd* m_pMainWnd;  在这里用 用户自定义窗口CMainWindow初始化,从而调用CMainWindow::CMainWindow() 

C++代码 复制代码  收藏代码
  1. CMainWindow::CMainWindow ()   
  2. {   
  3.     Create (NULL, _T ("The Hello Application"));   
  4. }  


Create (NULL, _T ("The Hello Application"));用来创建一个窗口。

其声明为:
virtual BOOL Create(
   LPCTSTR lpszClassName,
   LPCTSTR lpszWindowName,
   DWORD dwStyle,
   const RECT& rect,
   CWnd* pParentWnd,
   UINT nID,
   CCreateContext* pContext = NULL
);

2.m_pMainWnd->ShowWindow (m_nCmdShow);

当Create (NULL, _T ("The Hello Application"));完成后,程序又回到m_pMainWnd->ShowWindow (m_nCmdShow);来显示窗口。

3.m_pMainWnd->UpdateWindow ();

m_pMainWnd->ShowWindow (m_nCmdShow);来显示窗口后调用m_pMainWnd->UpdateWindow ();来更新窗口。

三、消息的传递

窗口创建后如何发送消息,使得响应消息的函数得以调用,本例中响应消息的函数是OnPaint ()用来在窗口中显示"Hello, MFC"字符,那么这个消息如何传递?

在调用m_pMainWnd->UpdateWindow ()时会发送WM_PAINT消息,此消息有谁获得,又是怎样发送出去的?

MFC程序和SDK程序一样,有一个GetMessage/DispatchMessage循环,用来获得消息和发送消息。而且每一个窗口都有一个窗口函数,并以某种方式进行消息的判断和响应。

当m_pMainWnd->UpdateWindow ()发送WM_PAINT消息后,CWinApp->Run();用循环判断来接受消息,并DispatchMessage发送出去。

四、MessageMap消息映射图及其消息响应机制

当CWinApp->Run();把接受到的消息发送出去后,是如何找到相应的响应函数,这就用到了MessageMap消息映射图。

C++代码 复制代码  收藏代码
  1. DECLARE_MESSAGE_MAP ()   
  2. BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)   
  3.     ON_WM_PAINT ()   
  4. END_MESSAGE_MAP ()   
  5. afx_msg void OnMyPaint ();  


这些宏构成了复杂的消息映射网。

CWinApp->Run()把接受到的消息发送到CWnd::DefWindowProc中,然后CWnd::DefWindowProc将绕行消息映射表MessageMap,绕行的过程中,发现吻合的函数,于是调用相应的函数。此函数是通过BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间的宏建立的连接。

这个例子中m_pMainWnd->UpdateWindow ()发送WM_PAINT消息,而CWinApp->Run()把接受到的消息发送到CWnd::DefWindowProc中,在映射表中会有
#define ON_WM_PAINT() \
{ WM_PAINT, 0, 0, 0, AfxSig_vv, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(void) > ( &ThisClass :: OnPaint)) },

会把WM_PAINT和&ThisClass :: OnPaint联系在一起,那么void CMainWindow::OnPaint ()就会被调用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值