# Clipboard 和 ClipboardAll

Clipboard 是内置变量, 它包含当前 Windows 剪贴板中可以用文本形式表示的内容. 与之相比, ClipboardAll 包含了剪贴板中的所有内容, 例如图片和其他特定格式的东西.

Clipboard 中的每行文本通常都是以回车和换行符(CR+LF) 结尾, 它们在脚本中表示为 ``r`n`. 文件(例如从资源管理器窗口中使用 `Ctrl`+`C` 复制的文件) 被视为文本: 每当在脚本中引用 Clipboard 时, 它们会被自动转换为它们的文件名(完整路径). 要逐个提取这些文件, 请参照此例:

    Loop, parse, clipboard, `n, `r
    {
        MsgBox, 4, , File number %A_Index% is %A_LoopField%.`n`nContinue?
        IfMsgBox, No, break
    }

要按字母顺序排列文件名, 请使用 Sort 命令. 要把剪贴板中的文件名写入到文件中, 请使用 `FileAppend, %clipboard%`r`n, C:\My File.txt`. 要改变脚本尝试打开剪贴板的持续时间, 例如另一个程序在使用剪贴板的时候, 请使用 #ClipboardTimeout.

基本示例:

    clipboard := "my text"   ; 在剪贴板中存入新内容.
    clipboard := ""   ; 清空剪贴板.
    clipboard := clipboard    ; 把任何复制的文件, HTML 或其他格式的文本转换为纯文本.
    clipboard := clipboard " Text to append."   ; 追加一些文本到剪贴板.
    StringReplace, clipboard, clipboard, ABC, DEF, All   ; 把剪贴板中所有 ABC 替换为 DEF (同时把剪贴板的内容转换为纯文本).

使用 ClipWait 提高脚本的可靠性:

    clipboard := ""  ; 让剪贴板初始为空, 这样可以使用 ClipWait 检测文本什么时候被复制到剪贴板中.
    Send ^c
    ClipWait  ; 等待剪贴板中出现文本.
    MsgBox Control-C copied the following contents to the clipboard:`n`n%clipboard%

## ClipboardAll(保存并恢复剪贴板中的所有内容)

ClipboardAll 包含了剪贴板中的所有内容(例如图片和格式). 它常用来保存剪贴板的内容, 以便脚本可以在某个操作中临时使用剪贴板. 当这个操作结束后, 脚本可以恢复剪贴板为原来的内容, 如下所示:

    ClipSaved := ClipboardAll   ; 把剪贴板的所有内容保存到您选择的变量中.
    ; ... 这里临时使用剪贴板, 例如使用 Transform Unicode 粘贴 Unicode 文本 ...
    Clipboard := ClipSaved   ; 恢复剪贴板为原来的内容. 注意这里使用 Clipboard(不是 ClipboardAll).
    ClipSaved := ""   ; 在原来的剪贴板含大量内容时释放内存.

ClipboardAll 中的内容可以保存到文件中(在这种模式中, FileAppend 总是覆盖任何现有的文件):

    FileAppend, %ClipboardAll%, C:\Company Logo.clip ; 文件扩展名无关紧要.

要在之后加载这个文件的内容回剪贴板(或变量中), 请参照此例:

    FileRead, Clipboard, *c C:\Company Logo.clip ; 注意 *c 必须在文件名的前面.

### 限制

一些直接使用 ClipboardAll 的限制:

- 除上面描述的方式外的其他方式使用 ClipboardAll 时, 都会得到空值.
- ClipboardAll 不支持在逗号分隔的表达式中; 即它必须在单独的一行进行赋值, 如 `ClipSaved := ClipboardAll`.

包含二进制剪贴板数据的变量可以按如下方式使用:

- 通过赋值给 Clipboard 将数据放回剪贴板, 如上所示.
- 用 FileAppend 将剪贴板数据写入文件, 如上所示.
- 将其复制到另一个变量(或 ByRef 参数) 如此例所示: `ClipSaved2 := ClipSaved`.
- 通过引用或通过值([v1.0.46+]), 将其传递给用户定义的函数.
- 通过将其传递给 StrLen() 来确定数据的大小, 如下所示.
- 通过使用传统 IF 比较这两个变量, 如下所示.
- 使用其地址或将变量本身传递给 NumGet 来检查数据.

其他限制:

- 当将二进制剪贴板数据赋值给一个变量时, 该变量将被标记一个隐藏属性. 这个属性只能通过 FileRead 的 `*c` 选项来设置, 或者通过直接从 ClipboardAll(如上所示) 或其他具有该属性的变量赋值来设置.
- 当以与上述不同的方式使用时, 二进制剪贴板数据通常被解释为文本, 并在第一个空字符处(通常是在数据的开头) 截断. 例如, 当试图从函数返回数据或将其赋值给属性或数组元素时, 就会发生这种情况.
- 当变量被释放或赋值任何其他值时, 剪贴板属性将被删除, 即使是通过间接方法(如 StrReplace() 或 StringReplace).
- 不带剪贴板属性的变量在复制到 Clipboard 或传递给 FileAppend 时将被视为文本, 即使数据采用适当的二进制格式也是如此.

### 注意

如果 ClipboardAll 不能获取剪贴板中一个或多个数据对象(格式), 则会忽略它们但仍保存剩余的所有对象.

ClipWait 可以用来检测剪贴板何时包含数据(可以包含非文本数据).

可以使用 StrLen() / StringLen 来发现复制到 ClipboardAll 的变量的总大小. 但是, 要在 AutoHotkey 的 Unicode 版本中获取字节的大小, 则前面得到的长度必须乘以 2. A_IsUnicode 可用来支持 ANSI 和 Unicode 版本, 如此例所示: `size := StrLen(ClipSaved) * (A_IsUnicode ? 2 : 1)`.

接受 ClipboardAll 赋值的变量可以通过 If[Not]Equal, `If Var1 = %Var2%`, 或 `If Var1 != %Var2%` 互相进行比较(但不能直接和 ClipboardAll 进行比较). 在下面的例子中, 首先检查每个变量的大小. 如果大小不足以判断, 则比较它们的内容来得到结果:

    if ClipSaved1 != %ClipSaved2%   ; 这里 必须 使用传统语法的 IF 语句, 不能使用表达式.
        MsgBox The two saved clipboards are different.

保存 ClipboardAll 到变量时, 这个变量的大小不受 #MaxMem 设置的内存限制.

保存的剪贴板文件在内部由 4 字节格式类型, 然后是 4 字节(32-位) 或 8 字节(64-位) 的数据块大小, 然后是该格式的数据块组成. 如果剪贴板包含多种格式(几乎总是这种情况), 则重复这三项, 直到包含所有格式. 该文件以 4 字节格式类型 0 结束.

已知限制: 当剪贴板中含有 Microsoft Excel 单元格数据时获取 ClipboardAll 可能会导致 Excel 弹出 "找不到打印机" 的对话框.

使用 AutoHotkey 编写的剪贴板实用工具:

- Deluxe Clipboard: 提供不限数量的私有的命名的剪贴板, 可以用来复制, 剪切, 追加或剪切追加选中的文本. www.autohotkey.com/forum/topic2665.html
- ClipStep: 仅使用键盘上 `Ctrl`-`X`-`C`-`V` 控制多个剪贴板. www.autohotkey.com/forum/topic4836.html

## OnClipboardChange

脚本可以使用 OnClipboardChange() 或 OnClipboardChange 标签监视系统剪贴板的改变.

dftg