keyhac でウィンドウ階層を指定する
keyhac v1.08 ではウィンドウ別のキーマップを定義できる。たとえば explorer.exe の Edit コントロールにフォーカスがあるときのキーマップはこのように定義する。
keymap_explorer = keymap.defineWindowKeymap(exe_name=u"explorer.exe", class_name=u"Edit")
しかし、explorer.exe ではアドレスバーも検索ボックスもリネーム中のファイル名もみんな Edit コントロールなのだ。class_name="" では末端のコントロール名だけが照合対象となるので、あちこちにある Edit コントロールを互いに区別できない。
窓使いの憂鬱では、トップレベルウィンドウから末端のコントロールまでのウィンドウ階層をコロン区切りで表した文字列に対して正規表現でマッチングを行うことができる。たとえばこんな感じ。
window ExplorerEditControl /explorer\.exe:(.+:)*Edit$/ : Global
これと同じことを keyhac で行うには次のようにする。
# config.py from keyhac import * import re def match_window(pattern): def _match_window(wnd): exe_name = wnd.getProcessName() lineage = ":" + wnd.getClassName() + ":" wnd = wnd.getParent() while wnd.getParent(): lineage = ":" + wnd.getClassName() + lineage wnd = wnd.getParent() lineage = exe_name + lineage print "match_window: " + re.sub("(?i)(" + pattern + ")", ur"<\1>", lineage) return re.search(pattern, lineage, re.IGNORECASE) return _match_window def configure(keymap): keymap_global = keymap.defineWindowKeymap() def launch_selstr(keymap, prefix = u"", suffix = u""): def _launch_selstr(): keymap.command_InputKey("C-C")() shellExecute(None, None, prefix + getClipboardText() + suffix, "", "", SW_NORMAL) return _launch_selstr keymap_explorer = keymap.defineWindowKeymap(check_func=match_window(ur"explorer\.exe:.*:Edit:$"))
この match_window 関数を使うと窓使いの憂鬱と同じように正規表現を使ってウィンドウ階層を特定することができる。たとえば Vista のエクスプローラでは
- アドレスバー
- explorer.exe:CabinetWClass:WorkerW:ReBarWindow32:Address Band Root:msctls_progress32:ComboBoxEx32:ComboBox:Edit:
- 検索バー
- explorer.exe:CabinetWClass:WorkerW:ReBarWindow32:UniversalSearchBand:Search Control:Edit:
- ツリービューでリネーム中
- explorer.exe:CabinetWClass:ShellTabWindowClass:DUIViewWndClassName:DirectUIHWND:CtrlNotifySink:NamespaceTreeControl:SysTreeView32:Edit:
- リストビューでリネーム中
- explorer.exe:CabinetWClass:ShellTabWindowClass:DUIViewWndClassName:DirectUIHWND:CtrlNotifySink:SHELLDLL_DefView:SysListView32:Edit:
となるから、リネーム中の Edit コントロールだけを対象にしたければ
keymap_explorer = keymap.defineWindowKeymap(check_func=match_window(ur"explorer\.exe:CabinetWClass:.*:Edit:$"))
とでもすればよい。*1