スポンサーリンク
AutoHotkey(現在v2)にて、キーが押されたままになってしまい、誤動作が発生してしまうことが以前より多発していました。例えばCtrlキーが押されたままになってしまうと、「s」キーを押しただけで「Ctrl+s」を押したこととなってしまい、急に保存ダイアログが表示されてしまう等の現象が発生します。
この修飾キーの押しっぱなし現象については、かなり長期間に渡って苦しめられてきており、以前にも対策についての試行錯誤記事を書いたのですが、その後も「押しっぱなし」現象は解消しないまま、騙し騙しAutoHotkeyの利用を継続しつつ、たまに対策について調べたり、実験的なAHKスクリプトの書き換えを行っていました。
AutoHotkey v2へのメジャーアップデートに伴う移行作業も行いつつ、その後も「押しっぱなし」となってしまい誤動作が発生する状態が続いていましたが、2024年6月、改めて対処をしていたところ、「押しっぱなし」になりにくくなったと思われる対策があったため、ここでシェアしておきます。
※ここ1年、2年程度、どういうわけか、押しっぱなし現象の発生頻度が悪化しており、対策しなければ、という度合いが上昇していた、というのもあります。
※「AutoHotkey v2.0.16」+ 「Windows バージョン 22H2 (OS ビルド 19045.4412)」+「キーボード:HHKB Professional HYBRID(日本語配列)」。
目次
スポンサーリンク
対策:SendEventを使用する
今回、色々と試した中で有力だった対策は、いくつかある「Send」の種類の中で、「SendEvent」を使用する、という方法です。
SendInput/SendPlayのほうが信頼性が高いと書かれているけれど、、、な対策
キーを送信する方法(モード)としては、「Event(SendEvent)」以外に「Input(SendInput)」や「InputThenPlay」、「Play(SendPlay)」があるのですが、それらの違いに関して、次のような記述があります。
SendInput and SendPlay: SendInput and SendPlay use the same syntax as SendEvent but are generally faster and more reliable. (引用元)
日本語で言えば、「SendInputやSendPlayは、SendEventと文法は同じだが、速度や信頼性に優れる」と書かれています。
つまり、「押しっぱなし」のような不安定な現象を避けようと思うと、「SendEventよりも、SendInputやSendPlayを使用しよう」となるような記述です。
まさに従来、「SendはInputやPlayを試そう」と思っていたわけですが、あえてそこに逆らってSendEventを使用してみたわけです。
そうすると、突然、安定し始めたように思えています(今のところ)。
Sendを使用しつつ、SendModeで「Event」を指定
実際の書き換えとしては、SendInputと書かれていたコードを「Send」に書き換えた上で、「SendMode "Event"」を最初に書くようにしました。
検証している最中は「SendEvent」と書きましたが、より書き換えの効率を良くするために、無指定の「Send」を使用しつつ、デフォルト値を書き換える「SendMode」を使用して、「SendMode "Event"」を指定したかたちです。
検証内容
今回この対策に至った実験内容について書き残しておきます。
押っぱなし現象を繰り返し再現できるコンパクトな操作を特定
もともと、「sc079 & a::SendInput("#{Tab}")」という指定を行っていました。
「sc079(変換キー)」を押しながら「a」キーを押すと、「WIn+Tab」が送信される、というホットキー定義文です。
私の環境では、この定義を書いている状態で、無変換キーを押して、離しきる直前のタイミングで「a」キーを押すと、無変換キーが押したままになってしまうことが分かりました。
普通に無変換キーを押しながらaを押す、というだけなら大丈夫なのですが、無変換キーを離す直前に(Up完了判定の直前に)「a」キーを押すと、無変換キーが押しっぱなしに高確率である、という、押しっぱなし現象を再現できる手順が分かったため、そこを実験材料にしました。
SendEvent化で改善の兆し
そこで、様々な書き換えを行いました。
Sleepを末尾に加えたり、Criticalを使ってみたり。
しかしいろいろと、ある意味しらみつぶしに試してみた結果、「SendEvent」を指定することで、突然その再現手順が発動しなく(発動できなく)なり、有力な対策では?と思えたわけです。
書き換えを実施してさらに検証を継続
そうした小さい実験で「改善されるかもしれない」という仮説が立ったため、すべてのSendを「SendEvent」に書き換えることとしました。
とはいえ、先ほども説明したとおり、直接すべての箇所を「SendEvent」に書き換えるのではなく、すべてを「Send」に書き換えつつ、「Send」時に「SendEvent」が発動するように、「SendMode "Event"」を最初に書いておいた、という形です(もちろん、すべてをSendEventで書き換えても良かったと思います)。
ホットキー定義によっては、意味があって明示的に「SendInput」や「SendPlay」と書いていたような気もするのですが、そこをSendEvent化したことが原因で問題が発生するようであれば元に戻せば良く、押しっぱなしによるホットキーの暴発のほうが深刻だと考えたため、特に区別せず、すべて「SendEvent」に変更してみたのが今回試している書き換えです。
完璧ではないものの手元の環境では激減
それから2週間程度継続してみました。
完全に解消しているわけではないものの、1日に何度も発生していた「押しっぱなし」になる現象が、1日に1回発動するかしないかといった具合に激減しました。
そのわずかな発生も、従来の発生タイミングとは異なる箇所・操作で発動するようになったことで影響が小さくなり、押しっぱなし状態の影響を受けて思わぬショートカットキーが発動してしまう問題の煩わしさは激減しました。
引き続き、この「SendEventを使用する」方法で利用を継続してみようと思います。
関連
スポンサーリンク
スポンサーリンク