AutoHotkeyでWindowsの操作を効率化
AutoHotkey
「AutoHotkey」を使えば、Windowsのキーボード操作をスクリプトでカスタマイズできます。
↑の画像は、タスクトレイのやつです(スクリプトとキーボード操作の書き換えなのでスクリーンレコードでは示しづらい……)。
以下はAutoHotkeyの日本語のWikiです。
例
ブラウザ
検索エンジンをカスタマイズしたり、URL直打ちを多用していると、アドレスバーに移ったときにはIMEがオフになっていたほうがストレスが無いです。
入力キー | 効果 | 備考 |
---|---|---|
「Ctrl」+「l(エル)」 | 「Ctrl」+「l(エル)」 & IMEオフ | アドレスバーフォーカス時 |
「Ctrl」+「t」 | 「Ctrl」+「t」 & IMEオフ | 新しいタブを開いた時 |
以下はChromeの例ですが、スクリプトを書き換えれば、他のブラウザにも対応可能です。
スクリプト
#IfWInActive, ahk_exe chrome.exe
^l::
Send ^l
Sleep 100
IME_SET(0)
Return
^t::
Send ^t
Sleep 100
IME_SET(0)
Return
#IfWinActive
「Alt」+「Tab」のタスク切り替えを便利に
タスク切り換え(「Alt」+「Tab」)は1日の間に何度も行います。そのたびにホームポジションから離れてしまうのはもったいないです。
下記の設定をすれば、ホームポジションから離れずに右手のみでタスク切り換え可能になります。もちろん、従来の「Alt」+「Tab」もそのまま使えます。
入力キー | 効果 |
---|---|
「変換キー」2連打 | 「Alt」+「Tab」 |
「カタカナひらがなローマ字キー」2連打 | 「Alt」+「Tab」 |
上記の 『2連打』か『「Alt」+「Tab」』を押してタスク切り替えが表示されている間は、
入力キー | 効果 |
---|---|
「h」 | 「Left」 |
「j」 | 「Down」 |
「k」 | 「Up」 |
「l」 | 「Right」 |
というVim風の割り当てです。
キーボードによっては「変換キー」と「カタカナひらがなローマ字キー」が押し間違えやすいため、両方に設定しています。
スクリプト
IsAltTabMenu := false
!Tab::
Send !^{Tab}
IsAltTabMenu := true
return
; カタカナひらがなローマ字キー2連打でAltTabMenuキーとして割当
vkF2::
If (A_PriorHotKey == A_ThisHotKey and A_TimeSincePriorHotkey < 1000){
Send !^{Tab}
IsAltTabMenu := true
}
return
; 変換キー2連打でAltTabMenuキーとして割当
vk1C::
If (A_PriorHotKey == A_ThisHotKey and A_TimeSincePriorHotkey < 1000){
Send !^{Tab}
IsAltTabMenu := true
}
return
#If (IsAltTabMenu)
h::Send {Left}
j::Send {Down}
k::Send {Up}
l::Send {Right}
Enter::
Send {Enter}
IsAltTabMenu := false
Return
Space::
Send {Space}
IsAltTabMenu := false
Return
#If
いろいろ開いたりフォーカスしたり
タスクバーにピン留めすれば、「Windows」+「1」とかで起動したり、「Windows」+「s」とかランチャーで素早くアプリを開くことができます。また、前項目のタスク切り替えも楽です。
ただ、本当によく開くものについては、もっと早く、もっと覚えやすくして開きたいです。
下記の設定をすれば、左手だけで、よく使うものを素早く開いたり、タスク切り替え画面を経由せずフォーカスします。
入力キー | 効果 |
---|---|
「無変換キー」+「b」 | ブラウザを開く or ブラウザにフォーカス |
「無変換キー」+「w」 | ターミナルにフォーカス |
「無変換キー」+「e」 | Tablacus Explorer を開く or Tablacus Explorerにフォーカス |
「無変換キー」+「re」 | AutoHotkeyのスクリプト再読み込み |
「無変換キー」+「f」 | Fit Winの起動 |
最後の「AutoHotkeyのスクリプト再読み込み」は、スクリプトを書き換えているときによく使うので登録しておくと良いです。
スクリプト
Run の後のパスは適宜変更すること。
IsOpenChrome() {
Process, Exist, chrome.exe
if ErrorLevel<>0
WinActivate, ahk_exe chrome.exe
Else {
Run,C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
Sleep 3000
}
}
; 無変換キー + b, w, re, e, f
vk1D::
Input,MyCommands,I T1 L2, {Esc},b,w,re,e,f
If MyCommands = b
{
IsOpenChrome()
} Else If MyCommands = w
{
WinActivate, ahk_exe mintty.exe
} Else If MyCommands = re
{
Reload
} Else If MyCommands = e
{
; tablacusexplorer を開く
Run, D:\tablacusexplorer\TE64.exe
} Else If MyCommands = f
{
Run,D:\fitwin\fitwin.exe
}
return
ターミナル
よくあるWSL、WSL2のVimのための設定です。
入力キー | 効果 | 備考 |
---|---|---|
「Esc」 | IMEオフにしてから「Esc」 | Vimのため |
「Ctrl」+「[」 | IMEオフにしてから「Esc」 | Vimのため |
「Ctrl」+「o」 | IMEオフにしてから「Ctrl」+「o」 | Vimの挿入ノーマルモードため |
「Ctrl」+「y」 | IMEオフにしてから「Ctrl」+「y」 | Vimのemmetのため |
スクリプト
#IfWInActive, ahk_exe mintty.exe
Esc::
getIMEMode := IME_GET()
if (getIMEMode = 1) {
IME_SET(0)
Send {Esc}
} else {
Send {Esc}
}
return
^[::
getIMEMode := IME_GET()
if (getIMEMode = 1) {
Send {Esc}
Sleep 1 ; wait 1 ms (Need to stop converting)
IME_SET(0)
Send {Esc}
} else {
Send {Esc}
}
return
^o:: ; 挿入ノーマルモードに入るときもIMEオフ
getIMEMode := IME_GET()
if (getIMEMode = 1) {
Sleep 1 ; wait 1 ms (Need to stop converting)
IME_SET(0)
Send ^o
} else {
Send ^o
}
return
^y:: ; emmetで次の入力をするためにIMEオフ
getIMEMode := IME_GET()
if (getIMEMode = 1) {
Sleep 1 ; wait 1 ms (Need to stop converting)
IME_SET(0)
Send ^y
} else {
Send ^y
}
return
#IfWinActive
⚠注意
途中にあるIME_GET()
などはこちらの関数を使用しています。
また、IME側で変換キーなどの割り当てを行わないように設定しています。
スクリプト全体
wikiから持ってきたIME_GET()
などの関数のコメントは仕様が書いてあるためそのまま残しています。
スクリプト
#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.
; Auto execute section is the region before any return/hotkey
; For Terminal/Vim
GroupAdd Terminal, ahk_class PuTTY
GroupAdd Terminal, ahk_class CASCADIA_HOSTING_WINDOW_CLASS
GroupAdd TerminalVim, ahk_group Terminal
GroupAdd TerminalVim, ahk_class Vim
;-----------------------------------------------------------
; IMEの状態の取得
; WinTitle="A" 対象Window
; 戻り値 1:ON / 0:OFF
;-----------------------------------------------------------
IME_GET(WinTitle="A") {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
return DllCall("SendMessage"
, UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
, UInt, 0x0283 ;Message : WM_IME_CONTROL
, Int, 0x0005 ;wParam : IMC_GETOPENSTATUS
, Int, 0) ;lParam : 0
}
;-----------------------------------------------------------
; IMEの状態をセット
; SetSts 1:ON / 0:OFF
; WinTitle="A" 対象Window
; 戻り値 0:成功 / 0以外:失敗
;-----------------------------------------------------------
IME_SET(SetSts, WinTitle="A") {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
return DllCall("SendMessage"
, UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
, UInt, 0x0283 ;Message : WM_IME_CONTROL
, Int, 0x006 ;wParam : IMC_SETOPENSTATUS
, Int, SetSts) ;lParam : 0 or 1
}
;===========================================================================
; IME 入力モード (どの IMEでも共通っぽい)
; DEC HEX BIN
; 0 (0x00 0000 0000) かな 半英数
; 3 (0x03 0000 0011) 半カナ
; 8 (0x08 0000 1000) 全英数
; 9 (0x09 0000 1001) ひらがな
; 11 (0x0B 0000 1011) 全カタカナ
; 16 (0x10 0001 0000) ローマ字半英数
; 19 (0x13 0001 0011) 半カナ
; 24 (0x18 0001 1000) 全英数
; 25 (0x19 0001 1001) ひらがな
; 27 (0x1B 0001 1011) 全カタカナ
; ※ 地域と言語のオプション - [詳細] - 詳細設定
; - 詳細なテキストサービスのサポートをプログラムのすべてに拡張する
; が ONになってると値が取れない模様
; (Google日本語入力βはここをONにしないと駄目なので値が取れないっぽい)
;-------------------------------------------------------
; IME 入力モード取得
; WinTitle="A" 対象Window
; 戻り値 入力モード
;--------------------------------------------------------
IME_GetConvMode(WinTitle="A") {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
return DllCall("SendMessage"
, UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
, UInt, 0x0283 ;Message : WM_IME_CONTROL
, Int, 0x001 ;wParam : IMC_GETCONVERSIONMODE
, Int, 0) ;lParam : 0
}
;-------------------------------------------------------
; IME 入力モードセット
; ConvMode 入力モード
; WinTitle="A" 対象Window
; 戻り値 0:成功 / 0以外:失敗
;--------------------------------------------------------
IME_SetConvMode(ConvMode,WinTitle="A") {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
return DllCall("SendMessage"
, UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
, UInt, 0x0283 ;Message : WM_IME_CONTROL
, Int, 0x002 ;wParam : IMC_SETCONVERSIONMODE
, Int, ConvMode) ;lParam : CONVERSIONMODE
}
;===========================================================================
; IME 変換モード (ATOKはver.16で調査、バージョンで多少違うかも)
; MS-IME 0:無変換 / 1:人名/地名 / 8:一般 /16:話し言葉
; ATOK系 0:固定 / 1:複合語 / 4:自動 / 8:連文節
; WXG / 1:複合語 / 2:無変換 / 4:自動 / 8:連文節
; SKK系 / 1:ノーマル (他のモードは存在しない?)
; Googleβ / 8:ノーマル
;------------------------------------------------------------------
; IME 変換モード取得
; WinTitle="A" 対象Window
; 戻り値 MS-IME 0:無変換 1:人名/地名 8:一般 16:話し言葉
; ATOK系 0:固定 1:複合語 4:自動 8:連文節
; WXG4 1:複合語 2:無変換 4:自動 8:連文節
;------------------------------------------------------------------
IME_GetSentenceMode(WinTitle="A") {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
return DllCall("SendMessage"
, UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
, UInt, 0x0283 ;Message : WM_IME_CONTROL
, Int, 0x003 ;wParam : IMC_GETSENTENCEMODE
, Int, 0) ;lParam : 0
}
;----------------------------------------------------------------
; IME 変換モードセット
; SentenceMode
; MS-IME 0:無変換 1:人名/地名 8:一般 16:話し言葉
; ATOK系 0:固定 1:複合語 4:自動 8:連文節
; WXG 1:複合語 2:無変換 4:自動 8:連文節
; WinTitle="A" 対象Window
; 戻り値 0:成功 / 0以外:失敗
;-----------------------------------------------------------------
IME_SetSentenceMode(SentenceMode,WinTitle="A") {
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
return DllCall("SendMessage"
, UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hwnd)
, UInt, 0x0283 ;Message : WM_IME_CONTROL
, Int, 0x004 ;wParam : IMC_SETSENTENCEMODE
, Int, SentenceMode) ;lParam : SentenceMode
}
;---------------------------------------------------------------------------
; IMEの種類を選ぶかもしれない関数
;==========================================================================
; IME 文字入力の状態を返す
; (パクリ元 : http://sites.google.com/site/agkh6mze/scripts#TOC-IME- )
; 標準対応IME : ATOK系 / MS-IME2002 2007 / WXG / SKKIME
; その他のIMEは 入力窓/変換窓を追加指定することで対応可能
;
; WinTitle="A" 対象Window
; ConvCls="" 入力窓のクラス名 (正規表現表記)
; CandCls="" 候補窓のクラス名 (正規表現表記)
; 戻り値 1 : 文字入力中 or 変換中
; 2 : 変換候補窓が出ている
; 0 : その他の状態
;
; ※ MS-Office系で 入力窓のクラス名 を正しく取得するにはIMEのシームレス表示を
; OFFにする必要がある
; オプション-編集と日本語入力-編集中の文字列を文書に挿入モードで入力する
; のチェックを外す
;==========================================================================
IME_GetConverting(WinTitle="A",ConvCls="",CandCls="") {
;IME毎の 入力窓/候補窓Class一覧 ("|" 区切りで適当に足してけばOK)
ConvCls .= (ConvCls ? "|" : "") ;--- 入力窓 ---
. "ATOK\d+CompStr" ; ATOK系
. "|imejpstcnv\d+" ; MS-IME系
. "|WXGIMEConv" ; WXG
. "|SKKIME\d+\.*\d+UCompStr" ; SKKIME Unicode
. "|MSCTFIME Composition" ; Google日本語入力
CandCls .= (CandCls ? "|" : "") ;--- 候補窓 ---
. "ATOK\d+Cand" ; ATOK系
. "|imejpstCandList\d+|imejpstcand\d+" ; MS-IME 2002(8.1)XP付属
. "|mscandui\d+\.candidate" ; MS Office IME-2007
. "|WXGIMECand" ; WXG
. "|SKKIME\d+\.*\d+UCand" ; SKKIME Unicode
CandGCls := "GoogleJapaneseInputCandidateWindow" ;Google日本語入力
ControlGet,hwnd,HWND,,,%WinTitle%
if (WinActive(WinTitle)) {
ptrSize := !A_PtrSize ? 4 : A_PtrSize
VarSetCapacity(stGTI, cbSize:=4+4+(PtrSize*6)+16, 0)
NumPut(cbSize, stGTI, 0, "UInt") ; DWORD cbSize;
hwnd := DllCall("GetGUIThreadInfo", Uint,0, Uint,&stGTI)
? NumGet(stGTI,8+PtrSize,"UInt") : hwnd
}
WinGet, pid, PID,% "ahk_id " hwnd
tmm:=A_TitleMatchMode
SetTitleMatchMode, RegEx
ret := WinExist("ahk_class " . CandCls . " ahk_pid " pid) ? 2
: WinExist("ahk_class " . CandGCls ) ? 2
: WinExist("ahk_class " . ConvCls . " ahk_pid " pid) ? 1
: 0
SetTitleMatchMode, %tmm%
return ret
}
;-----------------------------------------------------------
; ターミナル以外でもエスケープ設定
; ^[::
; Send {Esc}
; Return
IsOpenChrome() {
Process, Exist, chrome.exe
if ErrorLevel<>0
WinActivate, ahk_exe chrome.exe
Else {
Run,C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
Sleep 3000
}
}
; 無変換キー + b, w, re, e
vk1D::
Input,MyCommands,I T1 L2, {Esc},b,w,re,e
If MyCommands = b
IsOpenChrome()
Else If MyCommands = w
WinActivate, ahk_group TerminalVim
Else If MyCommands = re
Reload
Else If MyCommands = e
; tablacusexplorer を開く
Run, D:\tablacusexplorer\TE64.exe
return
;-----------------------------------------------------------
; ターミナルでvimのためのIME
#IfWInActive, ahk_group TerminalVim
Esc::
getIMEMode := IME_GET()
if (getIMEMode = 1) {
IME_SET(0)
Send {Esc}
} else {
Send {Esc}
}
return
^[::
getIMEMode := IME_GET()
if (getIMEMode = 1) {
Send {Esc}
Sleep 1 ; wait 1 ms (Need to stop converting)
IME_SET(0)
Send {Esc}
} else {
Send {Esc}
}
return
^o:: ; 挿入ノーマルモードに入るときもIMEオフ
getIMEMode := IME_GET()
if (getIMEMode = 1) {
Sleep 1 ; wait 1 ms (Need to stop converting)
IME_SET(0)
Send ^o
} else {
Send ^o
}
return
^y:: ; emmetで次の入力をするためにIMEオフ
getIMEMode := IME_GET()
if (getIMEMode = 1) {
Sleep 1 ; wait 1 ms (Need to stop converting)
IME_SET(0)
Send ^y
} else {
Send ^y
}
return
#IfWinActive
;-----------------------------------------------------------
; Chrome
; アドレスバーのショートカットキーを押したら
; IMEはオフの状態で起動するように設定
#IfWInActive, ahk_exe chrome.exe
^l::
Send ^l
Sleep 100
IME_SET(0)
Return
^t::
Send ^t
Sleep 100
IME_SET(0)
Return
#IfWinActive
;-----------------------------------------------------------
; AltTab
IsAltTabMenu := false
!Tab::
Send !^{Tab}
IsAltTabMenu := true
return
; カタカナひらがなローマ字キー2連打でAltTabMenuキーとして割当
vkF2::
If (A_PriorHotKey == A_ThisHotKey and A_TimeSincePriorHotkey < 1000){
Send !^{Tab}
IsAltTabMenu := true
}
return
; 変換キー2連打でAltTabMenuキーとして割当
vk1C::
If (A_PriorHotKey == A_ThisHotKey and A_TimeSincePriorHotkey < 1000){
Send !^{Tab}
IsAltTabMenu := true
}
return
#If (IsAltTabMenu)
h::Send {Left}
j::Send {Down}
k::Send {Up}
l::Send {Right}
Enter::
Send {Enter}
IsAltTabMenu := false
Return
Space::
Send {Space}
IsAltTabMenu := false
Return
#If
常駐使用のため、スクリプトファイルはスタートアップに登録しています。
スタートアップ登録方法
- スクリプトファイルのショートカットを作成
- 「Win」 + 「r」
-
shell:startup
を入力してスタートアップ登録フォルダを開く - スクリプトファイルのショートカットをスタートアップ登録フォルダに移動
最後に
便利すぎていろいろとスクリプトに書きたくなるかもしれませんが、覚える&使えるボリュームを見失わないようにするのが大切です。
この記事は「便利だと思って使ってるやつ Advent Calendar 2020」の24日目の記事です。
Discussion
WSLからChromeを起動していたのですが、
ブラウザの方がアクティブになってくれないことが多々ありました。
そのたびにマウスで操作していたのを何とかしたい、、、と思っていましたがこちらの記事で解決しました!
イネダさん
バッジありがとうございます!
Windowsの困りごとの解決手段として、AutoHotkeyは頼もしいですよね!
お役に立てたようで嬉しいです!