浅浅的理解消息响应机制

实话说,刚开始做视觉,那时候自己写框架,还经常不会用子窗口调用主窗口;指针也用不起来,所以,每次,最终的解决方法就是用消息传递。刚开始在书上看是基于消息响应,其实不太明白干啥的。现在理解的就是,你需要和某人建立关系,然后你俩需要一个指令,这个指令就是消息传递函数,具体传的啥,就看你函数写啥就会执行响应的动作,但是需要知道是谁给谁传递。所以就有一些主从关系和函数在。

两年前看QT的框架,发现槽函数和消息响应机制其实都差不多;可惜,当时做的框架也不知道去哪了,现在已经把QT忘光了。等改天有空,找出来好好学习拾起来QT。

DEEPSEEK搜MFC中的消息响应机制:
在 MFC(Microsoft Foundation Classes)框架中,消息响应机制是其核心设计之一,用于处理 Windows 窗口消息(如鼠标事件、键盘输入、控件通知等)。MFC 通过**消息映射(Message Map)**将 Windows 消息与对应的处理函数绑定,简化了传统 Win32 API 的复杂消息处理流程。以下是其核心要点:


1. MFC 消息机制的基础模型

  • 消息来源:Windows 系统生成的消息(如 WM_PAINT, WM_COMMAND)。
  • 消息接收者:MFC 窗口类(如 CWnd 派生类)或应用程序类(CWinApp)。
  • 消息路由:通过消息映射表将消息分发给对应的处理函数。

2. 消息处理流程

(1) 消息循环(Message Pump)
  • 位置CWinApp::Run() 中实现。
  • 作用:循环从系统消息队列中获取消息(GetMessage),并通过 DispatchMessage 分发到目标窗口。
    while (GetMessage(&msg, nullptr, 0, 0)) {
      TranslateMessage(&msg);  // 转换键盘消息(如 WM_CHAR)
      DispatchMessage(&msg);   // 分发到窗口过程
    }
    
(2) 窗口过程(Window Procedure)
  • MFC 封装了默认的窗口过程 AfxWndProc,通过消息映射表将消息路由到对应的类成员函数。
  • 关键步骤
    1. 收到消息后,MFC 查找目标对象(窗口或控件)的消息映射表。
    2. 根据消息类型(如 WM_COMMAND)和标识符(如按钮 ID),调用对应的处理函数。

3. 消息映射(Message Map)

(1) 定义消息映射表
  • 在类的头文件(.h)中声明消息处理函数,并使用 DECLARE_MESSAGE_MAP() 宏。
  • 在实现文件(.cpp)中使用宏绑定消息与处理函数:
    BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
      ON_WM_PAINT()           // 处理 WM_PAINT 消息
      ON_COMMAND(ID_BUTTON1, &CMyDialog::OnButton1Clicked)  // 处理按钮点击
      ON_MESSAGE(WM_MYCUSTOM, &CMyDialog::OnMyCustomMessage) // 自定义消息
    END_MESSAGE_MAP()
    
(2) 常见消息类型
  • 窗口消息:以 ON_WM_XXX 宏绑定(如 ON_WM_PAINT())。
  • 命令消息:控件或菜单触发的 WM_COMMAND,通过 ON_COMMAND 绑定。
  • 通知消息:控件的特定事件(如列表框选择变化),通过 ON_NOTIFY 绑定。
  • 自定义消息:使用 ON_MESSAGE 宏处理用户定义的 WM_APP + n 消息。

4. 消息处理函数

  • 函数签名:返回 LRESULT,参数为 WPARAMLPARAM(或特定参数类型)。
  • 示例
    // 处理 WM_PAINT 消息
    void CMyView::OnPaint() {
      CPaintDC dc(this);  // 自动调用 BeginPaint/EndPaint
      dc.TextOut(10, 10, L"Hello MFC");
    }
    
    // 处理按钮点击(WM_COMMAND)
    void CMyDialog::OnButton1Clicked() {
      MessageBox(L"Button clicked!");
    }
    
    // 处理自定义消息
    LRESULT CMyDialog::OnMyCustomMessage(WPARAM wParam, LPARAM lParam) {
      // 自定义逻辑
      return 0;
    }
    

5. 关键技术细节

(1) 消息路由优先级
  • MFC 消息路由顺序:
    1. 当前活动窗口(如对话框)。
    2. 应用程序主框架窗口(CFrameWnd)。
    3. 应用程序类(CWinApp)。
(2) 命令消息的特殊性
  • WM_COMMAND 消息支持通过 ON_UPDATE_COMMAND_UI 动态更新 UI(如禁用按钮):
    void CMyView::OnUpdateFileSave(CCmdUI* pCmdUI) {
      pCmdUI->Enable(m_bIsModified); // 根据条件启用/禁用菜单项
    }
    
(3) 消息预处理
  • 使用 PreTranslateMessage 拦截消息(如全局快捷键):
    BOOL CMyApp::PreTranslateMessage(MSG* pMsg) {
      if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F1) {
        ShowHelp();  // 自定义处理
        return TRUE; // 阻止消息继续传递
      }
      return CWinApp::PreTranslateMessage(pMsg);
    }
    

6. 常见问题与调试

  • 消息未响应
    • 检查消息映射宏是否正确定义(如拼写错误)。
    • 确保类的基类在 BEGIN_MESSAGE_MAP 中正确指定。
  • 自定义消息未触发
    • 使用 RegisterWindowMessage 注册唯一消息标识符(避免冲突)。
  • 死锁或卡顿
    • 避免在消息处理函数中执行耗时操作(应使用多线程)。

7. MFC 消息机制 vs 通用事件驱动

特性MFC 消息机制通用事件驱动(如 C#)
绑定方式静态消息映射宏事件委托(delegate/event
灵活性需要手动管理消息映射自动代码生成(IDE 支持)
适用场景传统 Windows 桌面应用现代框架(WPF、WinForms)
调试复杂度高(需手动跟踪消息流)低(可视化调试工具)

通过 MFC 的消息映射机制,开发者可以高效处理 Windows 消息,但其设计较为底层,需熟悉宏和消息路由规则。现代框架(如 Qt 或 WPF)提供了更高级的抽象,但 MFC 仍是维护旧代码或开发轻量级 Windows 应用的重要工具。

自己使用记录:
实现的功能是:
两个窗口之间传递消息。

定义窗口:g_HwndCamWindow,给谁说话
定义一个消息:WM_CAM_TO_MAIN ,咱俩要有一次说话这件事
消息内容是啥:(消息函数:这里是AutoRuns),这件事就是具体说啥
调用消息:PostMessage,啥时说

StructCommon.h
#define WM_CAM_TO_MAIN (WM_USER+112)

在Global.h中

extern HWND g_HwndCamWindow;

在主框架类中:
newApplication.cpp
因为每个都要包含这个,

给他初始化

HWND g_HwndCamWindow=NULL;

在使用的主类中DlgMain.h
afx_msg LRESULT AutoRuns(WPARAM wp, LPARAM lp);

在使用的主类中DlgMain.cpp

消息映射函数中定义函数
BEGIN_MESSAGE_MAP(CDlgMain, CDialogEx)
ON_MESSAGE(WM_CAM_TO_MAIN, &CDlgMain::AutoRuns)
END_MESSAGE_MAP()
初始化中给初始化

g_HwndCamWindow = this->GetSafeHwnd();

并写一个消息函数
LRESULT CDlgMain::AutoRuns(WPARAM wp, LPARAM lp)
{
m_Section1.Lock();
AutoRun(1);
m_Section1.Unlock();
return 0;
}

DlgCamera.cpp
在使用的地方调用
::PostMessage(g_HwndCamWindow,WM_CAM_TO_MAIN,0,0);

通过这个WM_CAM_TO_MAIN消息可以在DlgCamera.cpp中给DlgMain.cpp中发送消息传话。

个人理解,记录备用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值