语之屋

AHK 自动复制的实现与逻辑分析

技术AHK

阅读时间: 5 min

温馨提示:

本文使用 Ahk v2 进行代码编写,如有需求,自行修改为 v1 代码。

文章涉及思路分析与错误代码展示,需要成品可以下拉到最后查看。

昨天学习了 KeyWait,第一反应是可以做一个自动复制的脚本。

说干就干,仔细分析一下功能需求:

  1. 鼠标左键按下,选中文本,实现复制;

  2. 鼠标点击需要插入文本的地方Ctrl+V​ 粘贴文本。

初步尝试

第一版代码出来了:

1
~LButton::{
2
KeyWait "LButton"
3
Send "^c"
4
}

写的很快,错的也很快。

虽然实现了快速复制,但是我每次鼠标点击都会触发事件。

回到需求 2,很明显复制的文本会立刻被覆盖,难道用来(搭配微信输入法)做剪贴板同步吗?

鸡肋!(骂骂咧咧继续思考)

引入sleep​ 和GetKeyState

一夜无果,第二天重新思考并在群里进行了询问。

很明显,我不需要在任何时候去进行复制,而选择被复制的文本肯定需要一定时间。

初步将这个时间定为 1s

首先是决定加入sleep​,简单的加入并不能解决问题,因为会阻塞运行,导致我的鼠标勾选不显示。

由群里@逍遥大佬的第一版本建议出现了,我接触到一个新的函数GetKeyState​:

1
~LButton::{
2
StartTime := A_TickCount
3
While GetKeyState("LButton", "P")
4
{
5
If (A_TickCount - StartTime > 2000)
6
{
7
Send "^c"
8
Return
9
}
10
Sleep 10
11
}
12
}
1
建议的很好,仍然觉得哪里不对,打开文档查一下:
2
3
> 对于键盘键和鼠标按钮,如果键位向下 (或切换开启), 该函数返回 1(true) 如果键位向上 (或切换关闭), 该函数返回 0(false).
4
5
咦,这样看来,`while`​循环发生在我按住鼠标的时候啊,那岂不是不等我完全选中就要开始复制了?
6
7
事实证明,的确如此(大哭)。
8
9
# 问题解决(两种方案)
10
11
我没解决,饭后再看发现群里已经出现了两种解法,鲁迅说过:拿来吧你,现在都是我的了。
12
13
本着拿来主义精神,我对代码分析后得到了满足需求的两个版本:
14
15
第一个版本仍然是逍遥大佬给出的:
14 collapsed lines
16
17
```ahk
18
~LButton:: {
19
StartTime := A_TickCount
20
While GetKeyState("LButton", "P")
21
{
22
Sleep 10
23
}
24
If (A_TickCount - StartTime > 1000)
25
{
26
; MsgBox "长按左键 1 秒钟了!"
27
Send "^c"
28
}
29
}

这个解法的思路是:要在松开左键时判断,那就在左键按住时阻塞他,于是有了while​ 循环的Sleep​,当释放鼠标,进行判断。

思路奇妙而省心。(今日大收获之while​ 不仅可以用来循环,还可以用来等待)

第二个版本是@白天提出:

1
~LButton:: {
2
StartTime := A_Now
3
KeyWait "LButton"
4
if DateDiff(A_Now, StartTime, "Seconds") >= 1 {
5
SendInput "^c"
6
}
7
}

这里以按下左键触发程序,然后立刻做了一个锚点StartTime​,当 KeyWait 执行结束后将时间进行对比,这其实更加的合理,只是我最初的思路是,一步到位的等待 KeyWait LButton Up,反而执行失败。

思考的点在于,我没料到,在我一直按住左键这段时间,可以额外添加一个KeyWait "LButton"​ 来进行判断。


写程序最重要的是思维,今天一个程序的两个解法让我收获匪浅,今后将继续学习下去。

最后重新放上两种解法:

1
~LButton:: {
2
StartTime := A_TickCount
3
While GetKeyState("LButton", "P")
4
{
5
Sleep 10
6
}
7
If (A_TickCount - StartTime > 1000)
8
{
9
; MsgBox "长按左键 1 秒钟了!"
10
Send "^c"
11
}
12
}
1
~LButton:: {
2
StartTime := A_Now
3
KeyWait "LButton"
4
if DateDiff(A_Now, StartTime, "Seconds") >= 1 {
5
SendInput "^c"
6
}
7
}