はじめに
AutoHotkey歴2年にして、それなりに便利な使い方がわかってきました。
どうやら独自の運用方法をしているようですし、布教のためにもと思い、紹介しておくことにしました。
※初心の方はまずこちらからご覧ください。
【連載】なぜAutoHotkeyを使うのか
※最新のオリジナルAutoHotkeyスクリプトはこちら。
https://github.com/ryoheiszk/PortableApps/tree/master/ProgramFiles/AutoHotkey
環境構築
※ 下の記事の要約です。
【連載】AutoHotkeyのインストール・環境構築
以下のツールを用います。
- AutoHotkey(Unicode) - Portable
- VSCode
- AutoHotkey Plus(VSCode拡張)
- Git
AutoHotkey(Unicode) - Portable
かつてはShift-JIS版が主流でしたが、現在はUTF-8 with BOM版でOKです。
Portable版にした理由は環境依存性を極力除きたかったためで、持ち出したときに適応しやすくなります。
VSCode / AutoHotkey Plus
使い始めた頃はメモ帳でコーディングしていましたが、どう考えても不便なのでモダンなエディタに移行しました。
個人的にはこの組み合わせが無難なのではないかと思っています。
デバッガが便利で、MsgBox
でデバッグせずに済むので助かります。
launch.json
は次のように設定するとよいでしょう。
{
"version": "0.2.0",
"configurations": [
{
"type": "ahk",
"request": "launch",
"name": "AutoHotkey Debugger",
"program": "${workspaceRoot}\\AutoHotkey.ahk",
"stopOnEntry": true
}
]
}
※program
を自動生成のものから書き換えています。
後述のディレクトリ構成の場合、実行すべきは常にAutoHotkey.ahk
であるためです。
ただし、こちらの設定はF5
(既定値)によるデバッグに関するものであり、AutoHotkey PlusのDebug Script
の場合は常にアクティブがファイルが実行されるため、上記の設定にして差し支えることはないと思われます。
Git
バージョン管理したいお年頃です。
おすすめのスクリプト
下記のディレクトリ構成であることを前提とします。
※
部分に関して、重要な順に説明します。
root\
├ AutoHotkey.exe
├ ※AutoHotkey.ahk
├ PluginList.ahk
├ Variables.ahk
└ Plugins\
├ ※main.ahk
├ ※edit.ahk
├ ※numpad.ahk
├ ※fn.ahk
├ ※hotstring.ahk
├ ※others.ahk
├ ※git_alias.ahk
├ ※toggle.ahk
├ ※keybd_mouse.ahk
├ ※temp.ahk
├ ※IME.ahk
├ launcher_data.ini
└ bat\
└ batch_file_1.bat
AutoHotkey.ahk
AutoHotkey.ahk
は全スクリプトの核となるファイルですが、こちらは以下の役割としています。
- スクリプト全体の設定
- グローバル変数の定義
- プラグインの自動取り込み
- 共通サブルーチンの定義
1.スクリプト全体の設定
流派は様々ありますが、私は次のような設定にしています。
#Persistent
#SingleInstance, Force
#NoEnv
#UseHook
#InstallKeybdHook
#InstallMouseHook
#HotkeyInterval, 2000
#MaxHotkeysPerInterval, 200
Process, Priority,, Realtime
SendMode, Input
SetWorkingDir %A_ScriptDir%
SetTitleMatchMode, 2
コマンド | 説明 |
---|---|
#Persistent | スクリプトを明示的に常駐させる |
#SingleInstance, Force | 同じスクリプトを再実行した際は、確認なくリロードする |
#NoEnv | 変数の処理においてWindows環境変数の探索をしない(処理速度向上のため) |
#UseHook | RegisterHotkeyを介さず、フックを使用してホットキーを定義する(処理速度向上のため) |
#InstallKeybdHook | キーボードフックを有効化する(デバッグのため) |
#InstallMouseHook | マウスフックを有効化する(デバッグのため) |
#HotkeyInterval, 2000 | 無限ループの検出間隔を設定 |
#MaxHotkeysPerInterval, 200 | この回数以上のホットキーが↑の間隔で行われた場合、無限ループとして警告する |
Process, Priority,, Realtime | プロセス優先度を最高にする |
SendMode, Input | SendコマンドのモードをInputにする(処理速度向上のため) |
SetWorkingDir %A_ScriptDir% | 作業フォルダをAutoHotkey.ahkを含むフォルダとする |
SetTitleMatchMode, 2 | WindowTitleは部分一致検索にする |
2.グローバル変数の定義
グローバル変数はAuto-executeセクションで定義する必要があります。
切り分けたスクリプトで定義する方法がないわけではありませんが、こちらの方が手軽であると思い採用しています。
; 変数の初期化
#Include, %A_ScriptDir%\Variables.ahk
ちなみに、Variables.ahk
は次のようになっています。
(AutoHotkey.ahk
、keybd_mouse.ahk
、toggle.ahk
で利用します。)
keys_all := "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,vkBB,vkBA,vkBC,Space,Tab,Enter,BS,vkF3,vkF4,vk1D,vkF2,vkF0"
toggle := false
3. プラグインの自動取り込み
プラグイン(=切り分けたスクリプトファイル)を、Auto-executeセクションにおいていちいちInclude
するのは、DRY的にもよろしくないため、Plugins
ディレクトリ直下のスクリプトファイルを自動的にInclude
できるようにしておきました。
スクリプト実行時にPluginList.ahk
に一覧が書き込まれ、最後にまとめてInclude
されます。
; プラグインの検出・取り込み
If (search_plugins()) {
Reload
}
search_plugins() {
; Pluginsフォルダ内のAHKスクリプト名を整形してplugin_filesに格納
plugin_files := ""
Loop, %A_ScriptDir%\Plugins\*.ahk {
plugin_files .= "#" . "Include *i %A_ScriptDir%\Plugins\" . A_LoopFileName . "`n"
}
If (plugin_files == "") {
Return 0
}
; Pluginsの変更点を認識
file := FileOpen(A_ScriptDir . "\PluginList.ahk", "r `n", "utf-8")
If (file) {
plugin_list_old := file.Read(file.Length)
file.Close
If (plugin_list_old == plugin_files) {
Return 0
}
}
; plugin_list_oldをplugin_filesに書き換える
file := FileOpen(A_ScriptDir . "\PluginList.ahk", "w `n", "utf-8")
If (!file) {
Return 0
}
file.Write(plugin_files)
file.Close
Return 1
}
; (Auto-exexute Sectionここまで)
#Include, %A_ScriptDir%\PluginList.ahk
4. 共通サブルーチンの定義
切り分けたスクリプト群で自由に使いたい関数はこちらにまとめておきます。
ツールチップ関係
my_tooltip_function(str, delay) {
ToolTip, %str%
SetTimer, remove_tooltip, -%delay%
}
remove_tooltip:
ToolTip
Return
remove_tooltip_all:
SetTimer, remove_tooltip, Off
Loop, 20
ToolTip, , , , % A_Index
Return
カレントディレクトリ取得
get_current_dir() {
explorerHwnd := WinActive("ahk_class CabinetWClass")
If (explorerHwnd) {
for window in ComObjCreate("Shell.Application").Windows {
If (window.hwnd==explorerHwnd)
Return window.Document.Folder.Self.Path
}
}
}
動的なホットキー定義
hotkeys_define(keys, label, OnOff) {
Loop, PARSE, keys, `,
Hotkey, %A_LoopField%, %label%, %OnOff%
Return
}
; キー無効化用ラベル(Hotkeyコマンドでラベルとして指定する)
disable_keys:
Return
次のようにして動的にホットキーを定義できます。
; 変数で指定したキーを無効化する
keys_all := "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,vkBB,vkBA,vkBC,Space,Tab,Enter,BS,vkF3,vkF4,vk1D,vkF2,vkF0"
hotkeys_define(keys_all, "disable_keys", "On")
改行コード除去
rm_crlf(str) {
str := RegExReplace(str, "\n", "")
str := RegExReplace(str, "\r", "")
Return str
}
main.ahk
主要なスクリプトのうち、ファイルを切り分ける程の量でない場合、こちらにまとめます。
英数キー(CapsLock)無効
Ctrl
と入れ替える人は多いようですが、Lock系キーの動作が不安定であるため、AHKでは対応できません。
レジストリの書き換えをすればよい訳ですが、それではレジストリを書き換えられる環境のみで実現できる、環境依存性のあるキー配列となってしまうため、それはしないことにしています。
vkF0::Return
デスクトップフォルダを開く
クイックアクセスよりデスクトップフォルダを開きたいことが多いため、Windowsの既定動作を上書きしています。
#e::Run, %A_Desktop%
音量関連
Fn
キー頼りもまた機種依存的であるため、別途用意しました。
; 単体押下の動作指定
AppsKey::Send,{AppsKey}
; ボリュームを上げる
AppsKey & Up::Send,{Volume_Up 1}
; ボリュームを下げる
AppsKey & Down::Send,{Volume_Down 1}
; ミュート
AppsKey & Left::Send,{Volume_Mute}
ツールチップ表示
本当にコピーできたか、上書き保存できたか、不安なことがよくあるため、ツールチップを表示します。
; コピーした時
OnClipboardChange:
my_tooltip_function("コピー", 300)
Return
; 上書き保存した時
^s::
Send, ^s
my_tooltip_function("上書き保存", 300)
Return
カレントディレクトリのパスを取得
関数はAutoHotkey.ahk
(前述)で定義しています。
^+!p::Clipboard := get_current_dir()
日付入力
Excelの機能ですが、通常利用できるようにしました。
^vkBB::
FormatTime, dateStr, , yyyy-MM-dd
Send, {vkF2}{vkF3}%dateStr%
Return
最初のテキストフィールドに移動[Chromium]
Cent Browserに標準装備されている機能ですが、これが便利なのでAHKでポータブル化しました。
ポータブル化が目的であるため、意地でもブックマークレットは使いません。
アドレスバーにjavascript:
として、かんたんなjsコードを流し込みます。
正直使っておらず自己満ではありますが、技術的には面白いため掲載しました。
#If, WinActive("ahk_exe chrome.exe")
^+u::
; ホールド対策
KeyWait, Ctrl, Up
KeyWait, Shift, Up
stash := ClipBoardAll
ClipBoard := "const element=document.querySelector(""input[type='text'],input[type='search']"");element.select();element.scrollIntoView();"
ClipWait, 1
Send, ^l
; "javascript:"は貼り付けできない
Send, {vkF2}{vkF3}javascript:
Sleep, 100
Send, ^v
Sleep, 100
Send, {Enter}
Sleep, 10
ClipBoard := stash
stash := ""
Return
#If
edit.ahk
AHKから離れられない理由の1つです。
超高速文字編集を可能にします。(当社比)
私の性格が反映されている配列になっています。
; ↑
vk1D & i::Send, {Blind}{Up}
; ↓
vk1D & k::Send, {Blind}{Down}
; ←
vk1D & j::Send, {Blind}{Left}
; →
vk1D & l::Send, {Blind}{Right}
; Home
vk1D & h::Send, {Blind}{Home}
; End
vk1D & vkBB::Send, {Blind}{End}
; ↑↑↑↑
vk1D & u::Send, {Blind}{Up 4}
; ↓↓↓↓
vk1D & ,::Send, {Blind}{Down 4}
; →→→→
vk1D & .::Send, {Blind}{Right 4}
; ←←←←
vk1D & m::Send, {Blind}{Left 4}
; Enter
vk1D & Space::Send, {Blind}{Enter}
; Backspace
vk1D & n::Send, {Blind}{Backspace}
; Delete
vk1D & /::Send,{Blind}{Delete}
; 行挿入(Ctrl押下状況により、挿入位置を前後で選択)
vk1D & Enter::
If (GetKeyState("Ctrl", "P")) {
Send, {Up}{End}{Enter}
} Else {
Send, {End}{Enter}
}
Return
; 半角英数
vk1D & vkF2::Send, {vkF2}{vkF3}
numpad.ahk
出先PCで常に半角数字を入力する
AHKを持ち出したときに、利用するPCの設定によって数字の半角/全角が違ってしまうことを防ぐ。
既定値は大抵、テンキー入力の場合は日本語入力でも半角であることを利用
1::Send, {Numpad1}
2::Send, {Numpad2}
3::Send, {Numpad3}
4::Send, {Numpad4}
5::Send, {Numpad5}
6::Send, {Numpad6}
7::Send, {Numpad7}
8::Send, {Numpad8}
9::Send, {Numpad9}
0::Send, {Numpad0}
左手テンキー
無変換
+左ホームポジション
でテンキー(っぽい何か)を扱えます。
とても便利です。
テンキー付きキーボードに完全勝利しました。
; 修飾キーと無変換の組み合わせのトリガーを有効にする
#If, !(GetKeyState("Ctrl", "P")
|| GetKeyState("Shift", "P")
|| GetKeyState("Alt", "P")
|| GetKeyState("LWin", "P"))
vk1D & z::Send, 0
vk1D & x::Send, 1
vk1D & c::Send, 2
vk1D & v::Send, 3
vk1D & s::Send, 4
vk1D & d::Send, 5
vk1D & f::Send, 6
vk1D & w::Send, 7
vk1D & e::Send, 8
vk1D & r::Send, 9
vk1D & b::Send, =
vk1D & a::Send, *
vk1D & q::Send, {NumpadDiv}
vk1D & g::Send, {+}
vk1D & t::Send, -
vk1D & Tab::Send, {Enter}
vk1D & LWin::Send, .
#If
頭に何やら書いていますが、不便を感じるまでは内部のスッキリしている部分のみでOKです。
拡張性の都合により、条件を付与しています。
テンキーのマクロボード化(未設定)
左手テンキーを実現したため、テンキーをマクロボードとしたいところです。
まだ内容を考えていないため、とりあえず無効化してテンプレとしています。
Numpad1::Return
Numpad2::Return
Numpad3::Return
Numpad4::Return
Numpad5::Return
Numpad6::Return
Numpad7::Return
Numpad8::Return
Numpad9::Return
NumpadDot::Return
NumpadAdd::Return
NumpadSub::Return
NumpadMult::Return
NumpadDiv::Return
NumpadEnter::Return
fn.ahk
HHKB的にFn
キーを近づけます。
副次的に、Fn
キーが全て空くためマクロキーとして活用できます。
Alt
+F4
↓
無変換
+Alt
+4
vk1D & vkF3::Esc
vk1D & vkF4::Esc
vk1D & 1::F1
vk1D & 2::F2
vk1D & 3::F3
vk1D & 4::F4
vk1D & 5::F5
vk1D & 6::F6
vk1D & 7::F7
vk1D & 8::F8
vk1D & 9::F9
vk1D & 0::F10
vk1D & -::F11
vk1D & ^::F12
vk1D & \::F13
hotstring.ahk
型だけ用意しました。
Hotstringは頻繁に抜けるため、あまり使いたくありません。
AHKがシングルスレッド動作(疑似マルチスレッド)であることが関係していると、勝手に予想しています。
#Hotstring *C Z
; C: 大文字小文字を区別する
; *: 終了文字無しで発動する
; Z : 発動時点でキー入力のバッファをクリアする
; R : 特殊キーをそのまま入力する(個別設定)
; 設定はここから
::teststring::
Send, It's test.
Return
others.ahk
個別のターゲットに対する、細々とした処理を記述します。
Netflix
Netflixで早送りする際、矢印を連打するとサムネイルだけ先に進むようになるのがうっとうしいので(伝われ)、その対策としてこちらを用意しました。
#If, WinActive("Netflix")
~Right::
~Left::
Send, {Space 2}
Return
#If
git_alias.ahk
複数のPCで同じエイリアスを使いたいため、GitのエイリアスはAHKに統合した方が都合がいい気がします。
(他にいい方法があればお教えください。)
#Hotstring C O Z
; C : 大文字小文字の区別
; O : 最後に終了文字を入力しない
; Z : 発動時点でキー入力のバッファをクリアする
; R : 特殊キーをそのまま入力する(個別設定)
; 基本
::gia::git add .
::giac::git commit -a -m ""{Left}
::gibr::git branch{Space}
::gibrd::git branch -d{Space}
::gic::git commit -m ""{Left}
::gica::git commit --amend -m ""{Left}
::gican::git commit --amend --no-edit
::gico::git checkout{Space}
::gicob::git checkout -b{Space}
::gicon::git config --global{Space}
::gist::git stash save --include-untracked ""{Left}
::gistl::git stash list
:R:gistp::git stash pop stash@{}
::gists::git stash show
::gireb::git rebase{Space}
::girebi::git rebase -i HEAD~
::giref::git reflog -7
::giress::git reset --soft HEAD
::giresh::git reset --hard HEAD
::gil::git log --oneline -5
::gim::git merge --no-ff{Space}
::gis::git status{Space}
; 応用
::gishbr::git show-branch | grep '*'
; :R:gishbr::git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -1 | awk -F'[]~^[]' '{print $2}'
::gigr::git log --graph --date=short --decorate=short --pretty=format:'%Cgreen%h %Creset%cd %Cblue%cn %Cred%d %Creset%s'
toggle.ahk
自分のスクリプトの中で、1,2を争う程便利だと思っています。
VSCodeのCtrl
+K
→何か
という2段階のショートカットのアイデアを得て、それをAHKで実装しました。
具体的には例えば、
-
変換
+G
→G
で選択文字列をGoogle検索 -
変換
+G
→L
でランチャーが起動して、launcher_data.ini
に登録した動作を実行する
などがあります。
しかし、特大ボリュームで説明が大変なので、説明は省きます。
個人ブログの方で連載が追いついたら、こちらにリンクを張っておきます。
(以下、toggle.ahk
を細分化して扱っています。)
修飾キー単体動作の定義
vk1C::Return
押下時間によって、変換キーと無効を切り替えてもいいかもしれません。
コンビネーションキーとして利用する場合は、比較的長時間押下していることになるためです。
ホットキーが発火していない場合は組み込み変数A_ThisHotkey
に変化がないことから、変換キーをDown
したときとUp
したときのA_ThisHotkey
が一致していれば変換キーとして動作する、としてもよさそうです。
今のところ変換キーを使いたいことはあまりないため、放置しています。
プライマリキーの設定
冗長で気に入らないので、何かいい案があればお教えください。
#If, GetKeyState("vk1C", "P") == true
a::
b::
c::
d::
e::
f::
g::
h::
i::
j::
k::
l::
m::
n::
o::
p::
q::
r::
s::
t::
u::
v::
w::
x::
y::
z::
toggle := A_ThisHotkey
toggle_activation(toggle)
SetTimer, watch_hotkey_done, 50
hotkeys_define(keys_all, "disable_keys", "On")
Return
#If
セカンダリキーの設定
例えば変換
→G
としてから、やっぱりやめたいとなったときにESC
で入力を破棄できるようにします。
#If, toggle != false
Esc::SetTimer, toggle_deactivation, Off
#If
AHK関連
変換
+A
の世界線です。(以下同様)
例えば変換
+A
→D
ならAHKの公式ドキュメントをブラウザで開きます。
#If, toggle == "a"
; コンパイラを開く
c::Run, %A_ScriptDir%/Compiler/Ahk2Exe.exe
; Documentation
d::Run, https://www.autohotkey.com/docs/AutoHotkey.htm
; KeyList(日本語Wiki)
k::Run, http://ahkwiki.net/KeyList
; keybd_mouse.ahk
m::
Gosub, toggle_deactivation
Gosub, keybd_mouse
Return
; リロード
r::Reload
; 実行ファイルのフォルダを開く
o::Run, %A_ScriptDir%
; Wiki(日本語)を開く
h::Run, http://ahkwiki.net/Top
; WindowSpy
w::Run, %A_ScriptDir%\AutoHotkey.exe %A_ScriptDir%\WindowSpy.ahk
文字編集
正直使っていないですが、拡張性が無限大なので書いておきました。
例えば、「上の行の偶数番目の文字を削除する」のような設定も自由にできます。
#If, toggle == "e"
; 1行コピー
c::Send, {Home}+{End}^c{Right}
; 1行削除
e::
Send, {End}+{Home}{Delete}
Goto, toggle_deactivation
Return
; 1行削除(キャレット~末尾)
Delete::Send, +{End}{Delete}
; 1行削除(先頭~キャレット)
Backspace::Send, +{Home}{Backspace}
GUI関連
かなり便利です。
#If, toggle == "g"
DeepL検索
d::
; 多重起動防止
If (WinExist("ahk_class AutoHotkeyGUI")) {
Return
}
stash := ClipboardAll
Clipboard :=
Send, ^c
ClipWait, 0.05
clip := Clipboard
Clipboard := stash
clip := rm_crlf(clip)
Gui, Add, Text, , 日本語→英語
Gui, Add, Text, , (Shift)英語→日本語
Gui, Add, Edit, v_str_deepl w380, %clip%
Gui, Add, Button, Default, Translate
Gui, Show, Center w400, DeepL
Send, {vkF2}
clip := ""
Return
ButtonTranslate:
Gui, Submit
; Shift押下時はja->en
If GetKeyState("Shift", "P") {
Run, https://www.deepl.com/translator#ja/en/%_str_deepl%
; 直打ちならばen->ja
} Else {
Run, https://www.deepl.com/translator#en/ja/%_str_deepl%
}
4GuiEscape:
4GuiClose:
Gui, Destroy
Return
新しいブランクファイルを作成
超便利です。
通常はWindowsエクスプローラ上で新規作成
→テキストファイル
などとして、.txt
を削除するのだろうと思いますが、この方法なら
変換
+G
↓
L
↓
(ファイル名)
↓
Enter
で自由なファイルを作成できます。
f::
; エクスプローラがアクティブでなければ中断
If (!WinActive("ahk_class CabinetWClass")) {
MsgBox, エクスプローラがアクティブではありません
Return
}
; 現在表示中のディレクトリ
current_dir := get_current_dir()
; ファイルを生成(重複しない名前)
Gui, Add, Edit, v_str_filename w380
Gui, Add, Button, Default, Append
Gui, Show, Center w400, ファイル名
Send, {vkF2}{vkF3}
Return
ButtonAppend:
Gui, Submit
FileAppend, , %current_dir%\%_str_filename%
3GuiEscape:
3GuiClose:
Gui, Destroy
Return
Google検索
g::
; プライマリキーとセカンダリキーが同じ場合に必要
Gosub, toggle_deactivation
; 多重起動防止
If (WinExist("ahk_class AutoHotkeyGUI")) {
Return
}
stash := ClipboardAll
Clipboard :=
Send, ^c
ClipWait, 0.05
clip := Clipboard
Clipboard := stash
clip := rm_crlf(clip)
Gui, Add, Edit, v_str_google w380, %clip%
Gui, Add, Button, Default, Search
Gui, Show, Center w400, Google
Send, {vkF2}
clip := ""
Return
ButtonSearch:
Gui, Submit
Run, https://www.google.co.jp/search?q=%_str_google%
2GuiEscape:
2GuiClose:
Gui, Destroy
Return
ランチャーを起動
/Plugins/launcher_data.ini
の記述をRun
できます。
Run
はWebページを開いたり、ファイルを実行したりできる便利なコマンドです。
もちろんPowerShellスクリプト等も実行できるため、つまるところAHKの守備範囲を超えたすべての動作を定義できます。
; def:launcher
l::
; 多重起動防止
If (WinExist("ahk_class AutoHotkeyGUI")) {
Return
}
launcher_head:
Gui, Add, Edit, v_str_launcher Lowercase
Gui, Add, Button, Default, Launch
Gui, Show, Center AutoSize, Launcher
Send, {vkF2}{vkF3}
Return
ButtonLaunch:
Gui, Submit
IniRead, val, %A_ScriptDir%\Plugins\launcher_data.ini, Scripts, %_str_launcher%
; 一致するレコードがなければval="ERROR"となることを利用する
If (val != "ERROR") {
Run, %val%
} Else {
GoSub, GuiClose
Goto, launcher_head
}
GuiEscape:
GuiClose:
Gui, Destroy
Return
[Scripts]
codeahk = F:\Desktop\Tools\Source\AutoHotkey\ahk.code-workspace
fstartup = shell:startup
notion = https://www.notion.so
「GUI関連」を閉じる
#If
使用するサブルーチン
; セカンダリキー入力待ちにし、タイムアウトをSetTimerする
toggle_activation(toggle) {
time_limitation := 2000
SetTimer, toggle_deactivation, -%time_limitation%
my_tooltip_function("vk1C + " . toggle . " -> ?", time_limitation)
}
toggle_deactivation:
toggle := false
my_tooltip_function("toggle == false", 1000)
hotkeys_define(keys_all, "disable_keys", "Off")
SetTimer, toggle_deactivation, Off
SetTimer, watch_hotkey_done, Off
Return
; セカンダリキーの入力があった場合、toggleをfalseにし、SetTimerしたタイムアウト設定を解除する
watch_hotkey_done:
new_ThisHotkey := A_ThisHotkey
; toggleにはプライマリキー送信時のA_ThisHotkeyが格納されている
; 何らかのホットキー(つまりセカンダリキー)が実行されたとき、A_ThisHotkeyが書き換わることを利用する
If (new_ThisHotkey != toggle)
Goto, toggle_deactivation
Return
keybd_mouse.ahk
キーボードでマウスを操作します。
なくてもいいですが、たまに便利な場面があります。
(文字入力中にマウスカーソルが邪魔な場合や、無線キーボードしか手元にない場合など)
MouseMove
ではキー長押しのレスポンスが遅いため、While
で強引に処理しています。
しかし、AHKがシングルスレッド動作であるせいでカクつくのが悩みです。
Critical
で処理の乗っ取りを防ぐために、切り分けてある関数群をWhile
内にベタ打ちする方法も検討中です。
こちらも特大ボリュームなので、ここでの解説は避けます。
keybd_mouse:
; キー設定///////////////////////////////////
exit_this := "r" ; keybd_mouse終了
mouse_up := "e" ; ↑
mouse_down := "d" ; ↓
mouse_left := "s" ; ←
mouse_right := "f" ; →
mouse_LB := "j" ; 左クリック
mouse_RB := "l" ; 右クリック
mouse_MB := "vkBC" ; 中クリック
scroll_up := "i" ; 上スクロール
scroll_down := "k" ; 下スクロール
accel_key := "o" ; カーソル加速
decel_key := "vkBB" ; カーソル減速
default_speed := 4 ; 規定のカーソル移動速度
accel_vol := 16 ; accelKey押下時のカーソル移動速度の増加量
slow_vol := 1 ; decel_key押下時のカーソル移動速度
move_ratio := 16/9 ; 縦横移動量倍率
;////////////////////////////////////////////
hotkeys_define(keys_all, "disable_keys", "On")
Hotkey, %exit_this%, toggle_keybd_mouse
Gosub, toggle_keybd_mouse
SetTimer, mouse_button_checker, 100
While (toggle_keybd_mouse == true) {
; 速度設定///////////////////////////
speed := default_speed
move_X := 0
move_Y := 0
If (GetKeyState(accel_key, "P"))
speed += accel_vol
If (GetKeyState(decel_key, "P"))
speed := slow_vol
;////////////////////////////////////
; 移動方向設定///////////////////////
If (GetKeyState(mouse_up, "P"))
move_Y += speed
If (GetKeyState(mouse_down, "P"))
move_Y += -speed
If (GetKeyState(mouse_left, "P"))
move_X += -speed * move_ratio
If (GetKeyState(mouse_right, "P"))
move_X += speed * move_ratio
;////////////////////////////////////
; 移動///////////////////////////////
MouseMove, move_X, -move_Y, 0, R
; ///////////////////////////////////
}
SetTimer, mouse_button_checker, Off
hotkeys_define(keys_all, "disable_keys", "Off")
Hotkey, %exit_this%, toggle_keybd_mouse, Off
Return
;////////////////////////////////////////////
;サブルーチン////////////////////////////////
;////////////////////////////////////////////
; トグル/////////////////////////////////////
toggle_keybd_mouse:
toggle_keybd_mouse := !toggle_keybd_mouse
my_tooltip_function("マウスモード: " . (toggle_keybd_mouse == true ? "ON" : "OFF"), 1000)
; タスクバーの高さを取得
WinGetPos, , , , taskbarHeight, ahk_class Shell_TrayWnd
; 右下にツールチップ
CoordMode, ToolTip, Screen
ToolTip, % "マウスモード: " . (toggle_keybd_mouse == true ? "ON" : "OFF")
,A_ScreenWidth, A_ScreenHeight - (taskbarHeight + 21), 2 ; ツールチップの高さ: 20
CoordMode, ToolTip, Relative
; OFFにするならそのツールチップは指定時間後に削除
If (toggle_keybd_mouse == false)
SetTimer, remove_tooltip_all, -500
Return
;////////////////////////////////////////////
; マウス/////////////////////////////////////
mouse_button_checker:
; マウス/////////////////////////////
keybd_mouse_click(mouse_LB, "L")
keybd_mouse_click(mouse_MB, "M")
keybd_mouse_click(mouse_RB, "R")
keybd_mouse_scroll(scroll_up, "Up", accel_key, decel_key, accel_vol)
keybd_mouse_scroll(scroll_down, "Down", accel_key, decel_key, accel_vol)
;////////////////////////////////////
Return
keybd_mouse_click(key, button) {
;引数について////////////////////////
;// key:= "j", button:= "L" の場合 //
;// j を押すと LButtonが送信される //
;////////////////////////////////////
; 変数%button%B_downの値を引き継ぐ
; %button%B_downは直前に押したか離したかを記録
Global
; 上記変数を用いた連打対策///////////
; 押すとき
If (GetKeyState(key, "P") == true) {
If (%button%B_down != true) {
Send, {Blind}{%button%Button Down}
%button%B_down := true
; 押下したら一瞬カーソルを止める
Sleep, 150
}
; 離すとき
} Else {
If (%button%B_down == true) {
Send, {Blind}{%button%Button Up}
%button%B_down := false
}
}
;////////////////////////////////////
}
keybd_mouse_scroll(key, scroll, accel_key, decel_key, accel_vol) {
While (GetKeyState(key, "P")) {
; スクロール中はカーソルを固定
If (GetKeyState(key, "P"))
Send, {Blind}{Wheel%scroll%}
; スクロール速度の設定
scroll_wait := 100
If (GetKeyState(accel_key, "P"))
scroll_wait -= accel_vol * 5
If (GetKeyState(decel_key, "P"))
scroll_wait := 200
Sleep, scroll_wait
}
}
;////////////////////////////////////////////
temp.ahk
思いついたコードのテストをする場所です。
ちょっと試したいだけならAutoHotkey Plus
を活かしつつ別AHKファイルに書く方が便利ですが、短期間継続的に試したいコードがあれば、temp.ahk
に書くのが便利だろうと思います。
IME.ahk
IME.ahk
は有志が作成したプラグインです。
あまり依存関係を作りたくないため使用は避けていますが、いざというときのために配備しておきました。
管理者権限の付与
タスクマネージャその他、管理者権限を必要とするプログラム上でAHKを動作させるためには、AHK自体に管理者権限を付与する必要があります。
下記を参照されるとよいでしょう。
https://qiita.com/ryoheiszk/items/97618dc67360c0a1d963
まとめ
ここまでカスタマイズしてしまうと、Linuxアレルギーな副作用が生じますので、あまりおすすめできません。
Qiitaでは、備忘録、またエンジニア向けというつもりで説明を省いていますが、個人ブログの方ではしっかり説明しようと思っています。
遊びに来てください。
別のWindowsマシンで即時にAHKその他常駐ソフト環境を展開する方法があります。
Linuxにおけるdotfiles相当の手法で、そのPCの環境を汚すことなく、30秒程度で設定可能です。
文章による解説が困難であったため動画となっていますが、視聴後試されることをおすすめします。