切换windows虚拟桌面 Topic is solved

遇到了问题?请先进行搜索(中文和英文),然后在此提问

Moderators: tmplinshi, arcticir

norinco

切换windows虚拟桌面  Topic is solved

10 May 2023, 22:46

我在使用linux时一直使用的是wm它可以快速的切换桌面。当我使用win后我发现我有办法快速的切换不同的虚拟桌面。于是我想用ahk来实现他。对于这个脚本我有如下要求:1.可以使用win+数字,快速跳转到对应桌面。2.在跳转前记住当前桌面的焦点窗口以便我切回这个桌面后可以直接使用。3.win+shift+数字,将焦点窗口移动到对应桌面上。
我找到了一个可以基本使用的脚本

Code: Select all

; Capslock + 数字  -->  切换桌面
; Capslock + Shift + 数字  -->  把当前窗口带到某桌面
; [Switch to desktop] OR [Move the current window to the X-th desktop]

;;; 我用来测试的部分
#1:: 
SwitchToDesktop(1)
Return
#+1::
MoveActiveWindowToDesktop(1) 
Return

#2:: 
SwitchToDesktop(1)
Return
#+2::
MoveActiveWindowToDesktop(1) 
Return

#3:: 
SwitchToDesktop(1)
Return
#+3::
MoveActiveWindowToDesktop(1) 
Return
;;; 我用来测试的部分结束
Capslock & 4:: 
If GetKeyState("Shift")
MoveActiveWindowToDesktop(4) 
else SwitchToDesktop(4)
Return
Capslock & 5:: 
If GetKeyState("Shift")
MoveActiveWindowToDesktop(5) 
else SwitchToDesktop(5)
Return
Capslock & 6:: 
If GetKeyState("Shift")
MoveActiveWindowToDesktop(6) 
else SwitchToDesktop(6)
Return
Capslock & 7:: 
If GetKeyState("Shift")
MoveActiveWindowToDesktop(7) 
else SwitchToDesktop(7)
Return
Capslock & 8:: 
If GetKeyState("Shift")
MoveActiveWindowToDesktop(8) 
else SwitchToDesktop(8)
Return
Capslock & 9:: 
If GetKeyState("Shift")
MoveActiveWindowToDesktop(9) 
else SwitchToDesktop(9)
Return
Capslock & 0:: 
If GetKeyState("Shift")
MoveActiveWindowToDesktop(10) 
else SwitchToDesktop(1)
Return
; Capslock & -:: 
;If GetKeyState("Shift")
;MoveActiveWindowToDesktop(11) 
;else SwitchToDesktop(1)
;Return
; Capslock & =:: 
;If GetKeyState("Shift")
;MoveActiveWindowToDesktop(12) 
;else SwitchToDesktop(1)
;Return
 
SwitchToDesktop(idx){
    if (!SwitchToDesktopByInternalAPI(idx)){
        TrayTip , WARN, SwitchToDesktopByHotkey
        SwitchToDesktopByHotkey(idx)
    }
}
SwitchToDesktopByHotkey(idx){
    SendInput ^#{Left 10}
    idx -= 1
    Loop %idx% {
        SendInput ^#{Right}
    }
}
 
SwitchToDesktopByInternalAPI(idx){
    succ := 0
    IServiceProvider := ComObjCreate("{C2F03A33-21F5-47FA-B4BB-156362A2F239}", "{6D5140C1-7436-11CE-8034-00AA006009FA}")
    IVirtualDesktopManagerInternal := ComObjQuery(IServiceProvider, "{C5E0CDCA-7B6E-41B2-9FC4-D93975CC467B}", "{F31574D6-B682-4CDC-BD56-1827860ABEC6}")
    ObjRelease(IServiceProvider)
    if (IVirtualDesktopManagerInternal){
        GetCount := vtable(IVirtualDesktopManagerInternal, 3)
        GetDesktops := vtable(IVirtualDesktopManagerInternal, 7)
        SwitchDesktop := vtable(IVirtualDesktopManagerInternal, 9)
        ; TrayTip, , % IVirtualDesktopManagerInternal
        pDesktopIObjectArray := 0
        DllCall(GetDesktops, "Ptr", IVirtualDesktopManagerInternal, "Ptr*", pDesktopIObjectArray)
        if (pDesktopIObjectArray){
            GetDesktopCount := vtable(pDesktopIObjectArray, 3)
            GetDesktopAt := vtable(pDesktopIObjectArray, 4)
            DllCall(GetDesktopCount, "Ptr", IVirtualDesktopManagerInternal, "UInt*", DesktopCount)
            ; if idx-th desktop doesn't exists then create a new desktop
            if (idx > DesktopCount){
                diff := idx - DesktopCount
                loop %diff% {
                    Send ^#d
                }
                succ := 1
            }
            GetGUIDFromString(IID_IVirtualDesktop, "{FF72FFDD-BE7E-43FC-9C03-AD81681E88E4}")
            DllCall(GetDesktopAt, "Ptr", pDesktopIObjectArray, "UInt", idx - 1, "Ptr", &IID_IVirtualDesktop, "Ptr*", VirtualDesktop)
            ObjRelease(pDesktopIObjectArray)
            if (VirtualDesktop){
                DllCall(SwitchDesktop, "Ptr", IVirtualDesktopManagerInternal, "Ptr", VirtualDesktop)
                ObjRelease(VirtualDesktop)
                succ := 1
            }
        }
        ObjRelease(IVirtualDesktopManagerInternal)
    }
    Return succ
}
vtable(ptr, n){
    ; NumGet(ptr+0) Returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    Return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
GetGUIDFromString(ByRef GUID, sGUID) ; Converts a string to a binary GUID
{
    VarSetCapacity(GUID, 16, 0)
    DllCall("ole32\CLSIDFromString", "Str", sGUID, "Ptr", &GUID)
}
MoveActiveWindowToDesktop(idx){
    activeWin := WinActive("A")
    WinHide ahk_id %activeWin%
    SwitchToDesktop(idx)
    WinShow ahk_id %activeWin%
    WinActivate ahk_id %activeWin%
}
这个脚本默认的热键是Capslock我在测试时改了一部分为win(我修改注册表取消了win自带win+数字的热键),我是一个ahk新手,修改的部分可能有些丑陋,如果大家有更优雅的实现欢迎帮忙优化。现在我发现在我使用窗口切换时,脚本没有办法自动聚焦回原来的窗口上,我需要重新点击,希望大家可以帮忙改改。
当然我也有一个疑问在我刚想用ahk来解决这个问题时我找到的脚本大都只能实现上一个/下一个虚拟桌面的切换。在这种情况下win10因为有切换动画所以切换的很慢,win11没有动画就会很卡。而且他好像吧所有的切换任务放在一个队列里,当我快速连续按动快捷键后松手我会看到它还在不断切换。这个脚本是如何实现快速切换的呢。

Return to “请求帮助”

Who is online

Users browsing this forum: No registered users and 6 guests