微软MFC技术中的消息队列及消息处理(下)

 

我是荔园微风,作为一名在IT界整整25年的老兵,今天来聊聊微软MFC技术中的消息队列及消息处理。

MFC应用程序中由Windows 系统以消息的形式发送给应用程序的窗口。窗口接收和处理消息之后,把控制返回给Windows。Windows系统在同一时间可显示多个窗口。此系统利用消息队列来记录鼠标和键盘输入到相应窗口等消息。如果用户移动鼠标或敲一下键盘,鼠标或键盘的设备驱动器都会把此输入转换成消息,并把它们放到系统消息队列中去。Windows从系统队列中每次读取一条消息, 然后将其从队列中删除,之后处理它们发送到相应的窗口过程。

消息队列是一种先进先出的队列型数据结构,它实际上是系统内核中的一个内部链表。用户可以从消息队列中添加消息和读取消息,而消息则被顺序地插入到队列中。其中发送进程将消息添加到队列末尾,接收进程会从队列头读取消息。

今天我们接之前的《微软MFC技术中的消息队列及消息处理(上)》继续往下讲。

详解具体实例——消息的处理

首先用visual studio 2022新建一个工程名为Win32_message的Win32应用程序。工程建好后,新建一个源文件,命名为 Win32_message.cpp。此程序实现的功能是创建一个窗口,当按键盘上的按键时,会出现一个消息盒子,如“所按键的字符值是98”。如果按下Backspace键时,一旦消息发送成功,会出现有“发送后退消息成功”提示语句的消息盒子,否则,会出现“发送后退消息失败”等类似其他消息响应。我们来看看下面的代码,先看此程序的入口函数WinMain()。

Win32应用程序入口函数示例:Win32_message.cpp

//Win32应用程序入口函数WinMain()
int WINAPI WinMain(
  HINSTANCE hInstance,      //指向当前实例的句柄
  HINSTANCE hPrevInstance,      //指向先前实例的句柄
  LPSTR lpCmdLine,      //命令行
  int nCmdShow         //显示状态
)
{
  WNDCLASS wndclass;      //创建一个窗口类 
  wndclass. cbClsExtra=0;     //窗口类无扩展
  wndclass. cbWndExtra=0;    //窗口实例无扩展
  wndclass. hbrBackground=(HBRUSH)GetStockObject (BLACK_BRUSH);  //窗口背景为黑
  wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);    //窗口采用箭头光标
   wndclass. hIcon=LoadIcon(NULL, IDI_APPLICATION);  //窗口的最小化图标为缺省
  wndclass. hInstance=hInstance:  //当前实例句柄
  wndclass. lpfnWndProc=WinHouProc    //定义窗口处理函数
  wndclass.lpszClassName="VC++";      //窗口类为“VC++”
  wndclass.lpszMenuName=NULL;        //窗口无菜单
  wndclass.style=CS_HREDRAW|CS_PARENTDC;          //设置窗口类型
  RegisterClass(&wndclass);        //注册窗口类

  HWND hwnd;
  hwnd=CreateWindow("VC++","消息机制",WS_OVERLAPPEDWINDOW,0,0, 600, 400, NULL, NULL, hInstance, NULL);       //创建窗口

  ShowWindow(hwnd, SW_SHOWNORMAL);         //显示窗口
  UpdateWindow(hwnd);                 //更新窗口

  MSG msg;
  while(GetMessage 6msg, NULL,0,0))       //获取消息
  {
      TranslateMessage (&msg);
      DispatchMessage (&msg);
   }
  return 0;
}

从代码可以大致看出此程序的运行机制。要想显示一个窗口并执行各种命令,应先创建一个窗口。第9行对应创建窗口类这一步,而第16行表明将函数 WinHouProc()赋给此窗口的消息响应函数。第20行对应注册窗口类,这样一个窗口类已形成。接下来第23行就要定义一个窗口的大小、位置、窗口显示名字等信息。窗口也创建好之后,第26~27行就要显示窗口并实时更新此窗口的状态。最后第30行就是要处理关联此窗口的各种消息,判断当前是否得到消息,并形成循环。

讨论完入口函数,就要介绍此窗口的消息响应函数,代码为下面所示的消息响应函数WinHouProc()。

Win32应用程序消息响应函数示例:Win32_message.cpp

LRESULT CALLBACK WinHouProc(
  HWND hwnd,          //窗口句柄
  UINT uMsg,          //消息标识符
  WPARAM WParam,      //第一个消息参数
  LPARAM lParam        //第二个消息参数
)
{
  switch(uMsg)
  {
  case WM_CHAR:
      switch(wParam)      //显示所按键值
     {
      case 0x08:         //后退键
           if(PostMessage (hwnd, WM_KEYDOWN, VK_DELETE, 1L))
                MessageBox(hwnd,"发送后退消息成功","VC++",0);
             else
                 MessageBox(hwnd,"发送后退消息失败","VC++",0);
             break;
      default:
            break;
       }
    char szChar[20];
    sprintf(szChar,"所按字符值是%d",wParam);      //转换按键值类型
     MessageBox(hwnd, szChar, "VC++", 0);        //显示按键的值
      break;
   case WM_CLOSE:       //有提示消息的关闭窗口
      if(IDYES=MessageBox(hwnd,"是否结束?","VC++",MB_YESNO)   //判断
           DestroyWindow(hwnd);       //銷毀窗口
      break;
  case WM_DESTROY:                //强制关闭
    PostQuitMessage(0);       //发送关闭消息
    break;
  default:
    return DefWindowProc(hwnd,uMsg,wParam,lParam);     //返回窗口过程
   }
  return 0;
}

代码说明了3种功能:显示按键值、有提示消息的关闭、强制关闭。第14行是PostMessage()函数的应用,如果后退消息发送成功,就提示“发送后退消息成功”。第31行 PostQuitMessage()是 PostMessage()传递关闭消息的一种简单形式。

但是要注意的是,如果是在比VC++6.0和VS2003高级的版本上运行以上所编的程序时,就是立刻报一大堆错,应修改一下工程的编码选项:项目属性——常规——字符集——使用多字节字符集。否认显示文字部分会出现乱码。因为VC++6.0与VS2003默认使用ANSI编码,而VS2022及以上版本默认采用 Unicode。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MFCMicrosoft Foundation Classes)是一组用于开发 Windows 应用程序的 C++ 类库。在 MFC 消息映射是一种机制,用于将 Windows 消息与相应的消息处理函数关联起来。 消息映射是通过在类的消息映射表定义消息处理函数来实现的。消息映射表是一个由宏定义和消息映射项组成的静态数组。每个消息映射项指定了一个 Windows 消息的 ID 和相应的消息处理函数。 消息处理函数是类的成员函数,用于处理特定的 Windows 消息。当一个窗口接收到一个消息时,MFC 会根据消息映射表的定义找到对应的消息处理函数,并执行该函数来处理消息。 下面是一个简单的示例,展示了如何使用消息映射和消息处理函数: ```cpp // 声明消息映射表 BEGIN_MESSAGE_MAP(CMyWnd, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() // 定义消息处理函数 void CMyWnd::OnPaint() { // 处理 WM_PAINT 消息 // ... } void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point) { // 处理 WM_LBUTTONDOWN 消息 // ... } ``` 在上面的示例,`CMyWnd` 是一个继承自 `CWnd` 的自定义窗口类。通过在消息映射表使用 `ON_WM_PAINT` 宏和 `ON_WM_LBUTTONDOWN` 宏,将 `OnPaint` 函数和 `OnLButtonDown` 函数与 `WM_PAINT` 消息和 `WM_LBUTTONDOWN` 消息关联起来。 当窗口接收到相应的消息时,就会调用对应的消息处理函数进行处理。 需要注意的是,消息映射表消息处理函数必须是类的成员函数,并且符合特定的函数签名。 希望这个简单的解释能够帮助你理解 MFC 消息映射与消息处理机制。如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值