具体的mfc是怎么封装和实现的,必须得对微软的程序内部运行机制了解清楚,才能更深的了解mfc的框架。
想起有段经典的代码,在网上找到后,新建了一个简单的win32的应用程序,空项目,新建一个cpp粘贴进去,无误后,干脆专门就这一段代码分析一下windows的程序内部运行的机制,了解这个机制后,再在这个简单的机制上面寻找MFC 的封装过程,也为了更好的理解mfc的框架
1:网上找的windows程序内部运行机制的代码,贴出来留个底,在代码上也作了简单的注释
//WinMain.cpp
#include <windows.h>
#include <stdio.h>
//回调函数的声明
LRESULTCALLBACK WinAzeProc(
HWNDhwnd, // 窗口句柄
UINTuMsg, // 消息标识
WPARAMwParam,// 消息属性的第一个值
LPARAMlParam // 消息属性的第二个值
);
//入口函数
intWINAPI WinMain(
HINSTANCEhInstance, // 当前实例的句柄
HINSTANCEhPrevInstance,// 先前实例的句柄
LPSTRlpCmdLine, // 命令行语句
intnCmdShow // 显示的状态
)
{
//设计一个窗口类 通过WNDCLASS 结构体设计一个窗口类
WNDCLASS wndcls;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndcls.hCursor = LoadCursor(NULL, IDC_CROSS); //定义窗口光标的图标
wndcls.hIcon = LoadIcon(NULL, IDI_ERROR); //定义当前窗口的图标
wndcls.hInstance = hInstance; //应用程序实例句柄由WinMain函数传进来
wndcls.lpfnWndProc = WinAzeProc; //回调函数
wndcls.lpszClassName = "aze_003";//窗口类的名称
wndcls.lpszMenuName = NULL;
wndcls.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndcls); //注册窗口类
//创建窗口,定义一个变量用来保存成功创建后返回的句柄
HWNDhwnd;
hwnd = CreateWindow("aze_003","first Application", WS_OVERLAPPEDWINDOW, 0, 0, 600, 500, NULL, NULL,hInstance, NULL);
ShowWindow(hwnd, SW_SHOWNORMAL); //显示窗口
UpdateWindow(hwnd); //刷新窗口
//定义消息结构体,开始消息循环
MSG msg;
while( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);//将虚拟键消息转换成字符消息存在(&msg)中,并且存在wParam中
DispatchMessage(&msg);//函数将消息分发给操作系统,然后在给回调函数
}
returnmsg.wParam;
}
//编写窗口过程函数
LRESULTCALLBACK WinAzeProc(
HWNDhwnd, // 窗口句柄
UINTuMsg, // 消息标识
WPARAMwParam,// 消息第一个参数
LPARAMlParam // 消息第二个参数
)
{
switch(uMsg)
{
caseWM_CHAR://键盘消息
charszChar[20];
sprintf(szChar,"char code is %d", wParam);
MessageBox(hwnd, szChar, "char", 0);
break;
caseWM_LBUTTONDOWN://鼠标左击消息
MessageBox(hwnd,"mouse clicked","message", 0);
HDChdc;
hdc = GetDC(hwnd); //不能在响应WM_PAINT消息时调用
TextOut( hdc, 0, 50, "程序员之家!",strlen("程序员之家!") );
ReleaseDC(hwnd, hdc);
break;
caseWM_PAINT://窗口重绘消息
HDChDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hwnd, &ps); //BeginPaint只能在响应WM_PAINT消息是调用
TextOut(hDC, 0, 0, "http://www.sunxin.org",strlen("http://www.sunxin.org"));
EndPaint(hwnd, &ps);
break;
caseWM_CLOSE://窗口关闭消息
if( IDYES == MessageBox(hwnd, "是否真的退出?","message", MB_YESNO) )
{
DestroyWindow(hwnd);
}
break;
caseWM_DESTROY://窗口销毁消息
PostQuitMessage(0);
break;
default://默认消息
returnDefWindowProc(hwnd, uMsg, wParam, lParam);
}
return0;
}
2:通过上面大致的了解程序的运行机制:
1:编写入口函数winmain
2: 创建窗口
1、设计一个窗口类
2、注册设计好的窗口类
3、根据设计的窗口类,创建一个窗口
4、显示并且更新创建的窗口
3:编写消息循环,并且在消息队列中取得消息
4:编写窗口过程函数
3:概括windows程序的运行机制
windows程序设计模式是事件驱动方式的一种设计模式,它是基于消息的。当系统感知到一个用户或者系统的事件的时候,系统会将事件包装成消息,然后传输到应用程序的消息队列中,然后应用程序从消息队列中取出消息进行响应。在这个处理过程中,系统也会向应用程序“发送消息”,“发送消息”是指:操作系统调用应用程序中一个负责处理窗口过程函数
1、
每个事件都被封装成一个MSG的结构体,在windows中,消息是由一个个数值来表示的。由于每个数值不好记忆,windows将消息对应是数值定义成了WM_XXX的宏
2、消息队列:系统会在每个程序运行后为程序提供一个消息队列,这个消息队列主要是为了存放和更改关于这个窗口的一些消息的
3、回调函数的实现机制:
a:定义一个回调函数
b:提供函数实现的一方在初始化的时候,将回调函数的函数的指针注册给调用者
c:当特定的时间或者条件发生的时候,调用者使用函数指针调回回调函数对事件进行处理
4、针对windows的消息处理机制,窗口过程函数表调用的过程如下:
a:在设计窗口类的时候,将窗口过程函数的地址复制给lpfnWndProc成员变量
b:调用registerclass注册窗口类,那么系统就有了我们所填写的窗口过程函数的地址。
c:当应用程序接收到某个窗口的消息时,调用dispachmessage将对消息回传给系统,系统利用先前注册窗口类得到的函数指针,调用窗口过程函数对消息进行处理
提示:一个windows程序可以包含多个窗口过程函数,一个窗口过程函数总是与某一个特定的窗口类关联(通过WNDCLASS结构体中的lpfnWndProc成员变量指定),基于该窗口创建的窗口使用同一个窗口过程。
4:windows应用程序的消息处理过程
1、消息中有句柄将消息归属给某个应用程序,操作系统收到应用程序的消息后,根据包装好后的消息句柄,将消息投递给对应的应用程序的队列中;
2、应用程序在消息循环汇总调用getmessage函数从消息队列中取出一条条的消息,取出消息后,应用程序对消息进行一些预处理,如:放弃某些消息的相应,或者带调用translatemessage产生新的消息
3、应用程序调用dispatchmessage,将消息传递给操作系统
4、系统利用wndclass结构体的lpfnwndproc成员保存窗口过程函数的指针调用窗口过程,对消息进行处理
以上的部分也是mfc框架程序内部运行的机制,只不过mfc应用程序对其进行了封装,实际上原理是一样的