WinMain和MFC的差别
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的差别的更多相关文章
- QT和MFC的差别
QT和MFC的差别 在使用MFC之前就已经使用Qt这个事实可能影响了我的客观性. (MFC效率较高,但大量的Windows API和消息机制使得其较难理解,不易用:QT封装较好,易用且跨平台,但效率较 ...
- MFC框架中消失的WinMain()
学过一段时间的MFC之后,很多人大概都有一个疑问:在MFC中,WinMain()哪去了?因为任何一个使用过Win32 SDK编程的人都知道,WinMain()函数是Win32程序开始的入口点,可是在M ...
- 总结《二》MFC中WinMain和CALLBACK
MFC中WinMain和回调函数CALLBACK 一,路线 1.一般普通窗口或控件建立调用的CWnd :: CreateEx函数 2.经过资源对话框创建的即不调用的CWnd ...
- MFC学习-第2,3课 MFC框架的运行机制
转自:http://blog.163.com/zhigang0633@126/blog/static/38790491200822711526168/ 讲述MFC AppWizard的原理与MFC程序 ...
- MFC中存在的不属于任何类的全局函数,它们统统在函数名称开头加上Afx
MFC中存在的不属于任何类的全局函数,它们统统在函数名称开头加上Afx. 函数名称 说明 AfxWinInit 被WinMain(MFC提供)调用的一个函数,用做MFC GUI程序初始化的一部分,如果 ...
- (转)win32Application和win32ApplicationConsole
这几天在创建MFC项目时,常常遇到一下两个连接错误,例如: 1. LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _ma ...
- 孙鑫VC学习系列教程
教程简介 1.循序渐进 从Win32SDK编程开始讲解,帮助大家理解掌握Windows编程的核心 -- 消息循环机制. 2.通俗易懂 编程语言枯燥难懂,然而通过孙鑫老师形象化的讲解,Windows和M ...
- 孙鑫C++教学视频
视频百度云:https://pan.baidu.com/s/1jKf6GoY 在线观看:http://list.youku.com/albumlist/show?id=3567028&asce ...
- <MFC_1>深入剖析MFC的WinMain和消息机制
一.开篇引论 熟悉Win32开发的朋友,应该非常了解它的基本组成和流程 1. WinMain:书写窗口类(WNDCLASS) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗 ...
随机推荐
- Java:一个简捷的可分页的ResultSet实现
内容 前言 JDBC和分页 和具体数据库相关的实现方法 另一种繁琐的实现方法 使用Vector进行分页 一个新的Pageable接口及其实现 Pageable的使用方法 总结 参考资料 关于作者 前言 ...
- c++写入txt
用ofstream 输出流,#include <fstream> ofstream outf; outf.open("abc.txt");outf<<123 ...
- 【转载】文件上传命令rz和下载命令sz的安装
一.xshell工具简介 Xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议.其可以在Windows界面下用来访 ...
- 面向对象程序设计--Java语言第一周编程题:分数
分数 题目内容: 设计一个表示分数的类Fraction.这个类用两个int类型的变量分别表示分子和分母. 这个类的构造函数是: Fraction(int a, int b) 构造一个a/b的分数. 这 ...
- 关于dijkstra的小根堆优化
YY引言 在NOI2018D1T1中出现了一些很震惊的情况,D1T1可以用最短路解决,但是大部分人都在用熟知的SPFA求解最短路.而SPFA的最坏复杂度能够被卡到$O(VE)$.就是边的数量乘以点的数 ...
- [Algorithm] 10. Reverse Integer
Description Given a 32-bit signed integer, reverse digits of an integer. Example Example 1: Input: 1 ...
- 使用 resultMap 实现高级结果集映射
resultMap 的基本配置项 属性 id 属性:resultMap 的唯一标识,此 id 值用于 select 元素 resultMap 属性的引用. type 属性:表示该 resultMap ...
- 使用vuex实现父组件调用子组件方法
曲线救国. 核心原理就是父子共用一个vuex对象,且看代码: 父组件parent.vue <template> <div class="wrap"> < ...
- CCF201604-1 折点计数 java(100分)
试题编号: 201604-1 试题名称: 折点计数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给定n个整数表示一个商店连续n天的销售量.如果某天之前销售量在增长,而后一天 ...
- 洛谷 3178 [HAOI2015]树上操作
[题解] 就是个树链剖分的模板题. #include<cstdio> #include<algorithm> #include<cstring> #define L ...