写了一个用空格键当修饰键的 ahk 脚本,打字的时候不用移动手就能直接按到方向, backspace 之类的常用按键

2017-04-29 12:37:05 +08:00
 cy18

按住空格键大概 0.1 秒之后,空格键变成修饰键,然后可以用 edsf 控制方向,wr 控制 home 跟 end,cv 控制 backspace 跟 del,其他键还是照常工作。根据个人习惯可以改其他快捷键。

用了这套快捷键之后根本停不下来,完全不用移动手腕就可以控制方向,删除打错的字符。在不支持 vim 命令的编辑器里面尤其方便。相比于用 ctrl,alt,shift 做快捷键,空格键更方便,大拇指直接按下去就可以了。唯一的问题就是按住空格不放不能重复输入空格了。我个人感觉这个基本没有影响。

网上有一个类似的脚本,不过打字比较快的时候容易出问题,我重写了一个改进版的,打字快的时候基本不会出错。 这是我的第一个 ahk 脚本,有什么需要改进的地方,或者 ahk 高手看到有什么函数用错的地方,都欢迎提出来。

;
; AutoHotkey Version: 1.x
; Language:       English
; Platform:       Win9x/NT
; Author:         cy18 <thecy18@gmail.com>
;
; An improved script to use space as modifier
; In normal cases, if space is pressed for more than 0.1 second, it becomes a modifier, this time could be modified in the script
; If no other keys are pressed during space is pressed, a space is output when space is released
; Severial tunes are made so that the script works well when typing in fast speed
; Note that repeating space no longer works

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

AnyKeyPressedOtherThanSpace(mode = "P") {
    keys = 1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./
    Loop, Parse, keys
    {        
        isDown :=  GetKeyState(A_LoopField, mode)
        if(isDown)
            return True
    }   
    return False
}
 
Space Up::
    space_up := true
    Send, {F18}
    return
Space::
    if AnyKeyPressedOtherThanSpace(){
        SendInput, {Blind}{Space}
        Return
    }
    space_up := False
    inputed := False
    input, UserInput, L1 T0.1, {F18}
    if (space_up) {
        Send, {Blind}{Space}
        return
    }else if (StrLen(UserInput) == 1){
        Send, {Space}%UserInput%
        return
    }
    while true{
        input, UserInput, L1, {F18}
        if (space_up) {
            if (!inputed){
                Send, {Blind}{Space}
            }
            break
        }else if (StrLen(UserInput) == 1) {
            inputed := True
            StringLower, UserInput, UserInput
            if (UserInput == "e")
                Send, {Blind}{Up}
            else if (UserInput == "d")
                Send, {Blind}{Down}
            else if (UserInput == "s")
                Send, {Blind}{Left}
            else if (UserInput == "f")
                Send, {Blind}{Right}
            else if (UserInput == "w")
                Send, {Blind}{Home}
            else if (UserInput == "r")
                Send, {Blind}{End}
            else if (UserInput == "c")
                Send, {Blind}{BS}
            else if (UserInput == "v")
                Send, {Blind}{DEL}
            else
                Send, {Blind}%UserInput%
        }
    }
    return
5334 次点击
所在节点    分享创造
21 条回复
shoaly
2017-04-29 21:52:45 +08:00
问一下楼主两个问题呢 :
Send, {F18} 为什么要 send 这个 f18 呢....
第二个建议, 可以把修饰键做成 变量不, 这样支持 一键从空格键触发改成 , esc 触发, `键触发....win 键触发..
cy18
2017-04-30 01:36:31 +08:00
F18 是为了结束那个 input 过程找的一个不会影响其他东西的不存在的按键。没想到其他实现这个的办法。

至于其他修饰键,直接搜索替换吧...ahk 怎么用变量实现这个我也不太懂...

不过我感觉其他键触发感觉就意义不大了,像 ALT 之类的离手指都比较近,没必要用其他键做修饰。win 这种也不用搞得我这个这么麻烦。之所以用空格就是想完全不移动手。
nicktogo
2017-04-30 16:39:32 +08:00
收藏了,作为不会 vim 的试试看。
xiaopenyou
2017-05-03 20:31:44 +08:00
不错!好用,而且和我现有的 AutoHotkey 脚本不冲突,感谢
xy19009188
2017-05-15 22:00:36 +08:00
楼主,我想用 ahk 实现 mac 上的 spacelauncher 功能,目前不是很完美。。https://spacelauncherapp.com/
cy18
2017-05-16 12:52:16 +08:00
@xy19009188 主要是哪方面的问题?
moonhuahua
2017-07-30 10:51:13 +08:00
@cy18 我在你的基础上修改了一下,加入空格加大写和 F1-12、tab、win、Ctrl、方向键。。。。相当于稍微扩展了下,代码如何给你 呢 可以麻烦你 加群 271105729 吗,这个是 ahk 的 爱好群,里面很多 ahk 的大神
moonhuahua
2017-07-30 11:06:19 +08:00
@cy18 顺便也变通解决了你说的按住空格不放不能重复输入空格的唯一的问题,我是按一直空格+tab 来重复输入空格的,这个很简单::
else if (ErrorLevel="EndKey:Tab")
SendInput, {Blind}{Space}

加以上语句就可以的了
cy18
2018-02-04 13:42:35 +08:00
@moonhuahua 我试了一下不行- -不知道是不是版本问题,不过改成
else if (UserInput == "`t")
SendKey(" ")就可以用空格+tab 输入空格了
cy18
2018-02-04 13:46:30 +08:00
现在的脚本在新版的 AHK 会有点问题,下面是改进过的版本:

;
; AutoHotkey Version: 1.x
; Language: English
; Platform: Win9x/NT
; Author: cy18 <thecy18@gmail.com>
;
; An improved script to use space as modifier
; In normal cases, if space is pressed for more than 0.1 second, it becomes a modifier, this time could be modified in the script
; If no other keys are pressed during space is pressed, a space is output when space is released
; Severial tunes are made so that the script works well when typing in fast speed
; Note that repeating space no longer works

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
StringCaseSense, On

AnyKeyPressedOtherThanSpace(mode = "P") {
keys = 1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./
Loop, Parse, keys
{
isDown := GetKeyState(A_LoopField, mode)
if(isDown)
return True
}

return False
}


supressed := False
RestoreInput(){
BlockInput, Off
Global supressed
supressed := False
}

SupressInput(){
Global supressed
supressed := True
BlockInput, On
SetTimer, RestoreInput, -180
}

ModifierStates := ""
UpdateModifierStates(){
Global ModifierStates
if (supressed){
return
}
ModifierStates := ""

if GetKeyState("LWin", "P") || GetKeyState("RWin", "P") {
ModifierStates .= "#"
}

if GetKeyState("Ctrl", "P"){
ModifierStates .= "^"
}

if GetKeyState("Alt", "P"){
ModifierStates .= "!"
}

if GetKeyState("Shift", "P"){
ModifierStates .= "+"
}
}

SendKey(Key, num=1){
Global ModifierStates
Loop, %num%{
Send, %ModifierStates%%Key%
}
}

ReleaseModifier(){
global space_up
if (not space_up){
space_up := true
}
Send, {RShift}
}

Space Up::
Send {Blind}{Space up}
space_up := true
SendEvent, {RShift}
return
Space::
if AnyKeyPressedOtherThanSpace(){
SendInput, {Blind}{Space}
Return
}
if (GetKeyState(LShift, mode)){
SendInput ^{Space}
Return
}
inputed := False
space_up := False
input, UserInput, L1 T0.05, {RShift}
if (space_up) {
Send, {Blind}{Space}
return
}else if (StrLen(UserInput) == 1){
Send, {Space}%UserInput%
return
}
SetTimer, ReleaseModifier, -18000
while true{
input, UserInput, L1, {RShift}
if (space_up) {
if (!inputed){
Send, {Blind}{Space}
}
break
}else{
inputed := True
StringLower, UserInput, UserInput
UpdateModifierStates()
SupressInput()
if (UserInput == "e")
SendKey("{Up}")
else if (UserInput == "d")
SendKey("{Down}")
else if (UserInput == "s")
SendKey("{Left}")
else if (UserInput == "a")
SendKey("{Left}", 8)
else if (UserInput == "f")
SendKey("{Right}")
else if (UserInput == "g")
SendKey("{Right}", 8)
else if (UserInput == "w")
SendKey("{Home}")
else if (UserInput == "r")
SendKey("{End}")
else if (UserInput == "c")
SendKey("{BS}")
else if (UserInput == "x")
SendKey("{BS}", 6)
else if (UserInput == "v")
SendKey("{DEL}")
else if (UserInput == "b")
SendKey("{DEL}", 6)
else if (UserInput == "5")
SendKey("{F5}")
else if (UserInput == "8"){
RestoreInput()
break
}else if (UserInput == "`t")
SendKey(" ")
else
Send, {Blind}%UserInput%
}
}
RestoreInput()
return
xxxcjr
2018-03-28 22:17:07 +08:00
很棒脚本,但是使用中有个问题:输入中文的时候总是时不时变成英文,特别是打字速度快的时候,中英文切换是按 shift 键。有办法解决吗?
cy18
2018-03-29 12:35:30 +08:00
把脚本里的 Rshift 改成 RControl 或者 F18 之类的没用的键就行了- -
cy18
2018-03-29 12:36:27 +08:00
@xxxcjr
把脚本里的 Rshift 改成 RControl 或者 F18 之类的没用的键就行了。
xxxcjr
2018-03-29 22:35:22 +08:00
@cy18 改成 RControl 了,比改成 F18 好,F18 在 vim 中有时候还会输入。
moonhuahua
2018-04-18 00:35:36 +08:00
@cy18 大神你好,我改动了的代码最新版本 1.1.28.02 下是可用的,可以使用空格加“任何大写字母” 或 F1-12、tab、win、`( 1 左边的那个)、方向键。。。。完整代码如下::
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
StringCaseSense, On
moonhuahua
2018-04-18 00:36:03 +08:00
global space_up

;{ 新 space 脚本
Space Up::
global space_up := true
Send, {F18}
sendinput {Space Up}
return
Space::
if AnyKeyPressedOtherThanSpace(){
SendInput, {Blind}{Space}
Return
}
space_up := False
inputed := False
wordformatcopy := 0
input, UserInput, L1 T0.05, {F18}
if (space_up){
Send, {Blind}{Space}
return
}else if (StrLen(UserInput) == 1){
Send, {Space}%UserInput%
return
}
while true{
input, UserInput, L1, {LControl}{RControl}{LAlt}{RAlt}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Capslock}{Numlock}{PrintScreen}{Pause}{Tab}{F18}{F23}{RButton}
;~ MsgBox %ErrorLevel%
if (space_up){
if (!inputed){
Send, {Blind}{Space}
}
break
return
}else if (UserInput == "``"){
return
}else if (ErrorLevel="EndKey:Tab"){
SendKey("{Down}")
;~ return
}else if (ErrorLevel="EndKey:LWin"){
Send, {Space}
;~ return
}else if (ErrorLevel="EndKey:RWin"){
SendKey("{Left}")
}else if (ErrorLevel="EndKey:F1"){
SendKey("{Left}", 8)
return
}else if (ErrorLevel="EndKey:F2"){
return
}else if (ErrorLevel="EndKey:F3"){
sendinput !p
return
}else if (ErrorLevel="EndKey:F4"){
wingettitle, ut, A
if ut = Adobe Photoshop CC 2015
Send, !{F4}
else
{
SendInput ^w
Sleep 100
SendInput n{Enter}
}
return
}else if (StrLen(UserInput) == 1) {
inputed := True ;;;;;;;;;;;;;;;正式开始;;;;;;;;;;;;;;;
if (UserInput == "w")
Send, {up}
;~ return
else if (UserInput == "s")
Send, {Down}
;~ return
else if (UserInput == "a")
Send, {Left}
else if (UserInput == "d")
Send, {Right}
else if (UserInput == "W")
Send, !]
;~ return
else if (UserInput == "S")
return
else if (UserInput == "A")
return
else if (UserInput == "D")
return
else if (UserInput == "1")
return
else if (UserInput == "2")
return
else if (UserInput == "3")
return
else if (UserInput == "4")
return
else if (UserInput == "5")
return
else if (UserInput == ","){
return
}else if (UserInput == "."){
return
}else if (UserInput == "6"){
return
}else if (UserInput == "b"){
return
}else if (UserInput == "c"){
Send, i
return
}else if (UserInput == "C"){
return
}else if (UserInput == "e"){
return
}else if (UserInput == "E"){
return
}else if (UserInput == "f"){
return
}else if (UserInput == "F"){
return
}else if (UserInput == "g"){
Send, ^g
;~ return
}else if (UserInput == "G"){
return
}else if (UserInput == "h"){
return
}else if (UserInput == "H"){
return
}else if (UserInput == "i"){
Send, ^i
;~ return
}else if (UserInput == "j"){
Send, ^j
return
}else if (UserInput == "k"){
return
}else if (UserInput == "l"){
return
}else if (UserInput == "m"){
return
}else if (UserInput == "n"){
send, ^n
send, {Enter}
return
}else if (UserInput == "o"){
send, ^o
return
}else if (UserInput == "p"){
return
}else if (UserInput == "q"){
QuickInputList=
(Ltrim
--[家庭]--
&2)甜甜
&b)爸爸
--[工作]--
&z)庄大彪
&Z)李大新
--[供应商]--
&j)胡瑛
&t)周丽娟
--[朋友]--
&w)李平
&e)李红钢
)
MySub_QuickInputtx(QuickInputList)
return
}else if (UserInput == "r"){
return
}else if (UserInput == "t"){
return
}else if (UserInput == "u"){
send ^+z
;~ return
}else if (UserInput == "v"){
Send, {NumpadAdd}
;~ return
}else if (UserInput == "x"){
send, x
;~ return
}else if (UserInput == "y"){
return
}else if (UserInput == "z"){
try {
SetTitleMatchMode RegEx
SetTitleMatchMode Slow
ControlClick, i).*确定|OK.*, A
} catch e {
ControlClick, Button1, A
}
return
}else if (UserInput == "Z"){
return
}else if (UserInput == "["){
return
}else if (UserInput == "]"){
return
}else if (UserInput == "/"){
;~ Run %a_scriptdir%\Apps\Word\Vim-Word.jpg
return
}else if (UserInput == "="){
return
}else if (UserInput == "-"){
return
}else
Send, {Blind}%UserInput%
}
}
return
;}


MySub_QuickInputtx(String){
menu,KyMenu_QuickInput,Add
menu,KyMenu_QuickInput,DeleteAll
Loop,parse,String,`n,`r
{
if (A_LoopField="")
continue
if (A_LoopField="-")
menu,KyMenu_QuickInput,Add
else
menu,KyMenu_QuickInput,Add,% A_LoopField,KyMenu_QuickInput_Handlertx
}
menu,KyMenu_QuickInput,show
return

KyMenu_QuickInput_Handlertx:
PostMessage, 0x50, 0, 0x4090409, , A ;切换为英文 0x4090409=67699721
outputStr:=substr(A_ThisMenuItem,4,strlen(A_ThisMenuItem))
;~ if GetKeyState("Shift")
;~ Stringupper, outputStr, outputStr
sendinput ^!z
Sleep 300
SendInput {raw}%outputStr%
Sleep 300
SendInput {Enter}
PostMessage, 0x50, 0, 0x8040804, , A ;切换为中文 0x8040804=134481924
return
}

AnyKeyPressedOtherThanSpace(mode = "P") {
keys = 1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./
Loop, Parse, keys
{
isDown := GetKeyState(A_LoopField, mode)
if(isDown)
return True
}
return False
}
moonhuahua
2018-04-18 00:38:03 +08:00
里面赠送了个快速切换微信联系人的彩蛋,哈哈
xxxcjr
2018-05-31 08:15:16 +08:00
@cy18 经过这段时间的使用,在 vim 中还是会出现一些奇怪的问题,我想如果改成 RAlt 可能能够避免。
请问,如果要把这个修饰符改成 Ralt 应该怎么改?
cy18
2018-05-31 17:39:24 +08:00
alt 好像在很多窗口里面会直接跳出菜单。要改的话直接把花括号里面的东西批量替换了就好了
xxxcjr
2018-06-09 21:25:46 +08:00
@cy18
已经改成 Ralt 键了。
怎么说呢,当然没有空格键按起来方便快捷。

但是打字的时候感觉好太多了,毕竟打字按空格的次数要比按修饰键+ESDF 移动光标的次数多多了。因此我觉得还是很值得的。
你说的跳出菜单的情况并没有发生,就像你把空格变成修饰键不会按出一堆空格一样。不过我还是把 Send, {Blind}{Space} 这一行改成,Send, {Blind}{ctrl},这样完全不用担心弹出菜单的问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/358093

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX