090-6423-5550
ギークハウス南町田在住
糸柳和法
殺せ、俺は殺す。

2008年11月28日金曜日

窓使いの憂鬱で Alt + Space によるメニューを強引に表示する

Windows で任意のウィンドウをアクティブにし Alt + Space を押すと、そのウィンドウに関連付けられているメニュー(Win32API で GetMenu() を使い取得できるもの)が呼び出される。通常は次のものが登録されている。

  • 元のサイズに戻す(R)
  • 移動(M)
  • サイズ変更(S)
  • 最小化(N)
  • 最大化(X)
  • 閉じる(C)

ここで () 内の文字列を入力することでこのコマンドを実行することができる。たとえば Alt + Space の後に x を押せば、ウィンドウを最大化できる。

いちいちマウスを使わなくても最大化や最小化、アプリケーションの終了までできるため非常の便利であり、ウィンドウの位置に依存しないため慣れればウィンドウの位置が不揃いな場合に連続して何らかのコマンドを実行することができる。

メニューは必ず画面内に出現するため、ウィンドウがどこか見えない場所に消えてしまった場合、Alt + Space m で移動を開始して十字キーで画面内まで移動させることもできる。特にマルチウィンドウ環境でウィンドウを外し、ウィンドウがあった場所にアプリケーションが取り残された場合に効果を発する。まあ別にタスクバーを右クリックしても移動は呼び出せるが。

問題は Alt + Space が効かない場合だ。アプリケーションのウィンドウプロシージャで Alt キーや Space キーの押下イベントを DefWindowProc() に渡していない場合、このメニューは出現しない。Meadow や PuTTY、MSYS などのウィンドウでは Alt キーが特別な意味を持つため、DefWindowProc() に渡さず自前で処理してしまっている。他に、SDL を使ったアプリケーションを始めとしてゲームの多くもキー入力を DefWindowProc() に渡していないためウィンドウに関連付けられたメニューを呼び出すことができない。

確かに Emacs では Alt キーがメタキーに割り当てられているし、Space キーは通常のスペース入力の他に C-SPC が set-mark-command に割り当てられている。そもそも本来、Alt キーは押すだけでウィンドウ上のメニューバー(Alt + Space で呼び出すことのできるウィンドウに関連付けられたメニューとは違う。通常「ファイル」や「編集」などが置かれるメニュー)をアクティブにしてウィンドウへのキー入力を殺してしまうのだから、これを抑制して自前で処理してしまいたいのはわかる。しかし俺は Alt + Space によるウィンドウに関連付けられたメニューの呼び出しだけは使いたい。でしゃばるなくそたわけが。この問題は窓使いの憂鬱を使うこと解決することができる。

しかしそもそもこれらのアプリケーションは Alt + Space 以前にキー入力を DefWindowProc() に渡していないため、ウィンドウに関連付けられたメニューを呼ぶための手順がアプリケーション内部に無い。窓使いの憂鬱でウィンドウに対してできることはせいぜい頑張ってもウィンドウメッセージの送付程度であるため、キー入力をそのまま使ってウィンドウに関連付けられたメニューを呼び出させることはできない。

しかし実は Win32API には隠しウィンドウメッセージが存在し、このメッセージによって強制的にウィンドウに関連付けられたメニューを表示させることができる。このメッセージは定数定義に存在しない 0x0313 という数値であり、これを直接ウィンドウに送り付けることでウィンドウに関連付けられたメニューを表示することができる。

窓使いの憂鬱におけるウィンドウメッセージの送付には &PostMessage() を使う。現在アクティブなウィンドウ自身に対してメッセージを送付するため、次のように定義すればいい。

keyseq $WM_SYSTEM_MENU = &PostMessage(ToItself, 0x0313, 0, 0)

後は任意のウィンドウにおける任意のキーイベントに対し $WM_SYSTEM_MENU を割り当てていく。

window Emacs (/:MEADOW$/ && /- Meadow$/) : Global
  key A-Space = $WM_SYSTEM_MENU

window xyzzy (/.*/ && /xyzzy .+@.+ - .+$/) : Global
  key A-Space = $WM_SYSTEM_MENU

window PuTTY /.*PuTTY$/ : Global
  key A-Space = $WM_SYSTEM_MENU

window MinGW (/rxvt.*/ && /MINGW32.*/) : Global
  key A-Space = $WM_SYSTEM_MENU

これでこれらのアプリケーションでも Alt + Space でのウィンドウに関連付けられたメニューの呼び出しが可能になる。別のキーに割り当てたければ任意のウィンドウであれ keymap Global であれ好きな場所で別のキーに $WM_SYSTEM_MENU を割り当てればいい。

少しでもマウスを使いたくない、男気のあるザ・マッチョ・ユーザーの皆さん、どうぞご利用ください。

1 コメント:

kosugi さんのコメント...

Meadow で困っていたので試してみます.

ちなみに, PuTTY には ALT + Space でシステムメニューを表示する設定項目がありますよ.

xyzzy も, ALT を一度 keyup してメニューバーにキーボードフォーカスが当たった状態で Space を押すとシステムメニューが開くようになっています.

肥溜

ファックな人生、あなたの心

糸柳
人間を殺した。
詳細プロフィールを表示