# 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.

Control

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

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

WinTitle

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

WinText

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

ExcludeTitle

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

ExcludeText

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

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 在到达超时时间前会等待目标窗口处理消息.

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

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

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

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

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

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

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

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

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

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

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

## 相关

消息列表, 消息指南, 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

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

    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.

dftg