# SendMessage

发送消息到窗口或控件并等待回复.

    Result := SendMessage(Msg , wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText, Timeout)

## 参数

Msg

  类型: 整数

  要发送的消息的编号. 请参阅消息列表来确定编号.

wParam, lParam

  类型: 整数或对象

  消息的参数. 如果省略, 每个参数默认为 0.

  每个参数必须是一个整数或一个具有 Ptr 属性的对象, 比如 Buffer. 对于需要指向字符串指针的消息, 使用 Buffer 或 StrPtr 函数. 如果通过将变量的地址传递给 SendMessage 来改变变量所包含的字符串, 那么之后必须通过调用 VarSetStrCapacity(&MyVar, -1) 来更新变量的长度.

  如果 AutoHotkey 或目标窗口是 32 位的, 则只使用参数的低 32 位; 也就是说, 如果超出了有符号值的范围 -2147483648 到 2147483647(-0x80000000 to 0x7FFFFFFF), 或者超出了无符号值的范围 0 到 4294967295(0xFFFFFFFF), 则值会被截断. 如果 AutoHotkey 和目标窗口都是 64 位的, 可以使用 AutoHotkey 所支持的任何整数值.

Control

  类型: 字符串, 整数或对象

  如果省略此参数, 则消息会被直接发送到目标窗口而不是它的某个控件. 否则, 这个参数可以是控件的 ClassNN, 文本或 HWND, 或者是一个具有 `Hwnd` 属性的对象. 有关详情, 请参阅控件参数.

  如果这个参数指定了一个 HWND(作为一个整数或对象), 那么它不需要是一个控件(子窗口) 的 HWND. 也就是说, 它也可以是一个顶层窗口的 HWND.

WinTitle

  类型: 字符串, 整数或对象

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

WinText

  类型: 字符串

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

ExcludeTitle

  类型: 字符串

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

ExcludeText

  类型: 字符串

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

Timeout

  类型: 整数

  等待目标窗口处理消息的最大毫秒数. 如果省略, 默认为 5000(ms). 如果消息在这段时间内没有被处理, 则会抛出 TimeoutError.

## 返回值

类型: 整数

该函数返回消息的结果, 有时可能是一个 "回复", 这取决于消息的性质及其目标窗口.

可能的值范围取决于目标窗口和正在运行的 AutoHotkey 版本. 当使用 32 位版本的 AutoHotkey, 或者如果目标窗口是 32 位的, 结果是一个 32 位的无符号整数, 介于 0 和 4294967295 之间. 当使用 64 位版本的 AutoHotkey 和 64 位窗口时, 结果是介于 -9223372036854775808 和 9223372036854775807 之间的 64 位有符号整数.

如果期望结果是一个 32 位有符号的整数(从 -2147483648 到 2147483648 的值), 它可以被截断为 32 位, 并转换成一个有符号的值, 如下所示:

    MsgReply := MsgReply << 32 >> 32

即使在 64 位的 AutoHotkey 上, 这种转换也是必要的, 因为来自 32 位窗口的结果是零扩展的. 例如, 来自 32 位窗口的 -1 结果在任何版本的 AutoHotkey 上都被视为 0xFFFFFFFF, 而来自 64 位窗口的 -1 在 32 位 AutoHotkey 被视为 0xFFFFFFFF, 在 64 位 AutoHotkey 被视为 -1.

## 错误处理

如果找不到窗口或控件, 则抛出 TargetError.

如果消息超时, 则抛出 TimeoutError.

如果消息不能被发送, 则抛出 OSError. 例如, 如果目标窗口运行在比脚本更高的完整性级别上(例如, 它以管理员身份运行, 而脚本不是), 消息可能被阻止.

## 备注

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

SendMessage 等待目标窗口处理消息, 直到超时期结束. 与此相反, PostMessage 将消息放入与目标窗口相关联的消息队列中, 而无需等待确认或回复.

字符串参数必须按地址传递. 例如:

    Run "Notepad"
    WinWait "Untitled - Notepad"
    SendMessage 0x000C, 0, StrPtr("New Notepad Title")  ; 0X000C is WM_SETTEXT

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

    SendMessage 0x001A,,,, 0xFFFF  ; 0x001A is WM_SETTINGCHANGE

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

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

窗口标题和文本是区分大小写的. 除非 DetectHiddenWindows 被打开, 否则不会检测隐藏窗口.

## 相关

PostMessage, 消息列表, 消息指导, OnMessage, Automating Winamp, DllCall, ControlSend, MenuSelect

## 示例

通过热键关闭显示器. 在 SendMessage 行中, 将数字 2 替换为 -1 以打开显示器, 或将其替换为 1 以激活显示器的低功耗模式.

    #o::  ; Win+O 热键
    {
        Sleep 1000  ; 让用户有机会释放按键(以防释放它们时再次唤醒显视器).
        ; 关闭显示器:
        SendMessage 0x0112, 0xF170, 2,, "Program Manager"  ; 0x0112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER.
    }

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

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

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

    SendMessage 0x0115, 0, 0, ControlGetFocus("A")

向下滚动一行(具有竖直滚动栏的控件).

    SendMessage 0x0115, 1, 0, ControlGetFocus("A")

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

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

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

    SetTitleMatchMode 2
    DetectHiddenWindows true
    pid := SendMessage(0x0044, 0x405, 0, , "SomeOtherScript.ahk - AutoHotkey v")
    MsgBox pid " is the process id."

dftg