ぺんちゃん日記

食と歴史と IT と。 Web の旅人ぺんじろうが好奇心赴くままに彷徨います 。

【AutoHotkey】マウスドラッグが苦手なら自動操作に頼ればいいじゃん

目次


f:id:yasushiito:20190403184928p:plain

マウスドラッグ操作をahkにやらせる。

避けて通れないドラッグ操作。

マウスドラッグ操作がどうしても苦手です。
マウスポインタを動かす操作すらたどたどしい上にクリックするのも必死な状態ですから、ボタンを離さずに目的の位置まで動かす操作なんてできるわけありません。

特に残念なのは画像ソフトによるスクリーンショットのトリミング操作です。
こればっかりはどうしてもマウスでドラッグする以外に方法がありません。

f:id:yasushiito:20200805100846p:plain
GIMP でトリミングしているがドラッグ操作。


ブログ記事にスクリーン画像を盛り込む機会も多いのですが、トリミングのだるさを想像するだけで操作手順を説明にスクリーンショットを入れるのをためらいます。
というか実際にテキストの説明だけで済ませることが多いです。
それ以外にも選択範囲をぼかしたり、枠で囲んだり、 画像の利用は私にとって苦手な操作の塊です。

ということで、これまでずっと尻尾を巻いていましたが、たとえ中途半端な実装でも全くできないよりはましだと考えて思い切ってAutoHotkeyで自動操作することを検討してみました。

自動操作のイメージ。

ボタンを押しながら移動せずに、クリック2回で開始と終了地点を決めます。

健常者であれば 、キーボードと組み合わせて Ctrl キーが押されるまで待つのが一般的でしょう。
私はマウス操作しか出来ませんので、当然操作はマウスの左ボタンだけで行います。

マウスポインターを動かしてドラッグしたい開始位置をクリック。
その後自分のペースで終了地点に移動させてから、好きなタイミングでクリック。
すると、AutoHotkeyマウスポインタの座標を読み取って、マウスポインタと左ボタンを自動で動かします。

スクリプトを起動すると、即座に座標の聞き取りモードに入って、ユーザに対し開始地点と終了地点の2点を入力させます。
採取したポイントを自動操作でドラッグしたら終了します。

実装する。

簡単な割に効果が高そう。

AutoHotkeyの処理に難しいこところはありません。
実験的に作ってみたところ、想像以上に上手くいきました。

そこでデスクトップにショートカットアイコンを作りました。

より一層ドラッグ操作が快適になったので、今度はスクリーンキーボードからの操作で起動できないかと考え直しました。

この機能のイメージにふさわしいそうなキーはアプリケーションキー長押しではないかと見当をつけます。

スクリプトの例。

出来上がったスクリプトはこんな感じです。

AppsKey::
    ;長押し判定。
    ;スクリーンキーボードからマウスクリックで入力しているので左ボタンを監視している。
    KeyWait, LButton, T1
    if ErrorLevel
    {
        ;ドラッグ位置記憶モードの合図としてメッセージを表示。
        MsgBox, , , 左クリック2回でドラッグ位置記憶, 2
        ;左ボタンを押し下げて離れたらワンクリックとする。
        CoordMode,Mouse,Screen
        KeyWait, LButton, D
        Sleep, 100
        KeyWait, LButton, U
        ;開始地点の座標をスクリーン上の絶対位置で取得する。
        MouseGetPos, sx, sy
        ;2回目のクリックも同様に取得する。
        KeyWait, LButton, D
        Sleep, 100
        KeyWait, LButton, U
        MouseGetPos, ex, ey

        ;操作を繰り返すために開始と終了の座標を保存しておく。
        dragArea := sx . "," . sy . "," . ex . "," . ey
        
        ;ドラッグの自動操作。
        ;ユーザの操作を無視する。
        BlockInput, Mouse
        Sleep, 500
        ;マウスポインターを開始位置に移動させて左ボタンを押し下げる。
        MouseMove, sx, sy, 0
        Send, {LButton down}
        Sleep, 20
        ;そのまま終了位置に移動してからボタンを離す。
        MouseMove, ex, ey, 20
        Send, {LButton up}
        ;ユーザのマウス操作を有効にして終わり。
        BlockInput, off
        Return
    }
    ;長押しではなかった場合は通常通りにアプリケーションキー送信する。
    Send, {AppsKey}
    Return

myahk/mousedrag.ahk at master · yasushiito/myahk

注意点が三つ。

機能実装された座標を採取できない。

座標を採取するときの左クリックが本機のボタンクリック2なってしまいます。

予想はついていたけど想像以上に間抜けな実装です。

採取しようとしたポイントがボタンの上だったりすると、ボタンをクリックしたとみなされて普通に実行されてしまいます。
そのせいでファイルを実行したり画面遷移してしまうかもしれません。

先ほどはデスクトップ上に作成されたアイコンを移動させて整理しようとしたのですが、スクリプトが実行されてしまって苦笑いしました。

f:id:yasushiito:20200805101516p:plain
デスクトップのアイコンを移動させたいのだが。
画面内に収まりきらない選択はできない。

ドラッグ操作はあくまでも座標に対して行われるので、スクロールを伴う範囲選択には通用しません。

例えば長文のカット&ペーストを行うとき、Textarea をスクロールしてしまうと期待通りの範囲を選択できません。
つい先ほどもソースコードのコピペにこの機能を利用しようとして失敗しました。
そもそもスクリプトの目的が画像の範囲選択と移動ですから、テキストの範囲を選択することを想定してません。

特定のアプリの上では座標を取れない。

一部特殊なアプリケーション に対しては AutoHotkeyの処理が及ばないことがあります。
今回のスクリプトもその対象で、ドラッグ開始位置と終了位置の選択を行うときに、これらのアプリ上で左ボタンを押下しても、検知できません。

例えば先ほどは、このスクリプトでスクリーンキーボードを移動させようと試みたのですが失敗しました。
ただしスクリプトを管理者権限で起動してみたら期待通りに動作しました。
管理者権限のレイヤーで動いているアプリは同様でしょう。

座標採取でクリックしてしまうのは防げないのか。

注意点一つ目のやつです。

LButtonの入力を検知して、座標採取モードのボタン操作は無視できないのでしょうか?

実はできることを確認できたのは先日まとめましたが、マウスボタンの長押しができなくなってしまう問題にぶち当たってしまいました。

自動操作の再生を追加。

座標を撮る時、どうしてもクリックしてしまうなら、一度クリックしてしまうのは仕方ないとして、後から戻って自動操作し直してはいかがでしょうか。

ということで、スクリプトで実行したドラッグ操作を、もう一度繰り返す「再生機能」を実装してみました。


SHIFT キーを押しながらアプリケーションキーを長押しすると、前回のドラッグ実行をもう一度行います。

これなら座標を取る時に否応なくクリックしてしまっても、手順を戻ってから再生すればドラッグできなくもありません。

クリックで不可逆な処理が行われる場合は適用できませんが、そういう例外を除けば使えると思います。

;シフトキーを押しながらアプリケーションキーの長押し。
;マウスドラッグ操作をもう一度行う。
+AppsKey::
    ;長押し判定。
    ;スクリーンキーボードからマウスクリックで入力しているので左ボタンを監視している。
    KeyWait, LButton, T1
    if ErrorLevel
    {
        ;記憶された座標をカンマで分解して復元する。
        StringSplit, pos, dragArea, `,
        sx := pos1
        sy := pos2
        ex := pos3
        ey := pos4
        ;座標として復元できなかった場合は処理中止。
        i := sx . sy . ex . ey
        if i is not Number
        {
            MsgBox, , , 領域選択の記録を失敗しています\n%i%, 3
            Return
        }
        ;マウスドラッグの自動操作行う。
        CoordMode,Mouse,Screen
        BlockInput, Mouse
        Sleep, 500
        MouseMove, sx, sy, 0
        Send, {LButton down}
        Sleep, 20
        MouseMove, ex, ey, 20
        Send, {LButton up}
        BlockInput, off
        Return
    }
    ;長押しでなければ普通にシフトキーを押しながらのアプリケーションキー押下を送信する。
    Send, +{AppsKey}
    Return

myahk/mousedrag.ahk at master · yasushiito/myahk

最後に。

100点満点中60点かな。
どんな状況にも対応できるわけではないので考えながら使わないと無駄に終わってしまい、かえって手間が増えてしまうこともしばしば。
アプリケーションキーを探して長押しするのに時間がかかるので、時間的には効率化できた気分はしないです。
でもスクリーンショットのトリミングは楽になりました。



この記事に登場するAutohotkey スクリプトについて

この記事の中で私が作成したプログラムは、全て自由に使うことができます。
詳しくはこちら