# WinTitle 参数 & 最近找到的窗口

许多内置函数都有 WinTitle 参数, 用于识别要操作的窗口. 此参数可以是窗口的标题或部分标题, 和/或本页上描述的任何其他条件.

快速参考:

标题 | 匹配行为
整数 | HWND
对象 | 具有 HWND 的对象
A | 活动窗口
ahk_class | 窗口类
ahk_id | 唯一 ID/HWND
ahk_pid | 进程 ID
ahk_exe | 进程名称/路径
ahk_group | 窗口组
| 多重条件
(空) | 上次找到的窗口

## 匹配行为

SetTitleMatchMode 控制如何将部分或完整标题与每个窗口的标题进行比较. 根据这个设置, WinTitle 可以是完全匹配的标题, 也可以包含前面部分, 标题中任何位置出现的子字符串或 RegEx 模式. 该设置还控制 ahk_class 和 ahk_exe 是否解释为 RegEx 模式.

窗口标题是区分大小写的, 除非在 RegEx 模式中使用 i) 修饰符.

仅当 DetectHiddenWindows 被的打开时, 才会检测隐藏窗口, 但 WinShow 除外, 它总是检测隐藏窗口.

如果多个窗口与 WinTitle 和其他任何条件匹配, 则使用最顶层的匹配窗口. 如果活动窗口匹配条件, 则它通常优先, 因为它一般在其他所有窗口的上面. 然而, 如果某个置顶的窗口也匹配条件(且活动窗口没有置顶), 则使用这个置顶窗口.

## A(活动窗口)

使用字母 `A` 表示 WinTitle, 并省略其他三个窗口参数(WinText, ExcludeTitle 和 ExcludeText), 对活动窗口进行操作.

以下示例检索并报告活动窗口的唯一 ID(HWND):

    MsgBox WinExist("A")

下面的例子创建了一个热键, 按下它可以使活动窗口最大化:

    #Up::WinMaximize "A"  ; Win+Up

## ahk_ 条件

指定一个或多个下面的 ahk_ 条件(可选, 除了窗口标题). 一个 ahk_ 条件总是由一个 _ahk 关键字和它的条件值组成, 两者之间用零或多个空格或制表符分隔. 例如, `ahk_class Notepad` 代表一个记事本窗口.

ahk_ 关键字和它的条件值不需要用空格或制表符来分隔. 这主要是在指定 ahk_ 条件值为表达式并与变量结合时有用. 例如, 可以指定 `"ahk_pid" PID` 而不是 `"ahk_pid " PID`. 然而, 在所有其他情况下, 建议使用至少一个空格或制表符作为分隔, 以提高可读性.

### ahk_class(窗口类)

在 WinTitle 中使用 `ahk_class ClassName` 通过其窗口类来识别窗口.

窗口类是系统用来创建窗口的模板的属性集. 换句话说, 窗口类表示窗口的 类型. 窗口类可以通过 Window Spy 来显示或通过 WinGetClass 获取. 如果 RegEx 标题匹配模式被激活, ClassName 接受正则表达式.

下面的例子激活了一个控制台窗口(例如 cmd.exe):

    WinActivate "ahk_class ConsoleWindowClass"

下面的示例与上面的相同, 但使用了正则表达式(注意必须事先打开 RegEx 标题匹配模式才行):

    WinActivate "ahk_class i)^ConsoleWindowClass$"

### ahk_id(唯一 ID / HWND)

在 WinTitle 中使用 `ahk_id HWND`, 通过其唯一的 ID 来识别窗口或控件.

每个窗口或控件都有一个唯一 ID, 也称为 HWND(即窗口句柄的缩写). 即使在窗口或控件的标题改变时也可用这个 ID 来识别它.

DetectHiddenWindows 会影响 ahk_id 条件是否检测隐藏的顶层窗口, 但隐藏的控件总是会被检测到. 如果传递了一个有效的整数或对象, 则隐藏的窗口总是能被检测到.

ahk_id 条件也可以和给定窗口必须匹配的其他条件相结合. 例如, `WinExist("ahk_id " ahwnd " ahk_class " aclass)` 在窗口被 "检测到"(根据 DetectHiddenWindows) 且其窗口类别与 aclass 所包含的字符串相匹配时, 返回 ahwnd.

窗口的 ID 通常通过 WinExist 或 WinGetID 来检索. 控件的 ID 通常通过 ControlGetHwnd, MouseGetPos 或 DllCall 来检索. Gui 和 GuiControl 对象具有 `Hwnd` 属性, 因此可以直接在 WinTitle 中使用.

下面的示例通过存储在 VarContainingID 中的唯一 ID 对窗口进行操作:

    ; 传递一个整数.
    WinActivate Integer(VarContainingID)
    WinShow A_ScriptHwnd
    WinWaitNotActive WinExist("A")

    ; 传递一个具有 HWND 属性的 对象.
    WinWaitClose myGuiObject

    ; 使用 ahk_id 前缀.
    WinActivate "ahk_id " VarContainingID	WinActivate "ahk_id " VarContainingID

如果对象没有 HWND 属性或该属性的值不是整数, 则抛出 PropertyError 或 TypeError.

### ahk_pid(进程 ID)

在 WinTitle 中使用 `ahk_pid PID` 来识别属于特定进程的窗口. 进程标识符(PID) 通常由 WinGetPID, Run 或 Process 函数检索. 窗口的进程 ID 可以通过 Window Spy 来显示.

下面的例子是通过存储在 VarContainingPID 中的进程 ID 来激活一个窗口:

    WinActivate "ahk_pid " VarContainingPID

### ahk_exe(进程名称/路径)

在 WinTitle 中使用 `ahk_exe ProcessNameOrPath` 来识别属于任何具有给定名称或路径的进程的窗口.

ahk_pid 条件仅限于一个特定的进程, 而 ahk_exe 条件则考虑所有名称或完整路径与给定字符串相匹配的进程. 如果 RegEx 标题匹配模式处于活动状态, ProcessNameOrPath 接受正则表达式, 该表达式必须匹配进程的完整路径. 否则, 它接受不区分大小写的名称或完整路径; 例如, `ahk_exe notepad.exe` 涵盖了 `ahk_exe C:\Windows\Notepad.exe`, `ahk_exe C:\Windows\System32\Notepad.exe` 和其他变体. 窗口的进程名称可以通过 Window Spy 显示出来.

下面的例子是通过进程名称来激活一个记事本窗口:

    WinActivate "ahk_exe notepad.exe"

下面的示例与上面的相同, 但使用了正则表达式(注意必须事先打开 RegEx 标题匹配模式才行):

    WinActivate "ahk_exe i)\\notepad\.exe$"  ; 匹配完整路径的名称部分.

### ahk_group(窗口组)

在 WinTitle 中使用 `ahk_group GroupName` 来识别与先前定义的窗口组

WinMinimize, WinMaximize, WinRestore, WinHide, WinShow, WinClose 和 WinKill 将对组中的 所有 窗口进行操作. 相比之下, 其他窗口函数(如 WinActivate 和 WinExist) 仅对组中最顶层的窗口进行操作.

以下示例将激活任何符合窗口组定义标准的任何窗口:

    ; 定义组: Windows 资源管理器窗口
    GroupAdd "Explorer", "ahk_class ExploreWClass" ; 在 Vista 及更高版本中不使用
    GroupAdd "Explorer", "ahk_class CabinetWClass"

    ; 激活匹配上面标准的任意窗口
    WinActivate "ahk_group Explorer"

## 多重条件

与 ahk_group 条件(它扩大了搜索范围) 相比, 在 WinTitle 参数中指定多个条件可以缩小搜索范围. 在下面的例子中, 脚本等待标题中包含 My File.txt 且 类名为 Notepad 的窗口出现:

    WinWait "My File.txt ahk_class Notepad"
    WinActivate  ; 激活它找到的窗口.

使用这种方法时, 应该首先列出标题的文本(如果希望使用), 后面跟着一个或多个附加条件. 超过一个条件时条件之间必须准确地用一个空格或 tab 分隔(其他任何空格或 tab 会被视为前面一个条件的文字部分).

ahk_id 条件 可以和其他条件组合来测试窗口标题, 类名或其他属性:

    MouseGetPos ,, &id
    if WinExist("ahk_class Notepad ahk_id " id)
        MsgBox "The mouse is over Notepad."

## "上次找到的" 窗口

"上次找到的" 窗口是由最近的 WinExist, WinActive, WinWait[Not]Active 或 WinWait 发现的窗口. 这样可以让脚本更容易创建和维护, 因为目标窗口的 WinTitle 和 WinText 不需要在每个窗口函数中重复. 此外, 脚本会执行的更好, 因为在首次找到目标窗口后这些函数不需要再次搜索目标窗口.

"上次找到的" 窗口可以用于除 WinWait, WinActivateBottom, GroupAdd, WinGetCount 和 WinGetList 以外的所有窗口函数. 要使用它, 只需简单地省略所有的四个窗口参数(WinTitle, WinText, ExcludeTitle 和 ExcludeText).

每个线程保留自己的 "上次找到的" 窗口值, 这意味着如果当前线程被其他线程中断, 当原始线程恢复时它仍会拥有它原来的 "上次找到的" 窗口值, 而不是中断线程的值.

如果上次找到的窗口是一个隐藏的 Gui 窗口, 那么即使 DetectHiddenWindows 被关闭, 也可以使用它. 这通常与 GUI 的 +LastFound 选项一起使用.

下面的例子打开记事本, 等待直到它存在并激活:

    Run "Notepad"
    WinWait "Untitled - Notepad"
    ; WinWait "无标题 - 记事本"
    WinActivate  ; 使用由 WinWait 找到的窗口.

下面的例子是激活并最大化由上面的 WinExist 函数找到的记事本窗口:

    if WinExist("Untitled - Notepad")
    ; if WinExist("无标题 - 记事本")
    {
        WinActivate  ; 使用由 WinExist 找到的窗口.
        WinMaximize  ; 同上
        Send "Some text.{Enter}"
        return
    }

如果计算器不存在, 下面的例子将返回, 否则计算器将被激活并移动到一个新的位置:

    if not WinExist("Calculator")
        return
    else
    {
        WinActivate  ; 使用由 WinExist 找到的窗口.
        WinMove 40, 40  ; 同上.
        return
    }

dftg