Chapter 11

特定のアプリのウィンドウをアクティブ化

AWtnb
AWtnb
2021.12.30に更新

cuteExec を真似してみました。

プロセス名とクラス名でウィンドウを探して、見つからなければ指定されたパスを開き、見つかればアクティブ化します(アクティブ化に失敗したら Ctrl-Alt-Tab を押してウィンドウ一覧を表示)。

config.py

    # ウィンドウを探す
    def find_window(exe_name, class_name=None):
        found = [None]
        def _callback(wnd, arg):
            if not wnd.isVisible() : return True
            if not fnmatch.fnmatch(wnd.getProcessName(), exe_name) : return True
            if class_name and not fnmatch.fnmatch(wnd.getClassName(), class_name) : return True
            found[0] = wnd.getLastActivePopup()
            return False
        pyauto.Window.enum(_callback, None)
        return found[0]

    # 最大10回アクティブ化にトライする
    def activate_window(wnd):
        if wnd.isMinimized():
            wnd.restore()
        trial = 0
        while trial < 10:
            trial += 1
            try:
                wnd.setForeground()
                if pyauto.Window.getForeground() == wnd:
                    wnd.setForeground(True)
                    return True
            except:
                return False
        return False

    # クロージャ生成
    def pseudo_cuteExec(exe_name, class_name, exe_path):
        def _executer():
            found_wnd = find_window(exe_name, class_name)
            if not found_wnd:
                execute_path(exe_path)
            else:
                if found_wnd != keymap.getWindow():
                    if activate_window(found_wnd):
                        return None
                send_keys("LCtrl-LAlt-Tab")
        return _executer

find_window() は公式の keymap.ActivateWindowCommand()ソース を参考に書いてみました。

activate_window() で何度もループでアクティブ化しているのは、 Windows のどこかのバージョンからかウィンドウの強制アクティブ化ができなくなったからです。セキュリティ上を考えると当然ですね。

下記のようにループで割り当てています。

config.py

    # キー入力でウィンドウのアクティブ化
    for key, params in {
        "U1-Enter": (
            "TE64.exe",
            "TablacusExplorer",
            None
        ),
        "U1-P": (
            "SumatraPDF.exe",
            "SUMATRA_PDF_FRAME",
            None
        ),
    }.items():
        keymap_global[key] = pseudo_cuteExec(*params)

    # 変換とCを押してからのキー入力でアクティブ化
    keymap_global["U1-C"] = keymap.defineMultiStrokeKeymap()
    for key, params in {
        "C": (
            "chrome.exe",
            "Chrome_WidgetWin_1",
            r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
        ),
        "S": (
            "slack.exe",
            "Chrome_WidgetWin_1",
            resolve_path(r"AppData\Local\slack\slack.exe")
        ),
        "F": (
            "firefox.exe",
            "MozillaWindowClass",
            r"C:\Program Files\Mozilla Firefox\firefox.exe"
        ),
        "B": (
            "thunderbird.exe",
            "MozillaWindowClass",
            r"C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe"
        ),
        "E": (
            "EXCEL.EXE",
            "XLMAIN",
            None
        ),
        "W": (
            "WINWORD.EXE",
            "OpusApp",
            None
        ),
    }.items():
        keymap_global["U1-C"][key] = pseudo_cuteExec(*params)