PostMessage / SendMessage

发送消息到窗口或控件(SendMessage 还会等待回复).

PostMessage, MsgNumber , wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText
SendMessage, MsgNumber , wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText, Timeout

参数

MsgNumber

要发送的消息号, 可以为表达式. 请参阅消息列表来确定编号.

wParam

如果为空或省略, 将发送 0. 否则, 请指定消息的第一个组件, 可以为表达式. 如果为空或省略, 则会被设置为 0.

lParam

如果为空或省略, 将发送 0. 否则, 请指定消息的第二个组件, 可以为表达式. 如果为空或省略, 则会被设置为 0.

Control

如果此参数为空或省略, 则消息会被直接发送到目标窗口而不是它的某个控件. 或者指定 ClassNN(控件的类名和实例编号) 或控件的文本, 它们都可以通过 Window Spy 获取. 使用文本时, 匹配行为由 SetTitleMatchMode 决定.

要对控件的 HWND(窗口句柄) 进行操作, 请将 Control 参数留空同时在 WinTitle 参数中指定 ahk_id %ControlHwnd%(即使在 DetectHiddenWindows 设置关闭时, 这样也可以操作隐藏控件). 获取控件的 HWND 的一般方法是使用 ControlGet Hwnd, MouseGetPosDllCall().

WinTitle, WinText, ExcludeTitle, ExcludeText

如果这些都是空白或省略, 将使用上次找到的窗口. 否则, 为 WinTitle 指定窗口标题或其他条件, 来标识目标窗口, 和/或为 WinText 指定目标窗口的单个文本元素的子字符串(由包含的 Window Spy 实用程序显示).

ExcludeTitleExcludeText 可用于根据标题或文本排除一个或多个窗口. 它们的规范类似于 WinTitleWinText, 除了 ExcludeTitle 不识别除窗口标题之外的任何条件.

窗口标题和文本是区分大小写的. 默认情况下, 不检测隐藏窗口, 而检测隐藏文本元素, 除非使用 DetectHiddenWindowsDetectHiddenText 进行更改. 默认情况下, 窗口标题必须以指定的 WinTitleExcludeTitle 开头才能匹配, 除非使用 SetTitleMatchMode 进行更改.

Timeout [AHK_L 42+]

如果为空或省略, 默认为 5000, 这同时也是不支持此参数的 AutoHotkey 旧版本的默认行为. 否则, 请指定等待目标窗口处理消息的最大毫秒数. 如果在这时间内消息没有被处理, 则命令结束并设置 ErrorLevel 为单词 FAIL. 此参数可以为表达式.

ErrorLevel

[v1.1.04+]: 这两个命令失败时会抛出异常. 想了解更多信息, 请参阅运行时错误.

PostMessage: 如果遇到问题(例如目标窗口或控件不存在) 则 ErrorLevel 被置为 1. 否则被置为 0.

SendMessage: 如果遇到问题或命令超时, 则 ErrorLevel 被设置为单词 FAIL. 否则, 它被设置为此消息的返回值数字, 它可能取决于消息的性质和目标窗口的 "回复".

返回值的取值范围取决于目标窗口和运行的 AutoHotkey 版本. 当使用 32 位的 AutoHotkey, 或者目标窗口是 32 位, 那么返回值是 0 到 4294967295 之间的一个 32 位无符号整数. 当使用 64 位 AutoHotkey 和 64 位的目标窗体, 返回值将是 -9223372036854775808 到 9223372036854775807 之间的一个 64 位有符号整数.

如果返回值预期为一个 32 位有符号整数(-2147483648 到 2147483648 中的某个值), 那么可以将返回值截断为 32 位, 然后像下面这样转换为有符号整数:

MsgReply := ErrorLevel << 32 >> 32

即使在使用 AutoHotkey 64 位时, 这样的转换也可能是必须的, 因为从 32 位窗体返回的值都是零扩展的. 例如, 在任何版本的 AutoHotkey 中, 从一个 32 位窗体返回的 -1 都视为 0xFFFFFFFF , 但在 32 位 AutoHotkey 中接收到从 64 位窗体返回的 -1 视为 0xFFFFFFFF, 而在 64 位 AutoHotkey 中被视为 -1.

备注

应该小心使用这些命令, 因为发送消息到错误的窗口(或发送错误的消息) 可能导致意外的行为或者甚至让目标应用程序崩溃. 这是因为大多数应用程序并不是设计用于从外部来源中接受某些类型的消息.

PostMessage 把消息放置到和目标窗口关联的消息队列中, 并且不会等待确认或回应. 与之相比, SendMessage 在到达超时时间前会等待目标窗口处理消息.

wParamlParam 必须为整数. 如果 AutoHotkey 或目标窗体为 32 位, 那么只有低 32 位被使用; 也就是说, 值将是 -2147483648 到 4294967295(0xFFFFFFFF) 之间. 如果 AutoHotkey 和目标窗体都是 64 位, 那么 AutoHotkey 支持的任何整数值都可以使用. 与 AutoHotkey 支持的所有整数值一样, 前缀 0x 表示一个十六进制值. 例如, 0xFF 等同于 255.

字符串可以通过 wParamlParam 来传递变量地址(实现传递字符串的效果). 下面的例子演示了通过地址操作符(&) 实现这一效果:

SendMessage, 0x000C, 0, &MyVar, ClassNN, WinTitle  ; 0X000C 为 WM_SETTEXT

[v1.0.43.06+]: 由消息的接收者放入 MyVar 的字符串可以正确识别而不需要额外的步骤. 不过, 只有在参数的首个字符为和符号(&) 时才可以; 例如, &MyVar&MyVar+5 可以正常工作, 单 5+&MyVar 不能.

引号包围的(原义) 字符串也可以发送, 例如下面这个可运行示例(此时不应该使用 & 运算符):

#Persistent
ListVars
WinWaitActive, ahk_class AutoHotkey
SendMessage, 0x000C, 0, "New Title"  ; 0x000C is WM_SETTEXT

要发送消息到系统中的所有窗口, 包括隐藏或禁用的那些, 请在 WinTitle 中指定 ahk_id 0xFFFF(0xFFFF 为 HWND_BROADCAST). 这种技术应该只用于目标为广播的消息, 例如:

SendMessage, 0x001A,,,, ahk_id 0xFFFF  ; 0x001A 为 WM_SETTINGCHANGE

要让脚本接收消息, 请使用 OnMessage().

请参阅消息指南来查看使用这些命令的介绍.

消息列表, 消息指南, OnMessage(), 自动化 Winamp, DllCall(), ControlSend, WinMenuSelectItem

示例

按下热键关闭显示器.

#o:: ; Win+O
Sleep 1000  ; 让用户有机会释放按键(以防释放它们时再次唤醒显视器).
; 关闭显示器:
SendMessage, 0x0112, 0xF170, 2,, Program Manager  ; 0x0112 是 WM_SYSCOMMAND, 0xF170 是 SC_MONITORPOWER.
; 对上面命令的注释: 使用 -1 代替 2 来打开显示器.
; 使用 1 代替 2 来激活显示器的节能模式.
return

启动用户选择的屏幕保护程序.

SendMessage, 0x0112, 0xF140, 0,, Program Manager  ; 0x0112 是 WM_SYSCOMMAND, 而 0xF140 是 SC_SCREENSAVE.

向上滚动一行(用于含垂直滚动条的控件).

ControlGetFocus, control, A
SendMessage, 0x0115, 0, 0, %control%, A

向下滚动一行(用于含垂直滚动条的控件).

ControlGetFocus, control, A
SendMessage, 0x0115, 1, 0, %control%, A

切换活动窗口的键盘布局/语言为英语(US).

PostMessage, 0x0050, 0, 0x4090409,, A  ; 0x0050 是 WM_INPUTLANGCHANGEREQUEST.

请求 Winamp 的当前活动的轨道编号(有关详情, 请参阅 Automating Winamp).

SetTitleMatchMode, 2
SendMessage, 0x0400, 0, 120,, - Winamp
if (ErrorLevel != "FAIL")
{
    ErrorLevel++  ; Winamp 的计数从 "0" 开始, 所以加 1 进行调整.
    MsgBox, Track #%ErrorLevel% is active or playing.
}

找出 AHK 脚本的进程 ID(另一种方法是 WinGet PID).

SetTitleMatchMode, 2
DetectHiddenWindows, On
SendMessage, 0x0044, 0x0405, 0, , SomeOtherScript.ahk - AutoHotkey v
MsgBox %ErrorLevel% is the process id.