タスクビュー

書き直したやつも貼っておこー

https://猫猫猫.tokyo/?p=1259

機能追加

Ctrl + Win + F1~F6キー:デスクトップ切り替え
Ctrl + Shift + F1~F6キー:アクティブ画面を指定のデスクトップに移動*
Ctrl + Shift + Win + F1~F6キー:アクティブ画面を指定のデスクトップに移動してデスクトップも移動*
Ctrl + Win + 左右キー:デスクトップ1と6を左右キーで移動*
Ctrl + Shift + 左右キー:アクティブ画面を隣のデスクトップに移動*
Ctrl + Shift + Win + 左右キー:アクティブ画面を隣のデスクトップに移動してデスクトップも移動*

*:機能追加

もうぐちゃぐちゃ。こんなの覚えてられん。これを覚えて使おうとする人おる?環境によっては、Ctrl + Shift + 左右キーあたりは他のソフトのホットキーと被るかもしれないので人によっては使えないのだろうなぁとは分かりつつも致し方なし。

作ったもの

taskview_ext_20240615.zip

「タスクビュー」のソースファイル

#Requires AutoHotkey v2.0+
#SingleInstance Force

; ----------------------------------------
; define
; ----------------------------------------

PREV := "Prev"
NEXT := "Next"
OK := True
NG := False
VDA_PATH := "C:\tool\taskview\VirtualDesktopAccessor.dll"
hVirtualDesktopAccessor := DllCall("LoadLibrary", "Str", VDA_PATH, "Ptr")
GetDesktopCountProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetDesktopCount", "Ptr")
GoToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GoToDesktopNumber", "Ptr")
GetCurrentDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetCurrentDesktopNumber", "Ptr")
MoveWindowToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "MoveWindowToDesktopNumber", "Ptr")

; ----------------------------------------
; helper function
; ----------------------------------------

GetDesktopCount() {
    count := DllCall(GetDesktopCountProc, "Int")
    return count
}

GoToDesktopNumber(number) {
    if (number > GetDesktopCount())
        return
    ; Win + 左右キーのアニメーションに操作感を合わせるため、
    ; 移動前後に0.5秒の待ち時間を設定している(機能的には不要)
    Sleep 500
    DllCall(GoToDesktopNumberProc, "Int", number - 1)
    Sleep 500
}

GetCurrentDesktopNumber() {
    number := DllCall(GetCurrentDesktopNumberProc, "Int")
    number++ ; デスクトップ番号を1オリジンで指定するため + 1
    return number
}

MoveWindowToDesktopNumber(number) {
    WinWaitActive WinExist("A")
    retry := 0
    Loop
        try {
            activeHwnd := WinGetID("A")
            number-- ; dllには0オリジンで渡すため - 1
            DllCall(MoveWindowToDesktopNumberProc, "Ptr", activeHwnd, "Int", number, "Int")
            result := OK
            break
        } catch {
            Sleep 250
            result := NG
            retry++
        }
    until retry == 10

    return result
}

moveWindow(desktop) {
    current := GetCurrentDesktopNumber()
    max := GetDesktopCount()
    if (desktop == PREV) {
        if (current == 1) {
            result := MoveWindowToDesktopNumber(max)
        } else {
            result := MoveWindowToDesktopNumber(current - 1)
        }
    } else if (desktop == NEXT) {
        if (current == max) {
            result := MoveWindowToDesktopNumber(1)
        } else {
            result := MoveWindowToDesktopNumber(current + 1)
        }
    } else {
        result := MoveWindowToDesktopNumber(desktop)
    }
    return result
}

moveDesktop(desktop) {
    current := GetCurrentDesktopNumber()
    max := GetDesktopCount()
    if (desktop == PREV) {
        if (current == 1) {
            GoToDesktopNumber(max)
        } else {
            Send "^#{Left}"
        }
        KeyWait "Left"
    } else if (desktop == NEXT) {
        if (current == max) {
            GoToDesktopNumber(1)
        } else {
            Send "^#{Right}"
        }
        KeyWait "Right"
    } else {
        GoToDesktopNumber(desktop)
    }
}

moveWindowMoveDesktop(desktop) {
    result := moveWindow(desktop)
    if (result == OK)
        moveDesktop(desktop)
}

; ----------------------------------------
; main
; ----------------------------------------

; アクティブ画面移動
^+Left:: moveWindow(PREV)
^+Right:: moveWindow(NEXT)
^+F1:: moveWindow(1)
^+F2:: moveWindow(2)
^+F3:: moveWindow(3)
^+F4:: moveWindow(4)
^+F5:: moveWindow(5)
^+F6:: moveWindow(6)

; デスクトップ移動
^#Left:: moveDesktop(PREV)
^#Right:: moveDesktop(NEXT)
^#F1:: moveDesktop(1)
^#F2:: moveDesktop(2)
^#F3:: moveDesktop(3)
^#F4:: moveDesktop(4)
^#F5:: moveDesktop(5)
^#F6:: moveDesktop(6)

; アクティブ画面/デスクトップ移動
^#+Left:: moveWindowMoveDesktop(PREV)
^#+Right:: moveWindowMoveDesktop(NEXT)
^#+F1:: moveWindowMoveDesktop(1)
^#+F2:: moveWindowMoveDesktop(2)
^#+F3:: moveWindowMoveDesktop(3)
^#+F4:: moveWindowMoveDesktop(4)
^#+F5:: moveWindowMoveDesktop(5)
^#+F6:: moveWindowMoveDesktop(6)

インストール手順

1.「taskview_ext_20240615.zip」ファイルを展開し、C:ドライブの直下に格納します。

C:\tool\taskview
└─taskview_ext.ahk

※格納場所固定。変更する場合は、ソース内のパス「VDA_PATH := “C:\tool\taskview\VirtualDesktopAccessor.dll”」を変更する必要がある。

2. 以下のサイトからDLLファイルをダウンロードします。

VirtualDesktopAccessor.dll
https://github.com/Ciantic/VirtualDesktopAccessor

リリースページの「VirtualDesktopAccessor.dll」をダウンロードする。
https://github.com/Ciantic/VirtualDesktopAccessor/releases

3. ダウンロードしたDLLファイルを同じフォルダに格納します。

C:\tool\taskview
├─taskview_ext.ahk
└─VirtualDesktopAccessor.dll

4. 「taskview_ext.ahk」を実行します。

アンインストール

フォルダごと削除するだけ。

動作確認環境

  • Windows 11
  • Autohotkey V2
  • ディスプレイ:1枚だけ

既知の問題点

デスクトップ1と6を左右キーで移動するときにアニメーションがない。

その他

IVirtualDesktopManager インターフェイス (shobjidl_core.h)
https://learn.microsoft.com/ja-jp/windows/win32/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager

  • IVirtualDesktopManager::GetWindowDesktopId
    指定された最上位ウィンドウをホストしている仮想デスクトップの識別子を取得します。
  • IVirtualDesktopManager::IsWindowOnCurrentVirtualDesktop
    指定されたウィンドウが現在アクティブな仮想デスクトップ上にあるかどうかを示します。
  • IVirtualDesktopManager::MoveWindowToDesktop
    指定した仮想デスクトップにウィンドウを移動します。

「VirtualDesktopAccessor.dll」には、このインターフェイスでは実現できない機能が含まれているのなんで?どうやって作ってるんだろう?仮想デスクトップ周りって他にも公開情報あるのか?ググったけど見つからなかったので継続調査中・・・

ソースファイル、助かるーけど、COM周り、シェル周り、相変わらず難しい。Rustで書かれているので、これを機にRustも触ってみようかとインストールしてドキュメントをパラパラした。

ヒープメモリを使用する変数に所有権あるらしいな。所有権ムーブしたり変数の変更に制限をかけることで二重開放などなどが起こりえない言語仕様になってるとか、なっていないとか?メモリの管理というか、状態の管理で良くバグるのあるある。おかしな動作がパソコン再起動したら直るってそういうことですよねえ。

所有権を理解する
https://doc.rust-jp.rs/book-ja/ch04-00-understanding-ownership.html

25年、29年?何も変わらないWindows のデスクトップアプリの内部、一度公開されたインターフェイスは変わらないですねえ。

Win32 API のプログラミング リファレンス
https://learn.microsoft.com/ja-jp/windows/win32/api

いにしえのソースやドキュメントを見ながら酒飲んでるw 🥴

時には昔の話を

https://www.youtube.com/results?search_query=時には昔の話を


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です