# 重映射操纵杆为键盘或鼠标

## 目录

- 重要事项
- 让操纵杆按钮发送键击或鼠标点击

- 不同的方法
- 自动重复键击
- 上下文相关的操纵杆按钮
- 用操纵杆作为鼠标

- 让其他操纵杆控制发送按键或鼠标点击
  - 操纵杆轴
  - 操纵杆 POV 帽
  - 自动重复按键
- 备注
- 相关话题

## 重要事项

- 虽然可以把操纵杆按钮或轴向重映射为按键或鼠标按钮, 但不能把它重映射为其他的操纵杆按钮或轴向. 需借助游戏模拟器例如 vJoy 才有可能实现这样操作.
- AutoHotkey 用 1 和 32 之间的一个唯一的数字来标识操纵杆上的每个按钮. 要判断这些编号, 请使用操纵杆测试脚本.

## 让游戏杆按钮发送键击或鼠标点击

### 不同的方法

下面是从最简单到最复杂的三种方法. 最复杂的方法能适用于更大范围的情况(例如需要按下按键或鼠标按钮的游戏).

#### 方法 #1

此方法简单地发送键击和鼠标点击. 例如:

    Joy1::Send {Left}  ; 让按钮 #1 发送左方向键的键击.
    Joy2::Click  ; 让按钮 #2 发送鼠标左键的点击.
    Joy3::Send a{Esc}{Space}{Enter}  ; 让按钮 #3 发送字母 "a" 后面跟着 Escape, Space 以及 Enter.
    Joy4::Send Sincerely,{Enter}John Smith  ; 让按钮 #4 发送两行的签名.

要让一个按钮执行多个命令, 请把首个命令放到按钮名称的 下面 并使用 return 作为最后一个命令. 例如:

    Joy5::
    Run Notepad
    WinWait Untitled - Notepad
    WinActivate
    Send This is the text that will appear in Notepad.{Enter}
    return

请参阅按键列表来了解按键和鼠标/游戏杆按钮的完整列表.

#### 方法 #2

必须使用此方法的情况是当您在按住操纵杆按钮的整个过程中必须按住按键或鼠标按钮的时候. 下面的例子把操纵杆的第二个按钮映射为左方向键:

    Joy2::
    Send {Left down}  ; 按住左方向键.
    KeyWait Joy2  ; 等待用户释放操纵杆按钮.
    Send {Left up}  ; 释放左方向键.
    return

#### 方法 #3

必须使用此方法的情况是在您设置了多个方法 #2 中描述的热键类型, 且有时需要同时按下和释放这些热键的时候. 下面的例子把操纵杆的第三个按钮映射为鼠标左键:

    Joy3::
    Send {LButton down}   ; 按住鼠标左键.
    SetTimer, WaitForButtonUp3, 10
    return

    WaitForButtonUp3:
    if GetKeyState("Joy3")  ; 按钮仍处于按下的状态, 所以继续等待.
        return
    ; 否则按钮已经松开了.
    Send {LButton up}  ; 释放鼠标左键.
    SetTimer, WaitForButtonUp3, Off
    return

### 自动重复键击

有些程序或游戏可能需要您重复发送某个按键(就像您按住键盘上的那个键不放一样). 下面的例子在您按住操纵杆的第二个按钮时通过重复发送空格的键击来达到此目的.

    Joy2::
    Send {Space down}   ; 按下空格键.
    SetTimer, WaitForJoy2, 30  ; 减小数字 30 到 20 或 10 来更快地发送按键. 增加这个数字以减小发送的速度.
    return

    WaitForJoy2:
    if not GetKeyState("Joy2")  ; 按钮已经释放了.
    {
        Send {Space up}  ; 释放空格键.
        SetTimer, WaitForJoy2, Off  ; 停止监视按钮.
        return
    }
    ; 由于上面没有 "return", 所以按钮仍处于按住的状态.
    Send {Space down}  ; 再次发送空格键击.
    return

### 上下文相关的操纵杆按钮

#IfWinActive/Exist 指令可以用来让选择的操纵杆按钮根据窗口是否活动或存在的不同情况执行不同的动作(或什么都不做).

### 把操纵杆作为鼠标

操纵杆映射到鼠标的脚本通过重映射操纵杆的按钮和轴向控制器来把操纵杆变成鼠标.

## 让其他操纵杆控制器发送键击或鼠标点击

要让脚本对操纵杆轴或视点帽的移动进行响应, 请使用 SetTimer 和 GetKeyState().

### 操纵杆轴

下面的例子让 X 和 Y 轴的功能像键盘上的方向键群 (左, 右, 上和下):

    #Persistent  ; 让脚本保持运行, 直到用户明确退出.
    SetTimer, WatchAxis, 5
    return

    WatchAxis:
    JoyX := GetKeyState("JoyX")  ; 获取 X 轴的位置.
    JoyY := GetKeyState("JoyY")  ; 获取 Y 轴的位置.
    KeyToHoldDownPrev = %KeyToHoldDown%  ; Prev 现在保存了之前按下的按键(如果有).

    if (JoyX > 70)
        KeyToHoldDown := "Right"
    else if (JoyX < 30)
        KeyToHoldDown := "Left"
    else if (JoyY > 70)
        KeyToHoldDown := "Down"
    else if (JoyY < 30)
        KeyToHoldDown := "Up"
    else
        KeyToHoldDown := ""

    if (KeyToHoldDown = KeyToHoldDownPrev)  ; 已经按下了正确的按键(或者不需要按键).
        return  ; 什么都不做.

    ; 否则, 释放之前的按键并按下新按键:
    SetKeyDelay -1  ; 避免键击之间的延迟.
    if KeyToHoldDownPrev   ; 要释放之前的按键.
        Send, {%KeyToHoldDownPrev% up}  ; 释放它.
    if KeyToHoldDown   ; 要按下按键.
        Send, {%KeyToHoldDown% down}  ; 按下它.
    return

### 操纵杆 POV 帽

下面的例子让操纵杆的视点帽的功能像键盘上的方向键群; 即视点帽会发送方向键的键击(左, 右, 上和下):

    #Persistent  ; 让脚本保持运行, 直到用户明确退出.
    SetTimer, WatchPOV, 5
    return

    WatchPOV:
    POV := GetKeyState("JoyPOV")  ; 获取 POV 控制器的位置.
    KeyToHoldDownPrev := KeyToHoldDown  ; Prev 现在保存了之前按下的按键(如果有).

    ; 有些操纵杆可能有平滑/连续的视角切换而不是使用固定的增幅. 要全部支持它们, 请使用范围:
    if (POV < 0)   ; 没有角度
        KeyToHoldDown := ""
    else if (POV > 31500)                 ; 315 至 360 度: 向前
        KeyToHoldDown := "Up"
    else if POV between 0 and 4500      ; 0 至 45 度: 向前
        KeyToHoldDown := "Up"
    else if POV between 4501 and 13500  ; 45 至 135 度: 向右
        KeyToHoldDown := "Right"
    else if POV between 13501 and 22500 ; 135 至 225 度: 向下
        KeyToHoldDown := "Down"
    else                                ; 225 到 315 度: 向左
        KeyToHoldDown := "Left"

    if (KeyToHoldDown = KeyToHoldDownPrev)   ; 已经按下了正确的按键(或不需要按键).
        return  ; 什么都不做.

    ; 否则, 释放之前的按键并按下新键:
    SetKeyDelay -1  ; 避免键击之间的延迟.
    if KeyToHoldDownPrev   ; 要释放之前的按键.
        Send, {%KeyToHoldDownPrev% up}  ; 释放它.
    if KeyToHoldDown   ; 要按下按键.
        Send, {%KeyToHoldDown% down}  ; 按下它.
    return

### 自动重复键击

上面的两个例子都可以修改为重复发送按键, 而不只是按住它(即它们可以模拟按住了某个按键). 要做到这点, 请把下面这行:

    return  ; 什么都不做.

替换为:

    {
        if KeyToHoldDown
            Send, {%KeyToHoldDown% down}  ; 自动重复的键击.
        return
    }

## 备注

通过在按钮或轴的名称之前加上操纵杆的编号可以使用首个外的其他操纵杆. 例如, `2Joy1` 表示第二个操纵杆的首个按钮.

要找到其他有用的操纵杆脚本, 请访问 AutoHotkey 论坛. 进行类似 Joystick and GetKeyState and Send 的关键词搜索有可能找到有趣的主题.

## 相关主题

- 操纵杆到鼠标的映射脚本(把操纵杆作为鼠标使用)
- 操纵杆按钮, 轴向和控制器的列表
- GetKeyState()
- 重映射键盘和鼠标

dftg