V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
cy18
V2EX  ›  分享创造

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

  •  2
     
  •   cy18 · 2017-04-29 12:37:05 +08:00 via Android · 5544 次点击
    这是一个创建于 2763 天前的主题,其中的信息可能已经有所发展或是发生改变。

    按住空格键大概 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 <[email protected]>
    ;
    ; 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
    
    第 1 条附言  ·  2018-02-04 13:54:34 +08:00
    现在的脚本在新版的 AHK 里面会有点问题,我做了点小改进然后放在 https://github.com/cy18/ahk 了。
    21 条回复    2018-06-10 00:18:46 +08:00
    shoaly
        1
    shoaly  
       2017-04-29 21:52:45 +08:00
    问一下楼主两个问题呢 :
    Send, {F18} 为什么要 send 这个 f18 呢....
    第二个建议, 可以把修饰键做成 变量不, 这样支持 一键从空格键触发改成 , esc 触发, `键触发....win 键触发..
    cy18
        2
    cy18  
    OP
       2017-04-30 01:36:31 +08:00 via Android
    F18 是为了结束那个 input 过程找的一个不会影响其他东西的不存在的按键。没想到其他实现这个的办法。

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

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

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

    ;
    ; AutoHotkey Version: 1.x
    ; Language: English
    ; Platform: Win9x/NT
    ; Author: cy18 <[email protected]>
    ;
    ; 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
        11
    xxxcjr  
       2018-03-28 22:17:07 +08:00
    很棒脚本,但是使用中有个问题:输入中文的时候总是时不时变成英文,特别是打字速度快的时候,中英文切换是按 shift 键。有办法解决吗?
    cy18
        12
    cy18  
    OP
       2018-03-29 12:35:30 +08:00 via Android
    把脚本里的 Rshift 改成 RControl 或者 F18 之类的没用的键就行了- -
    cy18
        13
    cy18  
    OP
       2018-03-29 12:36:27 +08:00 via Android   ❤️ 1
    @xxxcjr
    把脚本里的 Rshift 改成 RControl 或者 F18 之类的没用的键就行了。
    xxxcjr
        14
    xxxcjr  
       2018-03-29 22:35:22 +08:00
    @cy18 改成 RControl 了,比改成 F18 好,F18 在 vim 中有时候还会输入。
    moonhuahua
        15
    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
        16
    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
        17
    moonhuahua  
       2018-04-18 00:38:03 +08:00
    里面赠送了个快速切换微信联系人的彩蛋,哈哈
    xxxcjr
        18
    xxxcjr  
       2018-05-31 08:15:16 +08:00
    @cy18 经过这段时间的使用,在 vim 中还是会出现一些奇怪的问题,我想如果改成 RAlt 可能能够避免。
    请问,如果要把这个修饰符改成 Ralt 应该怎么改?
    cy18
        19
    cy18  
    OP
       2018-05-31 17:39:24 +08:00 via Android
    alt 好像在很多窗口里面会直接跳出菜单。要改的话直接把花括号里面的东西批量替换了就好了
    xxxcjr
        20
    xxxcjr  
       2018-06-09 21:25:46 +08:00
    @cy18
    已经改成 Ralt 键了。
    怎么说呢,当然没有空格键按起来方便快捷。

    但是打字的时候感觉好太多了,毕竟打字按空格的次数要比按修饰键+ESDF 移动光标的次数多多了。因此我觉得还是很值得的。
    你说的跳出菜单的情况并没有发生,就像你把空格变成修饰键不会按出一堆空格一样。不过我还是把 Send, {Blind}{Space} 这一行改成,Send, {Blind}{ctrl},这样完全不用担心弹出菜单的问题。
    cy18
        21
    cy18  
    OP
       2018-06-10 00:18:46 +08:00
    @xxxcjr 我理解错你的意思了- -
    我试了一下,RAlt 确实也挺方便的- -而且我现在大部分的快捷键都是在左手,所以用 RAlt 完全不会有冲突的感觉……
    实现起来也方便,不用像空格这样加一堆东西,直接用 AHK 现成的功能就能实现。
    等有空了我也搞一个这种试试
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5508 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 01:34 · PVG 09:34 · LAX 17:34 · JFK 20:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.