OnMessage 是 AHK 里连接“脚本”和“Windows 消息”的入口。它不负责直接点按钮、发按键,而是在某个窗口收到指定消息时,调用你写好的函数。新手可以先把它理解成:窗口发生了某类事件,脚本就被通知一次。

它适合做窗口内部事件监听、GUI 交互增强、接收部分系统通知,以及把一些原本只能轮询检查的事情改成事件触发。但它不是全局钩子,也不是所有软件都能拦截;用它之前,要先分清“监听自己的 GUI”和“监听别人的窗口”是两件事。

完整的消息对照表 WM_Messages值解释详见:https://www.ahk66.com/638

 

最小示例:鼠标在 GUI 内移动

#Requires AutoHotkey v1.1
#NoEnv
#SingleInstance Force

Gui, Add, Text, w320 h80 vInfo, 把鼠标移到这个窗口里
Gui, Show,, OnMessage 示例

OnMessage(0x200, "WM_MOUSEMOVE")
return

WM_MOUSEMOVE(wParam, lParam, msg, hwnd) {
    GuiControl,, Info, 鼠标正在窗口内移动
}

GuiClose:
ExitApp

这里的 0x200 是鼠标移动消息。窗口收到这类消息时,AHK 就会调用 WM_MOUSEMOVE 函数。函数名可以自己取,但 OnMessage 里的名字要和函数定义一致。

回调函数的 4 个参数

OnMessage 回调常见参数是 wParam、lParam、msg、hwnd。初学者不需要一开始就背 Windows API,只要知道:msg 是消息编号,hwnd 是收到消息的窗口句柄,wParam 和 lParam 是这条消息附带的数据。

WM_MOUSEMOVE(wParam, lParam, msg, hwnd) {
    x := lParam & 0xFFFF
    y := lParam >> 16
    ToolTip, 鼠标位置:%x%, %y%
}

不同消息里,wParam 和 lParam 的含义不同。写 OnMessage 代码时,真正重要的不是“参数名字”,而是查清楚你监听的那条消息把数据放在哪里。

常见用途

OnMessage 最适合下面几类场景:

  • 监听自己写的 AHK GUI,例如鼠标进入、按下、窗口大小变化。
  • 处理窗口关闭、移动、激活等事件,让界面行为更自然。
  • 接收某些系统或控件发来的通知,减少死循环轮询。
  • 在多个脚本配合时,作为一种轻量的事件入口。

但如果你的目标是控制网页、Excel、普通软件按钮,通常应该先考虑 COM、控件命令、UIA、Acc、浏览器接口等更直接的方法。OnMessage 更像底层事件监听,不是自动化的第一选择。

高频消息要节流

鼠标移动、窗口尺寸变化这类消息触发非常频繁。如果回调里写了耗时操作,脚本就容易卡顿。比较稳的做法是先做时间间隔判断,把真正的处理频率降下来。

WM_MOUSEMOVE(wParam, lParam, msg, hwnd) {
    static lastTick := 0

    if (A_TickCount - lastTick < 100)
        return

    lastTick := A_TickCount
    ToolTip, 已处理一次鼠标移动消息
}

这段代码的意思是:100 毫秒内只处理一次。对于日志、界面刷新、文件写入等操作,这个习惯尤其重要。

临时关闭监听

OnMessage 不是写上就必须一直开着。某些窗口关闭后、调试结束后,或者你只想在特定阶段监听时,可以把对应消息取消掉。

OnMessage(0x200, "WM_MOUSEMOVE")  ; 开启监听

; 不再需要时关闭
OnMessage(0x200, "")

如果一个脚本里有多个 GUI,要注意 hwnd 参数。不要只看消息编号,还要判断这条消息来自哪个窗口,否则容易把 A 窗口的动作误处理到 B 窗口上。

新手最容易踩的坑

  • 把 OnMessage 当成全局监听:它通常监听的是脚本相关窗口收到的消息,不等于全系统按键鼠标钩子。
  • 回调函数里写太重的任务:高频消息会把脚本拖慢。
  • 没有判断 hwnd:多个窗口共用一个回调时很容易误判来源。
  • 照抄消息编号却不查参数含义:同样是 wParam、lParam,在不同消息里意思可能完全不同。
  • 忘记关闭监听:临时调试代码留下来,后面排查问题会很绕。

结语

OnMessage 的价值在于“事件驱动”。能用窗口消息解决的问题,就不必一直 SetTimer 或 Loop 去查。初学时建议先从自己的 GUI 开始练:监听鼠标移动、点击、窗口关闭,再逐步理解 msg、hwnd、wParam、lParam 的关系。这样学起来更稳,也更容易判断它什么时候该用、什么时候不该用。

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。