Clipboard、ClipboardAll和OnClipboardChange

AutoHotkey

Clipboard, ClipboardAllOnClipboardChange

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

Clipboard 中的每行文本通常都是以回车和换行符 (CR+LF) 结尾, 它们在脚本中表示为 `r`n. 文件 (例如从资源管理器窗口中使用 Control-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 不支持在逗号分隔的表达式中使用;即它必须在单独的一行进行赋值,例如 ClipSaved := ClipboardAll

接受了 ClipboardAll 赋值的变量以二进制格式存储数据, 因为使用类似 MsgBox 这样的方法显示时会出现乱码. 并且, 修改二进制剪贴板变量 (使用类似 StringReplace 的方法) 会将它还原为普通变量, 导致它所保存的剪贴板数据的丢失. 在 v1.0.46+, 二进制剪贴板变量可以作为值传递给 函数 (以前它们只有作为 ByRef 才行).

如果 ClipboardAll 不能获取剪贴板中一个或多个数据对象 (格式), 则会忽略它们但仍保存剩余的所有对象. 获取行为会根据 #ClipboardTimeOut 设置再次进行尝试 (而不只是尝试一次).

包含剪贴板数据的变量可以赋值给另一个变量,例如:ClipSaved2 := ClipSaved

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

StrLen / StringLen 可以用来获取接受 ClipboardAll 赋值的变量的总大小。然而, 要在 AutoHotkey 的 Unicode 版本中获取字节的大小, 则前面得到的长度必须乘以 2. A_IsUnicode 可用来支持 ANSI 和 Unicode 版本,例如:size := StrLen(ClipSaved) * (A_IsUnicode ? 2 : 1)

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

if ClipSaved1 <> %ClipSaved2%   ; 这里 必须 使用旧式的 IF 语句, 不能使用表达式.
    MsgBox The two saved clipboards are different.

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

保存了剪贴板内容的文件内部由四个字节的格式类型, 接着四个字节的数据块大小以及相应的格式的数据块组成. 如果剪贴板中包含多种格式的内容 (大部分时候都是这样), 这三个组成部分会一直重复, 直到包含所有的内容. 文件以四个字节的 0 格式类型结尾.

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

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

OnClipboardChange

如果脚本中含有名称为 OnClipboardChange 的标签, 则当任何应用程序 (甚至是脚本自身) 改变了剪贴板的内容时会自动运行此标签. 当脚本启动时也会运行此标签一次.

内置变量 A_EventInfo 包含:
0 如果剪贴板当前为空;
1 如果剪贴板中仅包含能以文本形式表示的内容 (这里也包含了从资源管理器窗口 复制的文件);
2 如果剪贴板包含了非文本的内容, 例如图片.

下面的例子是个可运行脚本. 运行后, 它会在每次剪贴板内容变化时短暂地显示一个工具提示.

#Persistent
return

OnClipboardChange:
ToolTip Clipboard data type: %A_EventInfo%
Sleep 1000
ToolTip  ; 关闭提示.
return

当 OnClipboardChange 标签正在运行时如果剪贴板内容改变了, 那么会丢弃此通知事件. 如果不希望这样, 请在此标签的首行中指定 Critical. 不过, 这样也会缓冲/延迟在 OnClipboardChange 线程运行期间产生的其他 线程 (例如热键).

如果脚本自身改变了剪贴板的内容, 则脚本中的 OnClipboardChange 标签通常不会立即执行; 即在它之前很可能还会执行改变剪贴板内容的命令之后的命令. 要强制立即执行这个标签,请在改变剪贴板后使用短暂的延迟,例如 Sleep 20

相关主题: OnExit, OnMessage(), RegisterCallback()