MFC框架剖析(二)

具体的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应用程序对其进行了封装,实际上原理是一样的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值