AutohotKeyの

更新履歴

動作環境

Tips

細かいもの

.ahk への Drag&Drop でフルパスを得る

引数

正規表現の "m" オプション

text =
(Join`r`n ;改行を`nから`r`nにする
1行目
2行目
3行目
)
RegExMatch(text, "m)^2行目$") ;もしくはこちらをm`n)
MsgBox, %$1%
return

ファイル名の変更 FileMove

ファイル名は255文字まで。フルパスは259文字まで。

ドライブ直下の場合のみ、C:\ で3文字、ファイル名が 255 文字でフルパス 258 文字まで。

FileMove, ~, ~
MsgBox, %A_LastError%
return

A_LastError
2    変更元のファイルが見つからない
3    フルパスが長すぎ
32   ファイルが使用中
123  ファイル名に使用できない文字が含まれている。もしくはドライブ直下のファイル名が255文字を超えている
183  新しいファイル名と同名のファイルがある

IsFunc

問題を解決したい

+#a:: など Shift キー & Win キーでスタート画面が出るようになった

Open Shell をインストールしなかったか?設定で Nothing に変更する

Open Shell

Windows キー + L でロック画面が出る問題 Win8.1

#l:: が動作せずにロック画面が出るときはレジストリに以下を追加する

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System]
"DisableLockWorkstation"=dword:00000001

Scancode Map で L キーの位置に別のキーを割り当てた場合の Windows キー + 物理 L 問題 Win8.1

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"= ~ 14,00,26,00 ; キーボードの L の位置に T を割り当てる

#l::
  MsgBox, LLL
  return
#t::
  MsgBox, TTT
  return

の場合、Win キーと物理的に L の位置にある T を押すと LLL が表示される。
#+t:: は大文字 L になるなど、Win キーと L の位置に割り当てたキーをコンビネーションとして使うのは良くない。
多分 Windows 側の仕様だと思う

※これが重要な問題になるのは Dvorak 使用者だけだと思う
私は Dvorak + 右手一列シフトなので T なのだが、普通のDvorak だと N だと思う。

対処1:
#t:: と #l:: はどちらか片方だけ割り当てる。
#t:: を使うときは #l:: として記述し、Win + 仮想 l は使用しない。

クリップボード への連続処理

クリップボードに対して高速で操作すると、OS が貼り付けをする前に中身が入れ替わってしまう。

貼り付けの完了を取得できないので ^v の後に Sleep を入れて対処するしかないが、クリップボードの文字列の長さに応じて Sleep の数値を大きくする必要がある。

loop, 10
{
	clipboard =
	clipboard = %A_Index%
	ClipWait, 1
	SendInput, ^v
}

結果:4101010101010101010 など

Send 問題

SendEvent と SendInput

SendEvent(KeyDelay 10) は一文字ずつ間隔をあけて入力するのでキーバッファに貯まりづらく、キーをすべて入力し終わってから次の処理に移れる

SendInput はキーバッファに貯まるので、キーをすべて打ち終わる前に次の処理が追い越すことがある

マクロ中で使うときは SendInput のメリットを生かせない

SetKeyDelay, 10, 0
SendEvent, ABCDEFGHIJKLMN ; キー入力に 130ms かかるが、完了してから次の処理に移れる
WinClose, A

SendInput, ABCDEFGHIJKLMN
Sleep, 100 ; キー入力の完了がわからないため、多めに待たなければならない
WinClose, A


WinGet, id, ID, A
DllCall("SendMessage", UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint, id), UInt, 0x0283, Int, 0x0006, Int, 0)
sleep, 10
SendInput, 12345678901234567890123456789012345678901234567890 ; 50文字
Sleep, % 50*4 ; 文字数 x 4ms
DllCall("SendMessage", UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint, id), UInt, 0x0283, Int, 0x0006, Int, 1)
; うちの PC 環境だと CPU の使用率が低い時は x 3ms、1コア占有なら x 6ms 
; Sleep が少ないと後半が全角になるのでチェックしやすい。4567890

KeyDelay (SendEvent , ControlSend)

SendEvent で確実にマクロを実行するには KeyDelay か KeyDuration が10ms 以上必要

ControlSend で修飾子を入力するには KeyDuration が 10ms 以上必要

よって Auto-execute セクションでの記述は SetKeyDelay, 10, 10 が無難

SetKeyDelay, 10, 0
ControlGetFocus, ctrl, A
if (ErrorLevel)
	ctrl = ahk_parent
ControlSend, %ctrl%, AB CD EF, A
; 結果:AB cd ef

Send 全角/半角問題

半角文字、{ 特殊キー } を入力する際には IME を offにしておくこと

修飾キー付きマウスボタン:: での Send 問題

まれに Send での修飾キーの自動復元が行われない

+LButton:: ; 物理キーの場合
SendInput, aaaaaaaaaa
; 結果:aaaaaAaaaa

; 対策
+LButton::
KeyWait, Shift ; Shift キーを物理的に離すのを待ってから Send を実行
SendInput, aaaaaaaaaa


RButton:: ; 仮想キーの場合
  SendInput, +{LButton}

; 別スクリプト
menu, root, add, item
item:
  SendInput, aaaaaaaaaa
; 結果:aaaaaAaaaa

; 対策:キーの入力先がメニューなら +{Enter} にしてみる

秀丸エディタ問題

改行問題

SetKeyDelay, 0, 0 では {Enter}、`r `n の後ろが入力されないことがある。SendInput、ContrelSend も同様

確証はないが、SendEvent は KeyDelay か KeyDuration が 10 以上、ControlSend ならば KeyDelay は 10 以上ならば大丈夫そう

SendInput は KeyDelay の設定がないので対応できない

SetKeyDelay, 0, 0
SendEvent, A{Enter}B
SendEvent, {Text}A`nB
SendEvent, {Raw}A`rB
SendInput, {Text}A`nB
ControlSend, %ctrl%, A`nB, A
; いずれも B が入力されない

SendInput, {vkF3} 問題

2021.07.27引っかかりがでる原因に"#UseHook, On"を追加。

#UseHook, On の状態で SendInput, {vkF3} を使うと、IME 切り替え動作に引っかかりが生じる

KeyDelay 10以上 の SendEvent を使うか、その他→動作環境→タブモード詳細→互換性→V7.xx以下 にチェックを入れると大丈夫

ControlSend で文字打つ問題

はじめに

https://www.autohotkey.com/docs/commands/ControlSend.htm

アルファベット大文字などのシフトを押しながら打つ文字(A +a)、修飾子の付くショートカットキー(^a +{Left})などは、修飾子が押されないことがある

半角問題

SetKeyDelay, 10, 10 でも不安定なソフトがある。Unity 製のゲームで確認

SetKeyDelay, 10, 10
ControlGetFocus, ctrl, A
if (ErrorLevel)
	ctrl = ahk_parent
ControlSend, %ctrl%, ZZZ, A
; 結果:zZZ
; Z は +z なので "Shift" が効いていない

全角(半角カナ含む)問題

全角の後ろにくる半角の修飾子は効かないことが多い

"AAAあああ" 前半が半角のみ、後半は全角のみで終わるなら良い

SetKeyDelay, 10, 10
ControlGetFocus, ctrl, A
if (ErrorLevel)
	ctrl = ahk_parent
ControlSend, %ctrl%, あああZZZ, A
; 結果:あああzzZ

ControlSend, %ctrl%, あああ, A ; 2つに分けてもダメ。下の "{Text} 問題"と同じ
ControlSend, %ctrl%, ZZZ, A
; 結果:あああzZZ

{Text} 問題

KeyDelay を無視して高速入力するが、`r `n `t `b は KeyDelay の値で入力される

{Text} 直後の ControlSend には注意。多めの "Sleep" を挟む必要がある

SetKeyDelay, 10, 10
ControlGetFocus, ctrl, A
if (ErrorLevel)
	ctrl = ahk_parent
ControlSend, %ctrl%, {Text}DDD, A
ControlSend, %ctrl%, ZZZ, A
; 結果:DDDzzz

`r `n `t `b の後ろが入力されなかったり、順番が入れ替わったりすることがある

SetKeyDelay, 0, 10
ControlGetFocus, ctrl, A
if (ErrorLevel)
	ctrl = ahk_parent
ControlSend, %ctrl%, {Text}A`nB, A
; 結果:AB`n
ControlSend, %ctrl%, {Text}A`tB, A
; 結果:A`t`t  (B が `t に化ける)

`n より前の文字列の長さに応じて KeyDelay の値を大きくしなければならないので
実用的ではない。1文字なら 10ms、10文字なら 30ms など

Control, EditPaest

高速だが、SendInput と組み合わせるときは注意。

対象の ctrl が Edit[0-9]+ でないと使えない?

; 失敗例
SendInput, abcdefg
ControlGetFocus, ctrl, A
Control, EditPaste, あいうえお, %ctrl%, A

結果:abあいうえおcdefg

SendInput が打ち終わる前に ControlEdit が実行される
A_KeyDelay 10 以上の SendEvent で対処すること

確実に入力できる文字列のパターン

Scripts

デスクトップ・エクスプローラ等からフルパスを取得


GroupAdd, explorerGroup, ahk_class Progman
GroupAdd, explorerGroup, ahk_class CabinetWClass
GroupAdd, explorerGroup, ViX
GroupAdd, explorerGroup, ahk_class MDIEClass

#IfWinActive, ahk_group explorerGroup
F1::
    if !(filesPath := GetSelectedFilesPath()) {
        return
    }
    filesPath := RegExReplace(filesPath, "m)^(.+?)$(?:\r\n|)", " ""$1""")
    MsgBox, %filesPath%
    return

GetSelectedFilesPath() {
	savedClipboard := clipboard
	clipboard =
	SendInput, ^c
	ClipWait, 3
	filesPath := clipboard
	clipboard := savedClipboard
	IfNotInString, filesPath, :\
		return
	return filesPath
}

半角全角用Send:SendU Windows 8.1(64bit) + Microsoft IME 2012 用


/*
テスト機能
  ・IME On時とOff時で出力する文字を変える
      ex. SendU("1", "i", "{?IME}2") IMEがOffの時は"1"、Onの時は"2"
  ・LButton押下時に出力する文字を変える
      ex. SendU("1", "i", "{?LB}3") 通常は"1"、LButton押下時は"2"
  ・{opt}は{?~}の後ろに記述する
      ex. SendU("1", "i", "{?IME}{opt ik}2", "{?LB}3")
  ・書式は暫定

動作
  ・Send実行前にIMEをオフにするSend。Send [U]nicode
  ・動作確認は Windows8.1 64bit + Microsoft IME 2012のみ
  ・googleIMEではIME入力がキャンセルされてしまうので、キーマッピングには使えない。2022/02/02
  ・他スクリプトで"!@::"を使っているならば、そちらはフックしておく
  ・"`r`n" は"`n" に変換される。単独の"`r"は出力不可

keys
  ・{Raw}~{/Raw} , {Raw} ~末尾まで
  ・{Text}~{/Text} , {Text} ~末尾まで
      ・{Text}**{/Text}{Left}{Text}{tab}{/Text} -> *{Tab}*
  ・{Wait ミリ秒}
      ・"Sleep, ミリ秒"を挿入する。SendEventでの使用を推奨
          ex. A{Wait 1000}B -> send,A sleep,1000 send,B
      ・{Text}内の{Wait}は不可

opt
  ・m : リマッピング用。"ikb"を一括して指定したもの。Re[M]apping
  ・i : SendInputで出力する
  ・e : SendEventで出力する。 KeyDalayは10,0
  ・r : keysの先頭に{Raw}を追加する
  ・t : keysの先頭に{Text}を追加する
          ex. SendU("abc", "t") -> "{Text}abc"
  ・k : SendU実行前のIME On/Offを維持する。[K]eep
        このオプションがない場合、終了時はIME Offの状態になる
  ・b : 実行中はBlockInput, Onの状態にする(管理者権限が必要)

  ・keyの先頭に{opt}があれば、そちらでの指定が優先される
          ex. SendU, ("{opt i}abc", "e") ; SendInputで出力
*/
SendU(keys="", opt="", subKeys*) {
	imeOnKey  := "!@", imeOffKey := "!@" ; {vkF3}

	; 秀丸エディタ対策 1/2。タブモードではタブごとにIME On/Offの状態を保持している
	ControlGetFocus, ctrl, A
	if (ErrorLevel)
		WinGet, id, ID, A
	else
		ControlGet, id, Hwnd,, %ctrl%, A
	savedImeState := DllCall("SendMessage", UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint, id), UInt, 0x0283, Int, 0x0005, Int, 0)

	for k, v in subKeys {
		if RegExMatch(v, "i)^{:?\?LB}(.*)", $) && GetKeyState("LButton", "P") {
			SendInput, {LButton Up}
			keys := $1
		} else if (RegExMatch(v, "i)^{:?\?IME}(.*)", $) && savedImeState) {
			keys := $1
		}
	}

	if RegExMatch(keys, "i)^{:?opt *(.*?)}(.*)", $)
		opt := $1, keys := $2
	keys := StrReplace(keys, "`r`n", "`n")
	keys := StrReplace(keys, "`r", "`n")
	if InStr(opt, "m")
		opt .= "ikb"
	if InStr(opt, "t")
		keys := "{Text}" keys
	else if InStr(opt, "r")
		keys := "{Raw}" keys
	else {
		keys := RegExReplace(keys, "i){:?/(?:Text|Raw)}", "`r")
		keys := RegExReplace(keys, "i){:?Wait +\d+}", "`r$0`r")
	}
	if (savedImeState) {
		keys := imeOffKey keys
		if InStr(opt, "k")
			keys .= "`r" imeOnKey
	}
	; 秀丸エディタ対策 2/2。KeyDelayが10以上でないと改行の次のキーが無効になることがある
	if (ctrl = "HM32CLIENT1" && RegExMatch(keys, "i)(?:{Enter(?: +\d+|)}|\n)")) ;class = "Hidemaru32Class"
		opt := StrReplace(opt, "i", "e")

	savedSendMode := A_SendMode
	if InStr(opt, "i") {
		SendMode, Input
	} else if InStr(opt, "e") {
		SendMode, Event
		savedKeyDelay := A_KeyDelay, savedKeyDuration := A_KeyDuration
		SetKeyDelay, 10, 0
	}
	if InStr(opt, "b")
		BlockInput, On
	loop, Parse, keys, `r
	{
		if RegExMatch(A_LoopField, "i)^{:?Wait +(\d+)}$", $)
			Sleep, %$1%
		else if (A_LoopField != "")
			Send, %A_LoopField%
	}

	if InStr(opt, "b")
		BlockInput, Off
	SendMode, %savedSendMode%
	if (savedKeyDelay != "")
		SetKeyDelay, %savedKeyDelay%, %savedKeyDuration%
	return "-- SendU --`nopt = " opt "`n" keys "`n-- SendU --"
}

全角用のSend関数:SendU XP 用

半角で打ちたい用 Send

; 必ず半角で出力するなら
; A は Ascii の A
8:: SendA("(){Left}")

SendA(key) {
	WinGet, hWindow, ID, A
	DllCall("SendMessage", UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint, hWindow), UInt, 0x0283, Int, 0x0006, Int, 0)
	Sleep, 10 ; 対象アプリによっては Sleep が必要
	SendInput, % key
}

逆SandS (Space and Shift)

* 試用するだけなら不要
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
~略~
2a,00,39,00,\	; L-Shift(2a,00) を Space(39,00) に割り当てる。R-Shift(36,00) でも可。
39,00,5c,e0,\	; 念のためスペースキーを適当なキーの位置に割り当てておく。Space(39,00) → R-Win(5c,e0)
; ↓説明が面倒だが、チョン押しと修飾キーの動作を分けるために必要。
; Shift を絡めたホットキーがあればいいので、なければ使っていないキーをダミーとして登録しておくこと
<+vk07::SendInput, +{vkFF}
LShift::SendInput, {LShift Up}{Space} ; Shift が押しっぱなしになることへの対策
+LShift::SendInput, +{Space}

#IfWinActive, ahk_class Photoshop
  ; 手のひらツール用 : 物理スペースキーの位置 + クリックを、Space + クリックにする
  <+LButton:: Send, {Space Down}{LButton Down}
  <+LButton Up:: Send, {LButton Up}{Space Up}
#IfWinActive

AutohotKeyでニコニコ生放送アラート

;● ニコニコ生放送 cookie
nicoUserSession = user_session_??????_????????????????????

RunWait, wget.exe -O %A_Temp%\nico_my.txt --header "cookie: user_session=%nicoUserSession%" http://live.nicovideo.jp/my ,, Hide

すぐ忘れるので書式のメモ

A_Args

A_Args.Length()

for n, param in A_Args  ; For each parameter:
{
    MsgBox Parameter number %n% is %param%.
}
for n, GivenPath in A_Args  ; For each parameter (or file dropped onto a script):
{
    Loop Files, %GivenPath%, FD  ; Include files and directories.
        LongPath := A_LoopFileFullPath
    MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%
}

StrReplace() / StringReplace

ReplacedStr := StrReplace(Haystack, SearchText , ReplaceText, OutputVarCount, Limit := -1)


Haystack = aaa bbb ccc
ReplacedStr := StrReplace(Haystack, "b" , "*", count, 2)
MsgBox, %count% : %ReplacedStr%

2 : aaa **b bbb

StrSplit() / StringSplit

Array := StrSplit(String , Delimiters, OmitChars, MaxParts := -1)


String = *aaa*,*bbb*,*ccc*
Array := StrSplit(String , ",", "*", 2)
MsgBox, % "Array[1]_" Array[1] "_`n" "Array[2]_" Array[2] "_`n" "Array[3]_" Array[3] "_`n"

Array[1]_aaa_
Array[2]_bbb*,*ccc_
Array[3]__

RegExMatch

ReplacedStr := StrReplace(Haystack, SearchText , ReplaceText, OutputVarCount, Limit := -1)


Mode 3 (match object) : O)abc.*123

2 : aaa **b bbb

すべての更新履歴