PostMessage / SendMessage

AutoHotkey

PostMessage / SendMessage

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

PostMessage, Msg [, wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]
SendMessage, Msg [, wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText, Timeout]

参数

Msg

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

wParam

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

lParam

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

控件

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

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

WinTitle

窗口标题或识别目标窗口的其他条件。请参阅 WinTitle

WinText

如果使用此参数, 那么它必须是目标窗口中单个文本元素的子字符串 (和内置的 Window Spy 工具显示的一样). 当 DetectHiddenText 的设置为 ON 时, 那么会检测到隐藏文本元素.

ExcludeTitle

标题中含有此参数值的窗口将被排除.

ExcludeText

文本中含有此参数值的窗口将被排除.

超时

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

ErrorLevel

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

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

SendMessage:如果遇到问题或命令超时,则 ErrorLevel 被设置为单词 FAIL。否则, 它被设置为此消息的数值结果, 这有时可能是由消息的性质和目标窗口决定的 "回复". 这个结果是介于 0 和 4294967295 之间的整数. 如果结果应该为有符号整数,请参照这个例子转换为负数:

MsgReply := ErrorLevel > 0x7FFFFFFF ? -(~ErrorLevel) - 1 : ErrorLevel

备注

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

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

参数 Msg, wParamlParam 都应该是介于 -2147483648 和 4294967295 (0xFFFFFFFF) 之间的整数. 和 AutoHotkey 中的所有整数值相同, 可以加上 0x 前缀表示十六进制值. 例如, 0xFF 等同于 255.

通过 wParamlParam 指定变量的地址可以发送字符串. 下面的例子使用 地址运算符 (&) 来实现这个目的:

SendMessage, 0xC, 0, &MyVar, ClassNN, WinTitle  ; 0XC 为 WM_SETTEXT

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

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

Run Notepad
WinWait Untitled - Notepad
SendMessage, 0xC, 0, "New Notepad Title"  ; 0XC 为 WM_SETTEXT

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

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

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

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

窗口标题和文本是区分大小写的. 只有在打开 DetectHiddenWindows 设置时,才能检测到隐藏窗口。

相关

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

示例

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

; 启动用户选择的屏幕保护程序:
SendMessage, 0x112, 0xF140, 0,, Program Manager  ; 0x112 为 WM_SYSCOMMAND, 而 0xF140 为 SC_SCREENSAVE.

; 向上滚动一行 (用于含垂直滚动条的控件):
ControlGetFocus, control, A
SendMessage, 0x115, 0, 0, %control%, A

; 向下滚动一行:
ControlGetFocus, control, A
SendMessage, 0x115, 1, 0, %control%, A

; 切换活动窗口的键盘布局/语言为英语:
PostMessage, 0x50, 0, 0x4090409,, A  ; 0x50 为 WM_INPUTLANGCHANGEREQUEST.

; 这个例子请求 Winamp 的当前活动的轨道编号:
SetTitleMatchMode, 2
SendMessage, 1024, 0, 120, - Winamp
if ErrorLevel <> FAIL
{
    ErrorLevel++  ; Winamp 的计数从 "0" 开始, 所以加 1 进行调整.
    MsgBox, Track #%ErrorLevel% is active or playing.
}
; 请参阅 自动化 Winamp 了解详情.

; 找出 AHK 脚本的进程 ID (另一种方法是 "WinGet PID"):
SetTitleMatchMode, 2
DetectHiddenWindows, on
SendMessage, 0x44, 0x405, 0, , SomeOtherScript.ahk - AutoHotkey v
MsgBox %ErrorLevel% is the process id.