Alt + Tab を卒業したくて Win + カーソルキーで隣のウィンドウに切り替えるツール for Windows をつくってみた

Alt + Tab よりもっと直感的に素早くウィンドウを切り替えたい、とは常々思っていた。まだまだ荒削りだけど一応形になったので取り上げる。

(2018/02/16 追記) Qiita にもう少し詳しく解説した記事を書いてみた → Alt + Tab が使いづらいのでカーソルキーで隣のウィンドウに切り替えるツールを Python + cx_Freeze でつくってみた - Qiita

つくったもの

winhop というツール。

Win + カーソルキーで隣のウィンドウをアクティブにするよ、的なツール。

デモ

Win + カーソルキーでメモ帳を切り替えてるデモ。

winhop_demo

成果物

GitHub に置いた。

現時点での想定ユーザー

UI やドキュメントが手抜きなので玄人向け。

  • AutoHotkey を使える技量がある
  • ウィンドウハンドルやクラス名を調べる技量がある

現時点での使い心地

  • 非常駐ツールなので AutoHotkey 等から起動してください
  • README は知った気に書いたオレオレ英語だけです(日本語版はそのうち書く)
  • (特にWin10では)要らんウィンドウが切り替え対象になってしまうのがジャマなので、オプションを駆使して頑張って省いてください
  • 作者環境ではちゃんと動いてます(誤動作なくサクサク切り替えできている)が、他環境ではわかりません
    • この手のソフト(ウィンドウを扱う系のソフト)は結構環境次第で動いたり動かなかったりする修羅の道なのですが、果たしてどうなることやら
  • (2018/02/17追記) 最小化されたウィンドウは切り替え対象になりません。コンセプトは「表示されているウィンドウの中で素早く切り替える」です。切り替え対象にしたければ最小化を解除する必要があります。

技術的なはなし

どうやって切り替えている?

過去記事 ウィンドウを確実にアクティブにする方法 - stamemo で取り上げたアルゴリズムを使用。

簡単に書くと、AttachThreadInput → BringWindowToTop をした後に 当該ウィンドウの左上をクリックする

クリック……邪道だが致し方ない。他に方法見つからなかった。

切り替え対象ウィンドウはどうやって列挙している?

ソースでいえば libwindow.pyの50行目 あたり.

  • FindWindowEx でズラズラ列挙する
  • IsWindowVisible で不可視ウィンドウは除外する

ただ、これだけだと(特にWin10で)列挙されてほしくないゴミウィンドウがちらほら列挙されやがるので、利用者に指定して除外してもらうことにした。winhop.pyの19行目 あたり。

  • 指定した文字列をタイトル or クラス名に含むウィンドウを除外する
  • 指定した面積(ウィンドウ縦サイズと横サイズの積)よりも小さい面積のウィンドウを除外する

(おまけ)ゴミウィンドウ

私の Win10 環境だと、以下ウィンドウあたりが邪魔者だった。

$ winlist --visible --area-over 25000 --format "'$caption' '$classname' $pos $size"
'Cortana' 'Windows.UI.Core.CoreWindow' (0,458) (392x582)
'タスク スケジューラ のジャンプ リスト' 'Windows.UI.Core.CoreWindow' (443,928) (256x112)
'スタート' 'Windows.UI.Core.CoreWindow' (0,458) (256x582)
'Windows シェル エクスペリエンス ホスト' 'Windows.UI.Core.CoreWindow' (0,0) (1920x1080)
'Microsoft Visual C++ Runtime Library' '#32770' (719,407) (496x290)
'' 'Shell_TrayWnd' (0,1040) (1920x40)
'' 'ApplicationFrameWindow' (1920,0) (1280x1024)
'' 'ApplicationFrameWindow' (0,0) (1920x1040)

Win7 ではそうでもなかったのに、Win10 になってから要らんウィンドウが多すぎる……。

※winlist はウィンドウ情報を調べるオレオレツール。気が向いたら公開したい。

「隣のウィンドウ」はどうやって判定している?

一番苦労したところ。

winhop.pyの107行目 あたり。詳しくはソースを見てもらうとして、まあぶっちゃけ泥臭く頑張っている。

今はとりあえず「各ウィンドウの左上座標」を基準にして計算している。シンプルな考え方だが、その分意図しないウィンドウが隣として扱われてしまうこともちらほら。そのうちもっと賢いアルゴリズムを考えたい。

おわりに

早速私の Windows に設定した。しばらく運用してみる。果たして Alt + Tab から解放されるのか。わくわく。乞うご期待。