AutoHotkeyでキー入力したときや Gui上のオブジェクトの上にマウスを持っていったときとかに ToolTipを出す方法について。
ToolTip
1
| |
な感じでToolTipを出現させられます。
Textに出現させたい文字列を入れればその文字列が出ます。
(`nで改行もいれられる。)
Textに何も入れないで実行すると表示されているToolTipを消しせます。
X、Yは出現位置で
CoordMode
のToolTipの値によってスタート地点が変わりますが、
初期値ではWindowになっていて、
0, 0とすれば現在のウィンドウの左上にひっつくような表示になります。
1 2 | |
とかすればウィンドウの右下から外側にくっつく様なToolTipに。
X, Yが省略されるとマウスの所に出現します。
WhichToolTipはToolTipに振られる番号で、1から20を指定できます。
省略すると1番になります。複数のToolTipを表示させたい場合には
違う番号を指定します。(そうしないと前のものを上書きしてしまいます。)
キー入力イベントで表示させる簡単な例
簡単に、Aを押すと1秒だけToolTipを出すやり方としては
1 2 3 4 5 | |
こんな方法。ToolTipを出して、
Sleep
で一秒待ってからText無しのToolTipコマンドで削除します。
Sleepに与える引数はミリ秒なので1000で一秒です。
次に複数のToolTipを出してみます。
1 2 3 4 5 6 7 8 9 | |
これを実行してAを押すと、
tool tip 2とtool tip 3が出ますが、
ToolTip番号1はtool tip 2に上書きされるので
tool tip 1は出ません。
その後、1秒たってtool tip 2が消え、さらに1秒経ってからtool tip 3が消えます。
ただし、このSleepを使った方法はちょっと問題があって、
1秒経つ前にAを押した場合、
再びtool tip 2が表示される命令が出てこれはそのまま表示され続けるままですが、
以前のSleep後のToolTipが生きているので前にAを押したときから
1秒のタイミングで消えてしまいます。
この様な事を避けるため、通常は次のSetTimerを使った方法を使います。
SetTimerを使った例
SetTimer を使うと指定時間の途中で消したりすることが可能になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
AでToolTipを出した後、SetTimerを使っています。
SetTimerでは最初の引数でラベルを指定し、2つめに数字があると
その時間(ミリ秒)のタイマーを作動し、その時間分待った後にラベルで指定された動作を実行します。
実行後はタイマーをリセットし、またカウントダウンを初めて指定時間後に動作を実行する、を繰り返します。
RemoveToolTipというラベルの中では
Text無しのToolTipで削除しています。
最初のタイマーが10000ミリ秒(10秒)で作動するのでここではツールチップが10秒間表示されることになります。
また、表示中にAをもう一度押すと
ToolTipがもう一度実行されますがこの際は同じメッセージなのでそのまま。
その後SetTimerによってタイマーがリセットされるので
Sleepを使ったときと違い、最後に押したときから10秒経ってから消えることになります。
RemoveToolTipではさらにToolTipの直前でSetTimerでOffをしています。
2つ目にOffがあるとそのタイマーは停止されるので
ここへ来るとタイマーは止まり、その後繰り返しません。
最初のSetTimerからラベルを伝って必ず来るようになっているので
このタイマーは一回しか作動しません。
この設定をこの様に別のラベルで作っておくとBでこのラベルを呼出し、 途中で消すことが出来ます。
Gosub
はラベルにジャンプしてReturnで戻ってくる機能です。
Goto
という似たような機能がありますが、こちらは行ったまま戻ってきません。
ここでは直後にReturnしてるのでどちらでも同じですが、
Goto的なものは混乱の元なのでGosubで関数的に呼び出して戻ってくる、
と言った感じにした方が分かりやすくなります。
ここで、Bに対して単に
1 2 3 | |
の様にToolTipを直接消す様に定義しても全く同じことが出来ます。
ただこの場合は裏でタイマーは動き続けていて3秒後にToolTipを実行します。
実行してもTextが無いので結局何も起こりませんが。
これだけの例だとそこまで気にする必要はありませんが、 与えたラベルの中で色々やる場合に、複数回起動されると困ることもあるでしょうし、 単に裏で無駄なプロセスが残っているのも気持ち悪いので きちんと消すようにした方が良いです。
同様に、Sleepを使ってる場合でもBにToolTipを実行させて
無理やり消すことも出来ますが、
この場合もSleep後の実行命令は残りますし、
上にも書いたようにSleepでの実行には問題があるので
SetTimerを使った方が良いです。
GuiのオブジェクトにマウスオーバーでToolTipを表示させる
Tooltipを直接表示させることは出来ましたが、 Webや他のアプリで良くあるのは何らかのものの上にマウスを持っていった時に 表示されるToolTipです。
これを実現するためには以下の様な事をやります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |

以下のページで出てる解答にちょっと手を加えたものになっています。
(SOLVED) gui control tooltip on hover? - Page 2 - Ask for Help - AutoHotkey Community
Guiに関しては以下参照。
まず、いくつかのGuiのコンテンツをいれたウィンドウを表示させています。
Showした後に、
OnMessage
という関数がありますが、
これは特定のメッセージ番号を受け取った時に実行する関数を指定できる
関数です。
最初の引数がメッセージ番号で2つめに関数名を文字列で書きます。
メッセージはSendMessage, 0x200の様にスクリプト内で送ることも出来ますが、
それ以外にもGui上の操作などでも特定の番号でAutoHotkeyに送られてきます。
ここに
...
WM_MOUSEFIRST = 0x200
WM_MOUSEMOVE = 0x200
WM_LBUTTONDOWN = 0x201
WM_LBUTTONUP = 0x202
WM_LBUTTONDBLCLK = 0x203
...
とありますが、0x200はWM_MOUSEFIRST及びWM_MOUSEMOVEにあてられています。
これはGuiウィンドウの上でマウスが動いた時にメッセージを送ることになります。
その後のWM_LBUTTONDOWNCLK(0x203)なら左クリックした時にメッセージを送ることになります。
これを使うことでGuiウィンドウ上でマウスが動いた時に常に
MyMouseMoveが実行される事になります。
MyMouseMoveでは、
CurrControlとPrevControlという2つのグローバル変数を使っています。
上の参考URLの中ではstaticを使って関数内で次回も使える変数にして
いますが、これによって
DisplayToolTipも関数内に書く様な形になっています。
2つの値を他の余計な所で書き換えられない、という点はstaticの方が便利ですが、
ラベルは外に出したほうがすっきりするかな、ということで
上の様な書き方をしてみました。
その上でまずA_GuiControlという値を取ってきています。
A_GuiControlは命令を実行させたGui Controlが入っていますが、
v-labelが指定されてる時はv-labelが、
されてない時はテキストが入ります。
この場合はマウスの下にあるオブジェクトのものが入ることになります。
Gui, Add, Edit, vMyEdit
ならMyEdit、
Gui, Add, Edit, , MyEditText
ならMyEditTextの部分がA_Controlに入ります。
両方ない場合は空。
ただし、Textはちょっと注意が必要で
そのままv-labelを与えてもテキストを与えてもGui Controlではないので
A_GuiControlに何も入りません。
(上の参考URLの最後の質問にこれに関すると思われるものもありますが。)
コントロールオブジェクトにするためにはg-labelを付けます。
これで押した時にする動作を付けられるわけですが、
今回はこれに何もしない動作をDummyラベルを割り当てています、
これにより、押しても何もしないテキストですが
Gui Controlとなり、A_GuiControlで値が取得できる様になります。
値を取得したら、前回と変わってなければ何もせずに終了。
上のURLの例だと!=の代わりに< >を使っていますが同じ意味です。
また、InStr(...)で" "と比べ、空白を含まないチェックをしていますが、
これは空白を含むと、あとで
1
| |
の所で、%CurrControl%の値と_TTをくっつけた名前の変数の中身を取り出す時に
変数名に空白があるとエラーが出てしまうからです。
ただ、その様な別の要素に移った際にもTooltipを消してリセットするのが正しいので
変更後はまずA_GuiControlが変わったかどうかだけ見てPrevControlをセットし
ToolTipで一度ToolTipを削除しています。
その次に、A_GuiControlが空白(何も無いスペースやTextなどでGui Controlオブジェクトじゃないもの、v-labelもテキストも無いもの)だったり、
スペースを含むような値(大概はTextでg-labelを設定してないもの)
の場合には何もせずに終了します。
この部分に関してもう少し。参考URLの方では
…and not InStr(CurrControl, " ")みたいなことをしていますがこれは上手く動きませんでした。
InStrは2つ目の引数が最初に現れる位置を返しますが、なければ0を返します。
0がfalseなのでnotにしてandでつなげれば同じことなはずなのですが。
これの&&だけ変更したり...==0だけ変更したりしても上手く行きませんでした。
エラーになるわけではなく、CurrControl != ""の真偽だけで全て決まってしまうような形になっていました。
何か勘違いしてる気がしますが、とりあえず上に書いた形だと期待通りに動いてくれました。
いずれにせよ、もし使えるA_GuiControlだった場合、
DisplayToolTipを1秒のタイマーでセットします。
これによっていきなり出すのではなく、1秒以上マウスが同じオブジェクトの上に居た場合にToolTip を出すことが出来ます。
DisplayToolTipでは上でも説明したとおり%CurrControl%_TTを
ToolTipに出していますが、
この値は
Prepare tooltip messagesのところで作っています。
この様にGui Control名+_TT (_TTでなくてもいいけど適当な共通のもの)
をToolTipの内容として作っておくことで
こんな感じの動作を実現することが出来ます。
これとは別の方法で実現しようとする以下のような解答もありました。
ここでは
MouseGetPos
を使ってGui Controlの情報を取ってきていますが、
ここで取れるものはButton1とかButton2とかで、
ClassNNと呼ばれるコントロール群の名前+番号となっています。
従って配置した順序によって取れる値が変わるためちょっと使いづらいものになっています。