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) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗 ...
随机推荐
- Android开发笔记(1)——View
笔记链接:http://www.cnblogs.com/igoslly/p/6781592.html 一.View基础知识 IDE——Integrated Developme ...
- JAVA 学习笔记 - 基础语法 2
---恢复内容开始--- 1.数组的申明和应用 数据类型 数组名称[] = null; //在堆栈中申明变量名称 数组名称 = new 数据类型[10]; // ...
- struts2特殊符号替换
今天用struts2做了一个小例子,结果发现个问题 action代码如下 private String table; public String execute(){ setName("pe ...
- token机制完成登录状态保持/身份认证
一般APP都是刚安装后,第一次启动时需要登录(提示你需要登录或者直接启动在登录界面).而只要登录成功后,以后每次启动时都是登录状态,不需要每次启动时再次登录.不过,也有些APP若你长期未启动,再次启动 ...
- angular5中的自定义指令(属性指令)
属性型指令用于改变一个 DOM 元素的外观或行为. 在 Angular 中有三种类型的指令: 组件 — 拥有模板的指令 结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令 属性型指令 ...
- C++ CEF 浏览器中显示 Tooltip(标签中的 title 属性)
在 Windows 中将 CEF 集成到 C++ 客户端以后,默认是无法显示 tooltip 的,比如图片标签中的 title 属性. 实现的方式其实很简单,按下面的步骤操作就可以: 创建一个文本文件 ...
- 安装ubuntu系统空间分配问题
以下是我安装linux系统(ubuntu)时的系统空间配置,以50G为例: 挂载点 大小 格式 分区类型 / 15G Ext4 主分区 /home 30G Ext4 逻辑分区 /boot 1G Ext ...
- JS中遍历EL表达式中后台传过来的Java集合
前言:在我的项目里有这么一个情况,后台直接model.addAttribute()存储了一个对象,此对象内部有一个集合,前端JSP处理的方法正常情况下就是直接使用EL表达式即可.但是如果在JS中需要使 ...
- IDLE in Python (Ubuntu)
To lauch IDLE in the Current Woking Directory >>> usr/bin/idle3 Alt + n # next command Alt ...
- 洛谷 1569 [USACO11FEB]属牛的抗议
[题解] 非常显然的DP,f[i]表示到第i个位置最多分成几组,f[i]=Max(f[i],f[j]+1) (j<i,sum[j]<=sum[i]) #include<cstdio& ...