AutoHotkey
GPDWIN

GPD WIN用のパッド操作用AutoHotkeyスクリプト

More than 1 year has passed since last update.


はじめに

GPD WINというデバイスが一部で人気です。

このデバイスには通常のポインティングデバイスはついていませんが、代わりにゲームパッドがついており、パッドのモードを切り替えることでマウスとしても使えます。

ですがデフォルトの挙動やボタン設定がしっくりこないので、AutoHotkeyでスクリプトを書きました。

パッドをポインティングデバイスにする方法としては、JoyToKeyを使う方法が一般的ですが、JoyToKeyはシェアウェア1なのと、AutoHotkeyのほうが細かい挙動がいじりやすいのでAutoHotkeyを使用しています。


ボタン配置(暫定)

とりあえず以下のように設定。使ってくうちにより使いやすい配置にしてきます。

L3/R3には無変換/変換を割り当てて、IMEのOFF/ONに使っています。

Start/Selectは押しづらいので未設定です。コピペとか割り当てると良いかも。

クリック(A,Bボタン)を押したときに、マウスポインタを一瞬停止するようにしています。これはスティックを操作しながらボタンを押したときに、予期せぬドラッグ操作になることを防ぐためです。この辺の挙動を自由にいじれるのがJoyToKeyではなくAutoHotkeyを使うメリットです。

ボタン
機能

左スティック
ポインタの移動

右スティック上下
スクロール

右スティック左右
Shift+Tab/Tab

方向ボタン
矢印キー

Aボタン
左クリック

Bボタン
右クリック

Xボタン
タスクビュー2

Yボタン
中クリック

L1ボタン
スローボタン
(押してる間ポインタの動きが遅くなる)

R1ボタン
修飾キー

L2/R2トリガー
戻る/進む

L3/R3
無変換/変換

R1+Aボタン
Enter

R1+Bボタン
Esc

R1+Xボタン
Alt+Tab

R1+Yボタン
Win

Win+J
スクリプトのON/OFF


スクリプト

AutoHotkeyではキーラベルにスティックが使えません。GetKeyStateで状態は取得できるので、Loopで常に監視しています。


GPDWINPad.ahk

; GPD WIN用スクリプト

; ***XInputモードで使用のこと。***

#SingleInstance, FORCE
SetMouseDelay, 0

DeadMargin := 1 ; スティックの不感帯
SpeedNormal := 0.4 ; 通常時のマウスポインタ移動速度
SpeedSlow := 0.08 ; スローボタンを押したときのマウスポインタ移動速度
WheelWaitNormal := 50 ; 右スティックでのスクロール間隔
WheelWaitSlow := 250 ; スローボタンを押したときの右スティックでのスクロール間隔
SlowButton := "Joy5" ; ポインタの移動やスクロールを遅くするボタン
LClickButton := "Joy1" ; 左クリックに設定するボタン
RClickButton := "Joy2" ; 右クリックに設定するボタン
ShiftButton := "Joy6" ; 他のボタンの機能を変更する修飾ボタン
ButtonWait := 100 ; ボタン押下後に待つ場合の時間

isPause := 0
isLClickButtonDowned := 0
isRClickButtonDowned := 0
isL2ButtonDowned := 0
isR2ButtonDowned := 0
lastClick := A_TICKCOUNT
Gosub, JoyStickInit

Loop
{
while isPause ;PauseがSuspendと組み合わせたときに挙動不審なのでフラグで管理
sleep, 1

Gosub, GetJoyStickState
; ToolTip, X:%stateJoyX% Y:%stateJoyY% Z:%stateJoyZ% U:%stateJoyU% R:%stateJoyR% POV:%stateJoyPOV%

; マウスカーソルの移動
diffX := stateJoyX - defaultJoyX
diffY := stateJoyY - defaultJoyY

coef := GetKeyState(SlowButton,"P") ? SpeedSlow : SpeedNormal
if(Abs(diffX) > DeadMargin && A_TICKCOUNT - lastClick > ButtonWait)
x := diffX * coef
if(Abs(diffY) > DeadMargin && A_TICKCOUNT - lastClick > ButtonWait)
y := diffY * coef
if(x || y)
{
MouseMove, %x%, %Y%,, R
Sleep, 1
}
x := 0
y := 0

; スクロール
diffR := stateJoyR - defaultJoyR
if(Abs(diffR) > DeadMargin)
{
if(diffR < 0)
{
MouseClick, WheelUp
}
Else
{
MouseClick, WheelDown
}
wait := GetKeyState(SlowButton, "P") ? WheelWaitSlow : WheelWaitNormal
Sleep, %wait%
}

diffU := stateJoyU - defaultJoyU
if(diffU > 40){
Send, {Tab}
Sleep, %ButtonWait%
}
if(diffU < -40){
Send, +{Tab}
Sleep, %ButtonWait%
}

; L2, R2
diffZ := stateJoyZ - defaultJoyZ
if(diffZ > 40 && !isL2ButtonDowned){ ;L2 Down
isL2ButtonDowned := 1
Send, {Browser_Back}
}
if(diffZ < -40 && !isR2ButtonDowned){ ;R2 Down
isR2ButtonDowned :=1
Send, {Browser_Forward}
}
if(-10 < diffZ && diffZ < 10 && isL2ButtonDowned) ;L2 Up
isL2ButtonDowned := 0
if(-10 < diffZ && diffZ < 10 && isR2ButtonDowned) ;R2 Up
isR2ButtonDowned := 0

; 方向ボタン
if(stateJoyPOV != -1)
{
if(stateJoyPOV == 0)
Send, {Up}
if(stateJoyPOV == 9000)
Send, {Right}
if(stateJoyPOV == 18000)
Send, {Down}
if(stateJoyPOV == 27000)
Send, {Left}
Sleep, %ButtonWait%
}

; 左クリック
; Joy1 Upで拾えないのでLoop中に記述
If(GetKeyState(LClickButton, "P"))
{
If(ShiftButton())
{
Send, {Enter Down}
while GetKeyState(LClickButton, "P")
Sleep, 1
Send, {Enter Up}
}
else
{
If isLClickButtonDowned = 0
{
Click, LEFT, D
isLClickButtonDowned = 1
lastClick = %A_TICKCOUNT%
}
}
}
else
{
If isLClickButtonDowned = 1
{
Click, LEFT, U
isLClickButtonDowned = 0
}
}

; 右クリック
If(GetKeyState(RClickButton, "P"))
{
if(ShiftButton())
{
Send, {Esc Down}
while GetKeyState(RClickButton, "P")
Sleep, 1
Send, {Esc Up}
}
else
{
If isRClickButtonDowned = 0
{
Click, RIGHT, D
isRClickButtonDowned = 1
}
}
}
else
{
If isRClickButtonDowned = 1
{
Click, RIGHT, U
isRClickButtonDowned = 0
}
}

}
return

JoyStickInit:
Gosub, GetJoyStickState

defaultJoyX := stateJoyX
defaultJoyY := stateJoyY
defaultJoyZ := stateJoyZ
defaultJoyU := stateJoyU
defaultJoyR := stateJoyR
Return

GetJoyStickState:
GetKeyState, stateJoyX, JoyX, P
GetKeyState, stateJoyY, JoyY, P
GetKeyState, stateJoyZ, JoyZ, P
GetKeyState, stateJoyU, JoyU, P
GetKeyState, stateJoyR, JoyR, P
GetKeyState, stateJoyPOV, JoyPOV, P
Return

ShiftButton()
{
global ShiftButton
Return, GetKeyState(ShiftButton, "P")
}

Joy3::
if(ShiftButton())
{
Send, !{Tab}
}
else
{
IfWinActive, ahk_class MultitaskingViewFrame
Send, {Enter}
Else
Send, #{Tab}
}
Return
Joy4::
if(ShiftButton())
{
Send, {LWin}
}
else
{
IfWinActive, ahk_class MultitaskingViewFrame
Send, {Delete}
Else
Click, Middle
Sleep, %ButtonWait%
}
Return
; Start
Joy8::Gosub, JoyStickInit ; スティック初期化
; L3
Joy9::vk1Dsc07B ; 無変換
; R3
Joy10::vk1Csc079 ; 変換

; スクリプト一時停止トグル
#J::
Suspend
isPause := isPause ? 0 : 1
Return


行き当たりばったりで書いたので汚いコードだけど動くから良いよね!





  1. 試用でも機能制限は無いけどお金払うつもりがないのに使い続けるのもアレ 



  2. Window10でWin+Tab押すと出てくるやつ