API(Application Programming Interface):开放给应用程序调用的系统功能。

一个Windows Application(SDK):

WinMain

ReristerClass

CreateWindow

GetMessage/DispatchMessage

/Window Procedure

various Windows APIs

一个MFC Application:

WinMain由MFC提供

RegisterClass包装于AfxWinInit中

CreateWindow在CWinApp::InitInstance中调用

GetMessage/DispatchMessage包装在CWinApp::Run中

Window Procedure由MFC提供

Windows APIs包装在MFC各类中

Massage Mapping, Message Routing.

Dynamic Creation, Serialization.

CWinApp代表程序本体——代替WndProc

传统上SDK程序的WinMain所完毕的工作如今由CWinAoo的三个函数完毕:

virtual BOOL InitApplication();

virtual BOOL InitInstance();

virtual int Run();

WinMain仅仅是扮演驾驶它们的角色。

传统的SDK窗体函数写法是:

long FAR PASCAL WndProc(HWND hWnd, UINT msg, WORD wParam, LONG lParam)
{
switch(msg) {
case WM_COMMAND :
swtich(wParam) {
case IDM_ABOUT :
OnAbout(hWnd, wParam, lParam);
break;
}
break;
case WM_PAINT :
OnPaint(hWnd, wParam, lParam);
break;
default :
DefWindowProc(hWnd, msg, wParam, lParam);
}
}

MFC中使用两个函数OnPaint(),OnAbout()与其相应。MFC中的声明例如以下:

class CMyFrameWnd : public CFrameWnd
{
public :
CMyFrameWnd();
afx_msg void OnPaint();
afx_msg void OnAbout();
DECLARE_MESSAGE_MAP()
}

OnPaint处理WM_PAINT

OnAbout处理WM_COMMAND和IDM_ABOUT

MFC内建的一个Message机制。会把消息自己主动送到“与消息相应的特定函数”中去,消息与相应函数之间的相应关系由程序猿指定。DECLARE_MESSAGE_MAP另搭配其他宏,就能够非常便利的将消息与其处理函数关联在一起:

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)

ON_WM_PAINT()

ON_COMMAND(IDM_ABOUT, OnAbout)

END_MESSAGE_MAP()

/***********************************************************/
/* WINMAIN.CPP */
/***********************************************************/
/* int AFXAPI AfxWinMain (...) */
/* { */
/* CWinApp* pApp = AfxGetApp(); */
/* */
/* AfxWinInit(...); */
/* */
/* pApp->InitApplication(); */
/* pApp->InitInstance(); */
/* nReturnCode = pApp->Run(); */
/* */
/* AfxWinTerm(); */
/* } */
/***********************************************************/
/* HELLO.CPP */
/***********************************************************/
/* CMyWinApp theApp; //application object */
/* */
/* BOOL CMyWinApp::initInstance() */
/* { */
/* m_pMainWnd = new CMyFrameWnd(); */
/* m_pMainWnd->ShowWindow(m_nCmdShow); */
/* m_pMainWnd->UpdateWindow(); */
/* return TRUE; */
/* } */
/* */
/* CMyFrameWnd::CMyFrameWnd() */
/* { */
/* Create(NULL, "Hello MFC", ..., "MainMenu"); */
/* } */
/* */
/* void CMyFrameWnd::OnPaint() {...} */
/* void CMyFrameWnd::OnAbout() {...} */
/* */
/* BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) */
/* ON_COMMAND(IDM_ABOUT, OnAbout) */
/* ON_WM_PAINT() */
/* END_MESSAGE_MAP() */
/***********************************************************/

Application object:每个MFC应用程序都有一个,并且仅仅有一个。

WINMAIN.CPP中,AfxGetApp事实上就是取得CMyWinApp对象指针。所以,AfxWinMain中这种操作:

CWinApp* pApp = AfxGetApp();

pApp->InitApplication();

pApp->InitInstance();

nReturnCode = pApp->Run();

事实上就相当于调用:

CMyWinApp::InitApplication();

CMyWinApp::InitInstance();

CMyWinApp::Run();

因而导致调用:

CWinApp::InitApplication(); //由于CMyWinApp并没有改写InitApplication

CMyWinAPP::InitInstance(); //由于CMyWinApp改写了InitInstance

CWinApp::Run(); //由于CMyWinApp并没有改写Run

AfxWinInit——AFX内部初始化操作

WinMain一開始即调用AfxWinInit,注冊四个窗体类。

MFC中也会为我们注冊窗体类,但不再是在AfxWinInit中完毕。

pApp指向CMyWinApp对象(theApp)。所以,当程序调用:

pApp->InitApplication();

CMyWinApp继承自CWinApp,而InitApplication又是CWinApp的一个虚拟函数;若我们并没有改写它(大部分情况下不需改写它),上述操作相当于调用:

CWinApp::InitApplication();

与此类似,当程序调用

pApp->InitInstance();

相当于调用:

CMyWinApp::InitInstance();。

CFrameWnd::Create 产生主窗体(并先注冊窗体类)

CMyWinApp::InitInstance 一開始new了一个CMyFrameWnd对象,准备用作主框窗体的C++对象。

new会引发构造函数:

CMyFrameWnd::CMyFrameWnd()

{

Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault, NULL, "MainMenu");

}

当中,Create是CFrameWnd的成员函数,他将产生一个窗体。

CFrame::Create的规格:

BOOL Create(LPCTSTR lpszClassName, //指定WNDCLASS窗体类

LPCTSTR lpszWindowName,
//指定窗体标题

DWORD dwStyle = WS_OVERLAPPEDWINDOW,
//指定窗体风格

const RECT& rect = rectDefault,
//指定窗体的位置与大小

CWnd* pParentWnd = NULL,
//指定父窗体

LPCTSTR lpszMenuName = NULL,
//指定菜单

DWORD dwExStyle = 0,

CCreateContext* pContext = NULL );
//指向CCreateContext结构的指针,framework利用它,在具备Document/View结构的程序中初始化外框窗体.

pApp指向CMyWinApp对象(theApp)。所以,当程序调用:

pApp->Run();

相当于调用:

CMyWinApp::Run();

把消息与处理函数连接在一起:Message Map机制





MFC提供给应用程序使用的“非常方便的接口”是两组宏。以Hello的主窗体为例。第一个操作是在HELLO.H的CMyFrameWnd加上DECLARE_MESSAGE_MAP:

class CMyFrameWnd : public CFrameWnd

{

public :

CMyFrameWnd();

afx_msg void OnPaint();

afx_msg void OnAbout();

DECLARE_MESSAGE_MAP();

}

第二个操作是在HELLO.CPP的不论什么位置(当然不能在函数之内)使用宏例如以下:

BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)

ON_WM_PAINT()

ON_COMMAND(IDM_ABOUT, OnAbout)

END_MESSAGE_MAP()





MFC把消息主要分为三大类。Message Map机制中对于消息与函数间的相应关系也明白下面三种:

  标准Windows消息(WM_xxx)的相应规则:

    |-----------------------------------------------------------------------------|
| 宏名称 | 相应消息 | 消息处理函数(名称已由系统默认) |
|-------------------|-------------------|-------------------------------------|
| ON_WM_CHAR | WM_CHAR | OnChar |
|-------------------|-------------------|-------------------------------------|
| ON_WM_CLOSE | WM_CLOSE | OnClose |
|-------------------|-------------------|-------------------------------------|
| ON_WM_CREATE | WM_CREATE | OnCreate |
|-------------------|-------------------|-------------------------------------|
| ON_WM_DESTROY | WM_DESTROY | OnDestroy |
|-------------------|-------------------|-------------------------------------|
| ON_WM_LBUTTONDOWN | WM_LBUTTONDOWN | OnLButtonDown |
|-------------------|-------------------|-------------------------------------|
| ON_WM_LBUTTONUP | WM_LBUTTONUP | OnLButtonUp |
|-------------------|-------------------|-------------------------------------|
| ON_WM_MOUSEMOVE | WM_MOUSEMOVE | OnMouseMove |
|-------------------|-------------------|-------------------------------------|
| ON_WM_PAINT | WM_PAINT | OnPaint |
|-----------------------------------------------------------------------------|

命令消息(WM_COMMAND)的一般相应规则是:

    ON_COMMAND(<id>, <memberFxn>)

    比如:

ON_COMMAND(IDM_ABOUT,
OnAbout)

ON_COMMAND(IDM_FILENEW,
OnFileNew)

ON_COMMAND(IDM_FILEOPEN,OnFileOpen)

ON_COMMAND(IDM_FILESAVE,OnFileSave)

  "Notification消息"(由控件产生。比如 BN_xxx)的相应机制的宏分为好几种(由于控件分为好几种),例:

    |-----------------------------------------------------------|
| 控件 | 宏名称 |消息处理函数|
|----------|-----------------------------------|------------|
| Button | ON_BN_CLICKED(<id>,<memberFxn>) | memberFxn |
|----------|-----------------------------------|------------|
| ComboBox | ON_CBN_DBLCLK(<id>,<memberFxn>) | memberFxn |
|----------|-----------------------------------|------------|
| Edit | ON_EN_SETFOCUS(<id>,<memberFxn>) | memberFxn |
|----------|-----------------------------------|------------|
| ListBox | ON_LBN_DBLCLK(<id>,<memberFxn>) | memberFxn |
|-----------------------------------------------------------|

各个消息处理函数均以afx_msg void 为函数类型。

05-25 15:40