キーストロークの送信方法

Send "Hello, world{!}{Left}^+{Left}"

キーストローク(略してキー)の送信は、最も一般的に機能するため、プログラムを自動化する方法として最も一般的です。より直接的な方法は、特定のタイプのアプリにのみ有効な傾向があります。

鍵の送り方を学ぶには、大きく分けて2つのパートがあります:

  1. どのキーを送りたいのか、プログラムがわかるようにコードを書く方法。
  2. 正しい結果を得るために、利用可能なモードやオプションをどのように使用するか。

キーを送信することで、人間の速度まで遅くしても、物理的にキーを押す行為が完全に再現されるわけではないことを理解しておく必要があります。しかし、その前に、いくつかの基本的なことを説明します。

例題の試用

SendText "Hi!"のような例を実行すると、テキストはアクティブ(フォーカス)なウィンドウに即座に送信されるので、例の実行方法によってはあまり役に立たないかもしれません。通常は、ホットキーを定義し、サンプルを実行してロードし、その効果を試したいときにホットキーを押すのがよいでしょう。以下のいくつかの例では、^1::Ctrlと数字、重複がなければ一度に複数の例を試すことができます)のような番号付きのホットキーを使用しますが、あなたの好みに合わせて変更することができます。

ホットキーのカスタマイズや独自に作成する方法については、「ホットキーの書き方」を参照してください。

例題を試す方法がわからない場合は、「例題コードを実行する方法」をご覧ください。

コードの書き方

キーを送信する場合、一般的には、キーまたはキーの組み合わせを送信してその効果を得るか(クリップボードにコピーするCtrl+Cのような)、何らかのテキストを入力することになります。文字入力の方が簡単なので、まずはそこから。SendText関数を呼び出し、送信したいテキストを正確に渡すだけです。

^1::SendText "To Whom It May Concern"

技術的には、SendTextは実際にはキーストロークではなく、Unicodeの文字パケットを送信するため、Shift+2 or AltGr+aのようなキーコンビネーションで通常入力される文字に対してより信頼性が高くなります。

引用符で囲まれた文字列のルール

SendTextは、テキストをそのまま送信しますが、言語のルールに注意してください。例えば、リテラルテキストは引用符(ダブル"またはシングル'」)で囲む必要があり、引用符そのものはSendText関数には「見えない」のです。文字通りの引用符を送るには、逆のタイプの引用符で囲むとよいでしょう。事例:

^2::SendText 'Quote marks are also known as "quotes".'

または、エスケープシーケンスを使用します。引用符で囲まれた文字列の中では、`"はリテラル"に、`'はリテラル'に変換されます。事例:

^3::{
    SendText "Double quote (`")"
    SendText 'Single quote (`')'
}

引用符を交互に並べることも可能です:

^4::SendText 'Double (") and' . " single (') quote"

2つの文字列は、SendText関数に渡される前に結合(連結)されます。ドット(.)は省略可能ですが、その場合、一方が終わり、他方が始まるのがわかりづらくなります。

上で見たように、エスケープ文字`backquotebacktickgrave accentなどの名前で知られている)には特別な意味があるので、その文字を文字通り送りたい(または対応するキーを送りたい)場合は、 Send "``" ように二重にする必要があります。その他によく使われるエスケープシーケンスとして、改行(Enter)を表す`n、タブを表す`tがあります。詳しくは「エスケープシーケンス」をご覧ください。

キーとキーの組み合わせの送信

SendTextはテキストをそのまま送信するのに適していますが、LeftHomeのようなテキストを生成しないキーは送信できません。SendSendInputSendPlaySendEventControlSendは、テキストとキーの組み合わせ、またはテキストを生成しないキーの両方を送信できます。そのために、次のようなシンボルに特別な意味を持たせている:^!+#{}

最初の4つの記号は、標準的な修飾キーであるCtrl(^)、Alt(!)、Shift(+)、Win(#)に対応しています。これらは組み合わせて使うことができますが、それ以外は次のキーにしか影響しません。

キーを名前で送る場合、または上記の記号のいずれかを文字どおり送る場合は、中括弧で囲んでください。事例:

Ctrl+Shift+"を押すと、次の例では2つの引用符が送られ、挿入点が左に移動して引用符の内側を入力できる状態になります:

^+"::Send '""{Left}'

Sendは、^!+#{}以外の任意の1文字について、それを対応するキーの組み合わせに変換し、その組み合わせを押したり離したりします。例えば、Send "aB"は、Aを押して離し、Shift+Bを押して離します。同様に、中括弧で囲まれたキー名は、デフォルトで押したり離したりされます。例えば、Send "{Ctrl}a"を実行すると、Ctrlを押したまま離し、Aを押したまま離すことになり、おそらく望むところではありません。

キーを押す(押し続ける)、または離すだけなら、キー名を中括弧で囲み、その後にスペースを入れ、"down"または"up"という言葉を入れます。次の例では、Ctrl+CapsLockShiftのトグルとして機能するようにします:

*^CapsLock::{
    if GetKeyState("Shift")
        Send "{Shift up}"
    else
        Send "{Shift down}"
}

ホットキーと送信の比較

警告:ホットキーと送信には、注意しなければならない違いがあります。

ホットキーも、記号^!+#と同じキー名を使用しますが、いくつかの重要な違いがあります:

これは、Sendが複数の目的を果たすのに対し、ホットキーはキーの組み合わせに最適化されているためです。

なお、ホットストリングはテキスト入力の検出専用なので、ホットストリングトリガーのテキスト内では、記号^!+#{}は特別な意味を持ちません。ただし、ホットストリングの置換テキストは、Sendと同じ構文を使用します(Tオプションを使用した場合を除く)。以下のホットストリングがアクティブな状態で "{" を入力すると、"}"を送信し、さらにLeftで挿入点を中括弧の間に戻す:

:*?B0:{::{}}{Left}

ブラインドモード

通常、Sendは、物理的に押している修飾キーが、送信を要求しているキーと組み合わされてはいけないと仮定しています。例えば、Ctrlを押しながらSend "Hi"を呼ぶと、Sendは"Hi"を送信する前にCtrlを自動的に離し、送信後にCtrlを押し戻すようにします。

あるキーを、以前に押したり送ったりした他のモディファイアと組み合わせて送りたいことがあります。そのためには、接頭辞として{Blind}を使用することができます。以下の例を実行しながら、空でないテキストエディターや入力フィールドにフォーカスし、CtrlまたはCtrl+Shiftを押したまま、1または2を押してみてください:

*^1::Send "{Blind}{Home}"
*^2::Send "{Blind}{End}"

{Blind}については、「ブラインドモード」を参照してください。

その他

Sendは、他にもいくつかの特殊な構成要素をサポートしています:

全リストは、「主要な名称」をご覧ください。

モードとオプション

キーを送信しても、物理的にキーを押すという行為を完全に再現することはできません。OSでは、キーを送信する方法がいくつか用意されており、それぞれに注意点があります。時には、望む結果を得るために、さまざまな方法を試すだけでなく、タイミングを微調整することも必要です。

主なメソッドは、SendInput、SendEvent、SendPlayです。一般的にSendInputが最も信頼性が高いので、デフォルトではSendはSendInputと同義です。SendModeを使用することで、SendをSendEventまたはSendPlayと同義にすることができます。ドキュメントにはSendInputSendPlayの他の長所と短所が長々と書かれていますが、SendInputで問題があったときにSendEventやSendPlayを試してみるだけでもいいと思います。

警告:SendPlayは、UIアクセスで実行しない限り、最新のシステムで動作しない傾向があります。

また、ControlSendも試してみる価値のあるオプションです。これは、キー操作を送信する公式な方法を使わず、指定したウィンドウに直接メッセージを送信します。主な利点は、これらのメッセージを受信するためにウィンドウが通常アクティブである必要がないことです。しかし、システムによるキーボード入力の通常処理をバイパスするため、うまくいかないこともあります。

タイミングと遅延

人並み以上の速さでキー入力の洪水を送っても大丈夫な場合もあれば、そうでない場合もあります。ディレイが必要になる場面は、一般的に2つあると思います:

最初の場合は、「Send」→「Sleep」→「Send」と呼び出すだけでよいです。

SetKeyDelay 2番目のケースに存在します。この機能は、各キーストロークの間に実行される遅延と、キーストロークの持続時間(つまり、キーを押してから離すまでの遅延)を設定できます。

^1::{
    SetKeyDelay 75, 25  ; キー間75ms、ダウン/アップ間25ms。
    SendEvent "You should see the keys{bs 4}text appear gradually."
}

警告:SendInputは、キー遅延をサポートしておらず、デフォルトのSendもサポートしていません。

SetKeyDelayを有効にするためには、一般的にSendMode "Event"を使用するか、SendやSendTextの代わりにSendEvent、SendPlay、ControlSendを呼ぶ必要があります。

テキストを大量に送信する

複数行の文章を送る方法として、継続部分を利用する方法があります:

SendText "
(
    先頭のインデントが取り除かれます。
    を1行目としています。
    改行が保持されます
    "Join"オプションを使用しない限り。
)"

一般的にかなり高速ですが、SendTextはまだ各文字を一度に送信する必要があり、Sendは一般的に少なくとも2倍のメッセージ(キーダウン・キーアップ)を送信する必要があります。そのため、大量のテキストを送信する際には、顕著な遅延が発生します。また、遅延が長くなると、ユーザーの入力と衝突したり、キーボードのフォーカスがずれたり、その他の条件が変化するリスクが高くなるため、信頼性が低くなる可能性があります。

一般的には、クリップボードにテキストを置き、それを貼り付ける方が、より速く、より確実です。事例:

^1::{
    old_clip := ClipboardAll()  ; クリップボードの内容をすべて保存する
    A_Clipboard := "
    (Join`s
        このテキストは、クリップボードに置かれます。
        で、Ctrl+Vを送ると下に貼り付けられます。
    )"
    Send "^v"
    Sleep 500  ; Ctrl+V が処理されるまで少し待つ。
    A_Clipboard := old_clip  ; 以前のクリップボードの内容を復元する
}