在Windows下,用ahk实现Ps和Ai在中文状态下也能用快捷键

Ps和Ai有一个很烦人的问题就是在中文输入法状态下没法直接用快捷键,如b笔刷,i吸管,很破坏沉浸的状态。

现在我想到解决逻辑是这样的:在ps里需要输入中文的地方有两处,一处的图层重命名,一处是文字框。图层重命名可以通过检测光标解决,文字框目前实现了只有按T以后,才会进入中文输入状态,按esc回到快捷键状态(但通过其他方式回到快捷键状态就不太行)

目前这样的方案,基本可以在大部分情况下不需要关心输入状态了,但是仍然有一点毛病,就是如果要编辑一个已有的文字框的话,就需要多按一次t再删掉,有点蠢。

另外还没有把Ps和Ai的脚本和在一起。

用ahk实现如下,大家有没有什么更好的方案或者建议呢?

#NoTrayIcon
#NoEnv
#SingleInstance Force

#if (WinActive("ahk_class Photoshop")) and (not A_CaretX)  

~t::
if (!is_typing) {
    is_typing := true
    sendinput, {text}t
    sendinput, {Backspace}
    tooltip("可以打字了,退出按Esc")
}
return

~Esc::
if (is_typing) {
    is_typing := false
    tooltip("可以用快捷键了")
}
return

#if 

#if (!is_typing) and (WinActive("ahk_class Photoshop"))  and (not A_CaretX)  
:*:a::
sendinput, {text}a
return

:*:b::
SendInput, {text}b
return

:*:c::
SendInput, {text}c
return

:*:d::
SendInput, {text}d
return

:*:e::
SendInput, {text}e
return

:*:f::
SendInput, {text}f
return

:*:g::
SendInput, {text}g
return

:*:h::
SendInput, {text}h
return

:*:i::
SendInput, {text}i
return

:*:j::
SendInput, {text}j
return

:*:k::
SendInput, {text}k
return

:*:l::
SendInput, {text}l
return

:*:m::
SendInput, {text}m
return

:*:n::
SendInput, {text}n
return

:*:o::
SendInput, {text}o
return

:*:p::
SendInput, {text}p
return

:*:q::
SendInput, {text}q
return

:*:r::
SendInput, {text}r
return

:*:s::
SendInput, {text}s
return

:*:u::
SendInput, {text}u
return

:*:v::
SendInput, {text}v
return

:*:w::
SendInput, {text}w
return

:*:x::
SendInput, {text}x
return

:*:y::
SendInput, {text}y
return

:*:z::
SendInput, {text}z
return

#if

;::xyz::不受t影响的热字串

tooltip(text := "", time := 1500) {
    Tooltip % text
    if text != ""
        SetTimer, % A_ThisFunc, % "-" time
}

在此处键入或粘贴代码

另一种方式,通过切中英输入法键盘,好处是可以直接看到目前的状态是中文还是英文

#NoTrayIcon
#NoEnv
#SingleInstance Force

;SwitchIME(04090409) ; 英语(美国) 美式键盘
;SwitchIME(00000804)  ; 中文(中国) 简体中文-美式键盘


SwitchIME(dwLayout){
    HKL:=DllCall("LoadKeyboardLayout", Str, dwLayout, UInt, 1)
    ControlGetFocus,ctl,A
    SendMessage,0x50,0,HKL,%ctl%,A
}


#if (WinActive("ahk_class Photoshop")) and (not A_CaretX)  

~t::
if (!is_typing) {
    is_typing := true
	SwitchIME(00000804)
    tooltip("可以打字了,退出按Esc")
}
return

~Esc::
if (is_typing) {
    is_typing := false
    SwitchIME(04090409)
    tooltip("可以用快捷键了")
}
return

#if 

#if (!is_typing) and (WinActive("ahk_class Photoshop"))  and (not A_CaretX)  
~a::
~b::
~c::
~d::
~e::
~f::
~g::
~h::
~i::
~j::
~k::
~l::
~m::
~n::
~o::
~p::
~q::
~r::
~s::
~u::
~v::
~w::
~x::
~y::
~z::
SwitchIME(04090409)
return
#if

;::xyz::不受t影响的热字串

tooltip(text := "", time := 1500) {
    Tooltip % text
    if text != ""
        SetTimer, % A_ThisFunc, % "-" time
}

1 Like

借鉴一下 VIM,只要在这两个软件里,就是英文输入。具体实现用按键映射还是什么的都可以。

然后设定某个特定的快捷键,进入编辑状态,这个快捷键不会产生输入。比如:右侧 Alt 可能你从来都不用,那就用这个按键来切换状态好了。而实际代码中,只需要用这个按键来控制脚本的启用和暂停即可。

但是 Esc 退出编辑状态可能有点小问题,比如输入时打错了,我有时候会用 Esc 整体清除,然后重新打。所以还是用上面的快捷键退出比较稳妥。

为了可以看到现在的状态,在托盘再显示一个图标就好。这一切都不难做到。只是……这和用 Shift 切换中英文好像没区别……

会好一点点,因为ps里经常会用到shift,alt用的相对少一点?我之前写过这种方案,用的是Capslock,不过还是有点麻烦,不能做到无感

autohotkey提供了内置变量A_CaretX和A_CaretY,指示当前光标(文本插入点)的X和Y坐标。如果没有使用 CoordMode 使得坐标相对于整个屏幕, 默认坐标相对于活动窗口. 如果没有活动窗口或无法确定文本插入点的位置, 则这两个变量为空。

这种方式能检测到文本框吗?

如果可以,那是最好的,如果不行,我讲另一种方案,不过通用性比较低。

利用 AHK 的图片查找功能,在左上查找文本编辑的图标,就是菜单栏底下根据不同工具会发生变化的那一条工具栏。不过这个方法可能换电脑就得重新弄一下那个要查找的图片。这样就可以判断输入状态了。因为 AHK 资源占用很小,即便是 0.1 秒检测一次问题也不大,基本可以做到无感。

A_CaretX 我的脚本上也用到了,这个可以检测到重命名图层的光标,但是t的文字框检测不到,包括chrome里的光标也检测不到。

你说的这个识图确实是个无感的办法欸,就是感觉有点重,也可以试试看

你试试看先,反正代码也不算复杂,倒是调节识别的阈值稍微需要尝试几次。

AHK 的有些操作比我们想象中的资源占用要小得多。我挺强迫症的,但是居然对于 AHK 的循环检测并不反感,就是因为资源占用太无感了。

何况这两个软件窗口没获得焦点的时候还可以停止这种检测

我写出来试了下,发现这个方案存在一个问题:如果目前是在文字工具下,左上角显示T的图,则处于中文状态,那么现在就不能按快捷键离开文字工具了……

啊,我一般不用 esc 退出文本框,都是鼠标,毕竟怎么也不可能脱离开鼠标操作的。所以就没困扰。如果你用 esc,那就保留对它的映射好了

对于我这种用了十几年PS/AI的人,反而是ctrl+space加上PS、AI自定义快捷键更加习惯了。
记得早期做网页的时代,甚至不用中文命名,全部用英文。
后面自定义快捷键用熟之后,已经形成肌肉记忆,只在管理图层的时候切换一些输入法。

我又改了一下,确实可以了!要检测正在输入的时候的左上角文字工具的图标,而不是单纯地文字工具的图标,确实是最完美的解法了!

#if (WinActive("ahk_class Photoshop")) and (not A_CaretX)  

SetTimer, isT, 150
return

isT:
ImageSearch, FoundX, FoundY, 0, 0, 150, 150, %A_ScriptDir%\PSt.png

if (ErrorLevel = 2) {       ; 没找到
    MsgBox 2.出错了
	Return
	}
else if (ErrorLevel = 1){ ; 没找到,在快捷键模式下
	is_typing := True
	Return
	}
else if (ErrorLevel = 0) {    ; 找到了,在中文模式下
	is_typing := False
	Return
	}

#if 

#if (is_typing) and (WinActive("ahk_class Photoshop"))  and (not A_CaretX)  

a::
b::
c::
d::
e::
f::
g::
h::
i::
j::
k::
l::
m::
n::
o::
p::
q::
r::
s::
t::
u::
v::
w::
x::
y::
z::
sendinput, {text}%A_ThisHotkey%
Return

#if

嘿嘿嘿 :laughing:

完美解决,集成到我开机的ahk一体脚本里了,但是不知道为什么必须放在引用标签的前面,在后面都会失效
我有很多标签是常用功能,但是很多程序都反复调用,形式是
1:
run xxx
return
2:
send xxx
return

我也遇到多个功能放在一个脚本里会莫名其妙出一些问题的情况,debug也比较费事,我目前的方法还是一个功能一个脚本,然后用个管理脚本的脚本,效果还挺好