
質問
AutoHotkey で特定のポップアップ ダイアログが表示されたときに自動的に検出し、特定のアクションを実行するようにしたいのですが。どうすればいいですか?
具体的な例
私の場合は、AutoHotkeyで目次を更新目次を更新するときに Word に表示されるダイアログ。
ワークフローは次のとおりです。
Word文書のタイトルを更新する
Ctrl+を押してA文書全体を選択します
F9すべてのフィールドを更新するには押してください
Arrow down選択するには押す必要がありますテーブル全体を更新続いてEnter押すわかりましたそして続ける
上記のワークフローは 1 日に何十回も実行するものなので、 AutoHotkey でArrow down,コマンドを自動的に発行したいと思います。Enter
もちろん、ワークフローを開始するのは私なので、次のようにCtrl+で始まるすべての処理を実行する AutoHotkey スクリプトを作成することもできます。A
#IfWinActive ahk_class OpusApp
F9::
Send, ^a
Send, {F9}
Sleep, 200
Send, {Down}
Send, {Enter}
return
ただし、上記の例はあくまで説明目的であり、ポップアップダイアログがランダムに表示され、ポップアップダイアログのタイトルに応じて AutoHotkey に何らかのアクションを実行させたい場合もあります。
これまでの私の研究
- いくつかのインターネットソースでは、AutoHotkeyループの使用を推奨していますこれは、特定のタイトルのウィンドウが存在するかどうかを1秒ごとに無限にループしてチェックし、その後閉じます。しかし、私はそれがCPUリソースの無駄だと感じています。
- 他のインターネットの情報源では、シェルフックコード スニペットも添付されており、これが正しい方法だと思いますが、コード スニペットが理解できません。これが解決策である場合、どのように機能するかを説明し、わかりやすい例を挙げていただける方はいらっしゃいますか?
次のコードスニペットはここからコピー。
SetBatchLines, -1
Process, Priority,, High
Gui +LastFound
hWnd := WinExist()
DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return
ShellMessage( wParam,lParam ) {
If ( wParam = 32772 or WParam = 4) ; HSHELL_WINDOWACTIVATED := 4 or 32772
WinGetActiveTitle, Title
If ( Title = "sun 4 - foxtrot - Remote Desktop Connection" )
SetCapsLockState, on
else SetCapsLockState, off
}
私は
If (Title = "sun 4 - foxtrot - Remote Desktop Connection")
部分。残り全体は何をしますか?
答え1
深いところまで来ていますね。特定のウィンドウ名をプログラムで監視することは、システム リソースにそれほど負担をかけません。おそらくこれが正しいやり方でしょう。
ShellMessage
は任意の名前にすることができます。これは、OnMessage
スクリプトがメッセージを受信したときにトリガーされる によって呼び出される関数だからです。この関数の内容は、正しいウィンドウにいることを確認し、送信したいコマンドを発行するためのコードである必要があります。関数は最大 4 つのパラメータを受け入れることができます。ヘルプファイルで定義されている通りのためにOnMessage
。
これらのDllCall
行は、システムからメッセージを取得するために Windows に結び付けられる難解な部分です。Windows のフードをいじる場合は、ここで何をしているのかを知っておく必要があります。
SetBatchLines, -1
そしてProcess, Priority,, High
、スクリプトは非常に重要であり、常にフルスピードで実行される必要があり、他のシステム プロセスによってスクリプトの速度が低下することはあってはならないと伝えます。
Gui +LastFound
そして、hWnd := WinExist()
スクリプトの実行時にそのスクリプトの一意の ID を見つけて、後続の で Windows に登録できるようにしますDllCall
。
答え2
ポーリングを行わず、応答性の高い効率的なコードにするには、次のコードを適応させます。
ファイルのセットアップ部分に次のステートメントを追加します。
Update Table of Contents ahk_exe WINWORD.EXE B WordTOCupdate
Update Table of Figures ahk_exe WINWORD.EXE B WordTOCupdate
スクリプトのこのセットアップ部分の列間にはタブがあることを確認してください (使用しているエディターによっては、スペースは使用しないでください)。exe 名は、変更しない限り RegEx マッチングを使用するため、大文字と小文字が区別されます。
次に、このコードをスクリプトの本体に記述します...
;-------------------------------------------------------
; Check for Microsoft Word Update Table of Contents
;-------------------------------------------------------
WordTOCupdate:
WinActivate ;Set Window to Be on top
SendInput !e{Enter}
return
投稿したスニペットを使用することもできます...基本的には同じものです。
Gui +LastFound
hWnd := WinExist()
DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return
ShellMessage( wParam,lParam ) {
If ( wParam = 32772 or WParam = 4) ; HSHELL_WINDOWACTIVATED := 4 or 32772
WinGetActiveTitle, Title
If (Title="Update Table of Contents" )
{
SendInput !e{Enter}
}
}
!e は Alt+e を送信してテーブル全体を更新します。