使用AutoHotKey(或其他)创建自定义键盘布局

时间:2015-03-21 05:04:57

标签: windows unicode keyboard autohotkey

我正在寻找创建自定义键盘布局,主要用于键入unicode数学符号。我需要的符号集非常大,我想出的方案涉及多种布局和特殊组合。

我输入`(反引号)一次,而我得到一个特殊字符,我们将用*表示。通过键入其他键,我获得与特定主题相关的特定键盘布局。 (我想用一个特殊符号替换后面的刻度,这样我就记住它是一种控制代码。通过键入两次,我得到一个正常的后退滴答)

以下是一些示例映射:

*s -> Set theory layout:
    [ -> ∈ (element of)
    o -> ∅ (empty set)

*r -> General math:
    s -> ∫ (integral sign)
    S -> ∬ (double integral sign)

*e -> Misc operators:
    8 -> ∗ (convolution asterisk)
    * -> ⋆ (star operator)

*g -> Greek alphabet

输入=之类的字符后,我可以输入一些其他特殊组合来修改该字符。例如:

*x -> Negates the previous character:
    = -> ≠ (unequal)
    ≡ -> ≢ (negation of three line equality)

*w -> Expands the previous character:
    ∫ -> ∭ (triple integral)
    ∬ -> ⨌ (quad integral)

映射是助记符。我可以想象将我想要的所有符号塞进一个布局中,但它将无法使用,所以我想尝试坚持这个方案或类似的东西。

键盘适用于Windows环境,但我不会自己编写键盘DLL。我调查了它,这太复杂了。

现在,我正在寻找AHK寻求解决方案。可以在AHK(或类似的东西)中完成吗?如果是这样,你能告诉我一些让我入门的例子吗?

我还想知道是否有其他方法可以做到这一点。

我知道Microsoft键盘布局创建器,并且过去曾使用它,但它不够强大。我也知道Tavultesoft的Keyman,我知道它可以做我想要的事情,但它的价格非常昂贵,所以它不是一个选择。

1 个答案:

答案 0 :(得分:3)

您可以使用AutoHotkey完成所需。

棘手的部分是:您需要动态分配热键和Hotstrings。前者可以使用Hotkey - 命令,后者尚未实现,可能永远不会实现。 您可以将它们写入新的.ahk文件并单独执行该脚本,或使用polyethene's really awesome dynamical regEx hotstring creator。 autohotkey.net的存储库已经停机多年,但我找到了脚本here。 要运行以下示例脚本,您需要将该脚本下载到Hotstrings.ahk并将其放在主.ahk文件所在的目录中。

但是,我无法将布局转换器热键分配给

`

,所以我将其设置为ä

我知道这个网站不是代码提供商网络,但我对此问题也很感兴趣。

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
#include Hotstrings.ahk

lastKey := ""

; KEYS OF THE NORMAL LAYOUT WHICH SHOULD BE NEGATABLE:
hotstrings("=", "_equals")  ;

; CHOOSE LAYOUT OR NEGATE/EXPAND LAST CHARACTER:
:*?:ä::
; backSpacePressed:  ; wtf is this? sorry just saw this now. Does not belong here, does not belong anywhere
    sendRaw *
    tooltip, 
    (
    n   normal layout

    s   set theory
    r   general math

    x   negate previous
    w   expand previous

    {esc}   cancel
    ), %A_CaretX%, %A_CaretY%
    input, layout, L1, {Escape}, s,r,e,g,x,w
    send {Backspace}    ; remove the *
    if layout in n,s,r,e,g,x,w
    {
        tooltip, %layout%, %A_CaretX%, %A_CaretY%

        ; RESET
        if layout = n
        {
            reset_all_hotstrings()

            ; KEYS OF THE NORMAL LAYOUT WHICH SHOULD BE NEGATABLE:
            hotstrings("=", "_equals")
        }



        ; NEW LAYOUT
        else if layout = s
        {
            reset_all_hotstrings()

            ; SET THEORY SHORTCUTS
            hotstrings("o", "_emptySet")
            hotstrings("\[", "_elementOf")
        }
        else if layout = r
        {
            reset_all_hotstrings()

            ; MATH SHORTCUTS
            hotstrings("s", "_integral")
            hotstrings("S", "_doubleIntegral")
            hotstrings("=", "_identical")
        }
        ; and so on
        ; ...



        ; EDIT PREVIOUS CHARACTER
        else if layout = x
        {
            send {backSpace}

            if lastKey = identical
                sendUnicodeChar(0x2262)
            else if lastKey = equals
                sendUnicodeChar(0x2260)
        }
        ; EXPAND PREVIOUS CHARACTER
        else if layout = w
        {
            send {backSpace}

            if lastKey = integral
                sendUnicodeChar(0x222D)
            else if lastKey = doubleIntegral
                sendUnicodeChar(0x2A0C)
        }
    }
    else
    {
        tooltip, cancelled, %A_CaretX%, %A_CaretY%
    }
    sleep, 500
    tooltip
return

reset_all_hotstrings() {
    hotstrings("=")
    hotstrings("\[")
    hotstrings("o")
    hotstrings("s")
    hotstrings("S")
    ; and so on
}

; NORMAL LAYOUT SHORTCUTS:
_equals:
    sendUnicodeChar(0x003D)
    lastKey = equals
return



; SPECIAL LAYOUT SHORTCUTS:
_emptySet:
    ;sendUnicodeChar(0x00D8)
    altNumpad(0216)
        ; to find out numpad combination or unicode: press WIN+R, type in "charmap"
        ; or for unicode only, go to http://www.fileformat.info/info/unicode/category/index.htm
        ; (sendUnicodChar() needs 0x before the unicode string)
    ;altNumpad(0248)
    ;send Ø
    ;send ø
    ;   choose whatever works best for you
    lastKey = emptySet
return

_elementOf:
    sendUnicodeChar(0x2208)
    lastKey = elementOf
return

_integral:
    sendUnicodeChar(0x222B)
    lastKey = integral
return

_identical:
    sendUnicodeChar(0x2261)
    lastKey = identical
return

_doubleIntegral:
    sendUnicodeChar(0x222C)
    lastKey = doubleIntegral
return

; -------------------------------------------

altNumpad(numbers) {
    stringSplit, n, numbers
    setkeydelay, 100
    send {alt down}
    loop, %n0%
    {
        t := n%a_index%
        send {numpad%t%}
    }
    send {alt up}
}


SendUnicodeChar(charCode)
{
    VarSetCapacity(ki, 28 * 2, 0)
    EncodeInteger(&ki + 0, 1)
    EncodeInteger(&ki + 6, charCode)
    EncodeInteger(&ki + 8, 4)
    EncodeInteger(&ki +28, 1)
    EncodeInteger(&ki +34, charCode)
    EncodeInteger(&ki +36, 4|2)

    DllCall("SendInput", "UInt", 2, "UInt", &ki, "Int", 28)
}

EncodeInteger(ref, val)
{
    DllCall("ntdll\RtlFillMemoryUlong", "Uint", ref, "Uint", 4, "Uint", val)
}

^e::reload

显然还有很大的改进空间,显然