PROFILE
ゆるゆるアキレス
Author: ゆるゆるアキレス
やってみて成功したことや失敗したこと等、誰かの参考になれば良いなぁ。
公開フリーソフト情報
カテゴリ
最新記事
月別アーカイブ
検索フォーム
日々の試行錯誤をメモすると、極一部の人の参考になるはず

ポップアップメニューは別AHKにする方が便利

せっかくホットキーを作っても使用頻度が少ないと忘れてしまいがち。
ホットキー一覧表を作って表示させてから使うくらいなら、オリジナルのポップアップメニューから実行した方が分かりやすくて便利です。

オリジナルポップアップメニューを作ってみたのですが、いくつか問題が出てきました。
メニュー表示中は割り込みが禁止されていてホットキー等が効かない。
メニューを表示した時、メニューにフォーカスが無いという状況がたまにある。
メニュー外をクリックしてもメニューが消えないことがたまにある。


これを解決するために、ポップアップメニューは別AHKにしてみましょう。
更にポップアップメニューの強調とメニュー外のクリックを確実に感知するためにバックを暗くするマスクを SplashImage で作ってみましょう。
popupmenu1.jpg

呼び出されるポップアップメニュー表示用 CtMenu.ahk

#NoEnv
SendMode,Input
SetTitleMatchMode,3
#InstallKeybdHook
#UseHook
#NoTrayIcon

CoordMode,Mouse,Screen
CoordMode,Menu,Screen
MouseGetPos,mx,my

SplashImage,1:,B CW00007f,,,wt_ctMenuAHK
WinSet,Transparent,90,wt_ctMenuAHK
WinSet,Top,,wt_ctMenuAHK
SysGet,x,76
SysGet,y,77
SysGet,w,78
SysGet,h,79
WinMove,wt_ctMenuAHK,,%x%,%y%,%w%,%h%

Menu,ctMenu,Add,AutoHotkeyフォルダを開く,folderAhkOpen
Menu,ctMenu,Add,Cドライブを開く,folderCdrvOpen
Menu,ctMenu,Add,サウンドデバイス,soundDevOpen
Menu,ctMenu,Add
Menu,ctMenu,Add,キャンセル,cmenuCancel

Menu,ctMenu,Show,%mx%,%my%

cmenuCancel:
SplashImage,1:off

ExitApp


folderAhkOpen:
run,%A_ScriptDir%
return

folderCdrvOpen:
run,C:\
return

soundDevOpen:
Run,mmsys.cpl
return

呼び出す側のメインAHKの呼び出し部分のスクリプト

^sc03a::
if(WinExist("ahk_class #32768")){
return ;何かのメニュー表示中は出さない
}
CoordMode,Mouse,Screen
Run,%A_ScriptDir%\AutoHotkey.exe CtMenu.ahk
;メニューにフォーカスを移す処理をして終わる
WinWait,ahk_class #32768,,2
WinGetPos,wx,wy,,,ahk_class #32768
MouseClick,Right,%wx%+16,%wy%+16
return

このスクリプトの例では、Ctrl+ CapsLock キーでオリジナルポップアップメニューを表示できます。
AutoHotkey のフォルダを開く
エクスプローラでCドライブを開く
サウンド設定のウィンドウを開く
が選択できます。

いろいろと便利になりますが、メインのAHKにフィードバックが必要な処理には不向きです。
この記事のカテゴリ: AutoHotkey ▲PageTop

別AHKの実行中確認にSplashImageを使う

AutoHotkey はいろいろことが出来ますので、ついつい大きくなりがちです。
ホットキーの実行内容の変更などはちょくちょく編集してリロードするので、その度に再実行になると不便な処理があるんですよね。
時間の掛かる処理や独立した処理は別AHKにして run で呼び出した方が便利なようです。

AHKファイルを分けた場合、別AHKが実行中かどうかをメインのAHKから知りたいことがよくありますが、ちょっと困ったことになります。

~.ahk を常駐実行すると、プロセス名がどれも AutoHotkey.exe になっていること。
run 時の pid を変数に記憶しても、リロード時に使えなくなること。


これを解決するための手段として、ユニークな WinTitle を付けた透明な SplashImage を置いて手がかりにしてみましょう。

呼ばれる側の test.ahk のファイル内容

#NoEnv
SendMode,Input
SetTitleMatchMode,3
#InstallKeybdHook
#UseHook
#NoTrayIcon

SplashImage,,B FM10 W150 X200 Y0,,test常駐,wt_test
WinSet,Top,,wt_test
WinSet,Transparent,100,wt_test
WinSet,ExStyle,+0x00000020,wt_test

SetTimer,ShiftChecker,100

exit

AppsKey::
KeyWait,AppsKey
ExitApp
return

ShiftChecker:
if(GetKeyState("Shift","P")){
ToolTip,Shift=ON
} else {
ToolTip,Shift=OFF
}
return


呼ぶ側のメインAHKの呼び出し部分のスクリプト

#IfWinNotExist,wt_test
AppsKey::
Run,%A_ScriptDir%\AutoHotkey.exe test.ahk
WinWait,wt_test,,2 ;必ず起動確認してから終わる
return
#If

このスクリプトの例では、アプリケーションキーを押すと Shift キー監視の常駐AHKが起動します。
常駐AHK実行中にアプリケーションキーを押すと常駐AHKが終了します。
メインAHKを編集リロードしても同じ動作が維持できます。
WinSet,Transparent,100,wt_test の 100 を 0 にすれば完全に透明になって隠せます。

いろいろと便利なので本来の使い方以外で SplashImage を使いまくっています。
この記事のカテゴリ: AutoHotkey ▲PageTop

マウス位置のビューにフォーカスを移す方法

マウスジェスチャーソフトで、
→↑に Ctrl + Home (先頭にスクロール)
→↓に Ctrl + End (末尾にスクロール)
を登録しているのですが、マウス位置ではなくその時のアクティブな対象に実行されてしまいます。
いろいろやってみたところ、MouseGetPos でマウス位置のコントロールを取得して、
WM_VSCROLL で、SB_TOP と SB_BOTTOM が一番良い感じでしたが、
Chrome や エクスプローラのファイル表示欄等で使えず、
ControlSend ではブラウザの別フレームとか判定できず…

そこで、RButton を押して即キャンセルすることでクリック判定されることなくマウスカーソル位置のビューにフォーカスを移すことが出来るのを利用してみましょう。メニューが一瞬表示されるのは気にしないということで。

ScrollTopEnd(k,pm){
;↓右クリックキャンセル方式で実行したいクラス名を羅列
ng1:="Internet Explorer_Server DirectUIHWND Chrome_RenderWidgetHostHWND"
;↓長距離スクロール方式で実行したいクラス名を羅列
ng2:="MozillaWindowClass DroverLord - Window Class PSViewC"
CoordMode,Mouse,Screen
MouseGetPos,mx,my,wh,ct,3
ct:=(ct==null)?wh:ct
WinGetClass,c,ahk_id %ct%
if(InStr(ng1,c)){
BlockInput,on
BlockInput,MouseMove
Send,{RButton}
Sleep,100
Send,{Esc}%k%
BlockInput,off
BlockInput,MouseMoveOff
} else if(InStr(ng2,c)){
Sleep,100
mv:=(pm==6)?90000:-90000
Loop,10 {
SendMessage,0x20A,mv<<16,(my<<16)|mx,,ahk_id %ct%
}
} else {
Sleep,100
SendMessage,0x115,pm,0,,ahk_id %ct%
}
}
^f15::ScrollTopEnd("^{Home}",6)
+f15::ScrollTopEnd("^{End}",7)

このスクリプトでは、Ctrl+ f15 で先頭にスクロール、Shift+ f15 で末尾にスクロールします。
RAlt::f15
で一時的に f15 キーを作ってマウスジェスチャーソフトに登録しました。

右クリックメニュー出現のタイムラグ対策の Sleep と、マウス操作誤爆対策の BlockInput が入っています。
右クリックキャンセル方式でも動作しないこものがあったので長距離ホイールスクロール方式も入れました。
これは万能ですが、一瞬で移動しないとか、長すぎると端まで行けないとかの弱点もあります。

上手く動作しないビューのクラス名を調べるにはこんなスクリプトを利用します。

RAlt::
MouseGetPos,,,wh,ct,3
ct:=(ct==null)?wh:ct
WinGetClass,c,ahk_id %ct%
MsgBox,%c%
Clipboard = %c%
return

右Altキーを押すと、マウスカーソル位置のビューのクラス名がクリップボードに入りますので、それをクラス名羅列の中に追加します。

追記:2017/08/30
結局、三方式から選ぶことになりました。
スクロールバーにTop/Bottomメッセージ発行 , 右クリックキャンセル後にHome/End , 長距離スクロール。
この記事のカテゴリ: AutoHotkey ▲PageTop

括弧の入力を便利にするスクリプト

括弧の入力をする時、() の後に自動的に括弧内にカーソルが移動したり、
一発で選択文字列を囲うように括弧が入力されると便利なことが多いです。

PasteKakko(k1,k2){
ClipSaved := ClipboardAll
Clipboard =
Send,^c
Sleep,50
c1 := Clipboard
Clipboard =
Send,+{Left}^c
Sleep,50
cb := Clipboard
if(cb=="`r`n" or cb=="`r" or cb=="`n"){
Send,+{Right}
cb := ""
} else if(cb==c1 and StrLen(cb)==StrLen(c1)){
cb := c1
} else if(StrLen(cb)==1){
if(StrLen(c1)==2 and SubStr(c1,2,1)!="`r" and SubStr(c1,2,1)!="`n"){
Send,+{Right}
cb := c1
} else {
Send,+{Right}
cb := ""
}
} else {
Send,+{Right}
cb := c1
}
Clipboard := k1 . cb . k2
Send,^v
Sleep,100
Send,{left}
Clipboard := ClipSaved
ClipSaved =
}

vk1Dsc07B & 8::
if(GetKeyState("Shift","P") and GetKeyState("Ctrl","P")){
PasteKakko("「","」")
} else if(GetKeyState("Ctrl","P")){
PasteKakko("{","}")
} else if(GetKeyState("Shift","P")){
PasteKakko("[","]")
} else {
PasteKakko("(",")")
}
return

vk1Dsc07B & 2::
PasteKakko("""","""")
return

[無変換]+ 8 を押すと、() が入力され、() の中にカーソルが移動します。
文字列選択中であれば、選択した文字列を囲うように括弧が付きます。
Shift+ [無変換]+ 8 で、[]
Ctrl+ [無変換]+ 8 で、{}
Shift+ Ctrl+ [無変換]+ 8 で、「」
[無変換]+ 2 で、""

という感じです。
単純な処理なのにちょっとスクリプトが長いのは、選択範囲無しで Ctrl+c をすると1行コピーになるテキストエディタへの対応処理が入っているからです。
ClipWait だと反応が悪すぎるので Sleep,50 を入れていますが、正常に動作しないようなら 時間を伸ばしてみてください。

今回わかったこと
if 文で数字のみが入った変数同士を比較する時、文字列ではなく数値で比較されてしまう。
例えば、000 と 0 は同じ、0001 と 01 は同じと判定される。
今回は、StrLen() で文字列の長さも同時に比較することで文字列として同じかどうかの判定をしました。
(他にもっと良い方法があるかもしれませんが)
この記事のカテゴリ: AutoHotkey ▲PageTop

ウィンドウの移動とサイズ変更を便利にする

ウィンドウのサイス変更は Alt+Space の直後に s を押すやり方だと
内側から境界に向かってゆっくりドラッグすれば吸着して便利。
そして、ウィンドウのどこをドラッグしてもウィンドウが移動できると便利。
という記事を書きましたが、それをマウスジェスチャーや拡張マウスボタンに設定して
便利に使えるスクリプトを作ってみました。

このスクリプトでは、

F16キーを押した後、すぐにドラッグならウィンドウの移動ができます。
最大化状態など、ウィンドウによっては移動が出来ないものもあります

Shift+ F16 を押すと、ウィンドウのサイズ変更モードになります。
内側からウィンドウの境界へ向かってややゆっくり目にドラッグすればウィンドウの境界に吸着します。
ウィンドウによってはサイズ変更が出来ないものもあります

RAlt::f16 を使ってマウスジェスチャーソフトに登録すると便利です。

;ウィンドウ移動
f16::
if(InStr(A_Cursor,"Size")){
return
}
mblockerOn()
Loop,100 {
ToolTip,Window Move
if(GetKeyState("LButton","P")){
break
}
Sleep,10
}
ToolTip
mblockerOff()
CoordMode,Mouse,Screen
MouseGetPos,sx,sy,mh
WinGet,St,MinMax,ahk_id %mh%
if(st){
return
}
mblockerOn()
WinGetPos,wx,wy,,,ahk_id %mh%
while(GetKeyState("LButton","P")){
MouseGetPos,mx,my
WinMove,ahk_id %mh%,,wx-(sx-mx),wy-(sy-my)
}
mblockerOff()
return
;ウィンドウサイズ変更
+f16::
if(InStr(A_Cursor,"Size")){
return
}
MouseGetPos,,,mh
WinGet,St,Style,ahk_id %mh%
if((st & 0x00040000) and !(St & 0x80000000)){
ToolTip,Window Resize
DllCall("user32.dll\SendMessage","Int",mh,"Int",0x0112,"Int",0xF000,"Int",NULL)
ToolTip
}
return

mblockerOn(){
SplashImage,5:,B,,,mblock
WinSet,Transparent,1,mblock
WinSet,AlwaysOnTop,On,mblock
SysGet,x,76
SysGet,y,77
SysGet,w,78
SysGet,h,79
WinMove,mblock,,%x%,%y%,%w%,%h%
}
mblockerOff(){
SplashImage,5:off
}

ちょっと解説:
SplashImage で全面を覆ってマウスをガードしてマウスカーソル形状がノーマルのみになるテクニックを使っているのですが、SplashImage のXYWH指定ではタスクバーの範囲まで大きく出来ないので、WinMove で指定しています。

追記:2017/09/02
移動とサイズ変更を待ち時間で分岐する方式でしたが、短時間でも待ちきれないので2つに分けました。
この記事のカテゴリ: AutoHotkey ▲PageTop