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 为函数类型。

WinMain和MFC的差别的更多相关文章

  1. QT和MFC的差别

    QT和MFC的差别 在使用MFC之前就已经使用Qt这个事实可能影响了我的客观性. (MFC效率较高,但大量的Windows API和消息机制使得其较难理解,不易用:QT封装较好,易用且跨平台,但效率较 ...

  2. MFC框架中消失的WinMain()

    学过一段时间的MFC之后,很多人大概都有一个疑问:在MFC中,WinMain()哪去了?因为任何一个使用过Win32 SDK编程的人都知道,WinMain()函数是Win32程序开始的入口点,可是在M ...

  3. 总结《二》MFC中WinMain和CALLBACK

    MFC中WinMain和回调函数CALLBACK 一,路线        1.一般普通窗口或控件建立调用的CWnd :: CreateEx函数        2.经过资源对话框创建的即不调用的CWnd ...

  4. MFC学习-第2,3课 MFC框架的运行机制

    转自:http://blog.163.com/zhigang0633@126/blog/static/38790491200822711526168/ 讲述MFC AppWizard的原理与MFC程序 ...

  5. MFC中存在的不属于任何类的全局函数,它们统统在函数名称开头加上Afx

    MFC中存在的不属于任何类的全局函数,它们统统在函数名称开头加上Afx. 函数名称 说明 AfxWinInit 被WinMain(MFC提供)调用的一个函数,用做MFC GUI程序初始化的一部分,如果 ...

  6. (转)win32Application和win32ApplicationConsole

    这几天在创建MFC项目时,常常遇到一下两个连接错误,例如: 1. LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _ma ...

  7. 孙鑫VC学习系列教程

    教程简介 1.循序渐进 从Win32SDK编程开始讲解,帮助大家理解掌握Windows编程的核心 -- 消息循环机制. 2.通俗易懂 编程语言枯燥难懂,然而通过孙鑫老师形象化的讲解,Windows和M ...

  8. 孙鑫C++教学视频

    视频百度云:https://pan.baidu.com/s/1jKf6GoY 在线观看:http://list.youku.com/albumlist/show?id=3567028&asce ...

  9. <MFC_1>深入剖析MFC的WinMain和消息机制

    一.开篇引论 熟悉Win32开发的朋友,应该非常了解它的基本组成和流程 1. WinMain:书写窗口类(WNDCLASS) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗 ...

随机推荐

  1. PSP需求分析文档

    PSP软件需求分析文档 刘杰 1.       引言 1.1  背景 开发项目经常延期不能按时提交,甚至不能给出明确的延迟时间 1.2  术语 PSP,数据库 2.       任务概述 2.1  目 ...

  2. redis的安装、启动、主从配置,以及.Net下StackExchange.Redis的使用

    开门见山,Linux下配个环境真是苦逼死了,这里记录一下,囧 一.环境 服务端:Ubuntu16.04 LTS(虚拟机,redis官方没有window发布版本,而且在Linux下运行更稳定) 客户端: ...

  3. ci框架中model简单的mysql操作

    <?php class SingerModel extends CI_Model { function SingerModel() { //会将数据库对象赋值给CI_Controller的db属 ...

  4. 三维重建:GitHub百度Apollo 2.0

    GitHub:https://github.com/ApolloAuto/apollo 1. 关于Apollo的数据:Apollo的数据会如何开放? 自动驾驶数据将包括具有高分辨率图像和像素级别标注的 ...

  5. C++写注册表

    1.       注册表简介 注册表是为Windows NT和Windows95中所有32位硬件/驱动和32位应用程序设计的数据文件,用于存储系统和应用程序的设置信息.16位驱动在Winnt (Win ...

  6. CAD绘制一个图象标记对象(com接口VB语言)

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  7. Python之TCP编程

    参考原文 廖雪峰Python教程 客户端 我们知道每一条TCP的连接有2个端点,这两个端点叫做套接字socket.如果我们要进行基于TCP的通信必须先创建套接字.在Python中可以这样创建套接字so ...

  8. 洛谷——P1850 换教室

    P1850 换教室 有 2n 节课程安排在 nn 个时间段上.在第 i个时间段上,两节内容相同的课程同时在不同的地点进行,其中,牛牛预先被安排在教室 $c_i$​ 上课,而另一节课程在教室 $d_i$ ...

  9. KMP瞎扯一下

    什么是KMP KMP俗称看毛片算法,是高效寻找匹配字串的一个算法 百度百科 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为 ...

  10. linux ifstat-统计网络接口流量状态

    推荐:更多linux 性能监测与优化 关注:linux命令大全 ifstat命令就像iostat/vmstat描述其它的系统状况一样,是一个统计网络接口活动状态的工具.ifstat工具系统中并不默认安 ...