/AHK-Virtual-Desktop-Library

Take full control of Windows 10/11 virtual desktops with this AHK library

Primary LanguageAutoHotkeyMIT LicenseMIT

AHK-Virtual Desktop Library

Introduction:

In Windows you can use virtual desktops, this library gives you functions to fully manipulate them
For example:

  • GoToDesktop(desktop_number)
  • GetCurrentDesktop()
  • GetAmountOfDesktops()
  • MoveCurrentWindowToDesktop(desktop_number)
  • SetBackgroundOnDesktop(desktop_number, imgPath)(You can have one background per desktop)
  • NewDesktop()
  • you can open a program always on a specifed desktop with AlwaysOpenOnDesktopNumber(in_wich_desktop, the_program_you_want)
  • GetAltTabList()
  • and more!(you can see all functions in the index)
  • Also there's a list of usefull ideas to use this library

Index(start here):


Installation:

Note: This DLL and library works only on 64 bit Windows 10 and it was tested with Windows 10, 21H2, build 19044.1766, also it was done with ahk v1

  1. You probably need VS 2017 runtimes vc_redist.x64.exe and/or vc_redist.x86.exe if they are not installed already
  2. Download the "lib" folder
  3. Put it in the same folder as your script
  4. You should end up with:
Your script folder(or repo)
├── lib
│    ├── AHK-Virtual-Desktop-Library
│    ├── Other Library if you have
│    ├── Other Library if you have
│    └──...
└── Your Script Here.ahk
  1. Then include the library in your script like this:
#Include lib\AHK-Virtual-Desktop-Library\Main.ahk
  1. I really recomend deactivating the animation of changing desktops, they are "enemies" of instant responsiveness, try it for a while, to do so:
    Win+r > sysdm.cpl > enter > advanced options > performance > configuration > uncheck the "Animate windows when minimizing and maximizing" > apply > ok

Additional steps to install it on Windows 11:

Your script connects to the AHK-Virtual-Desktop-Library, and the library connects to the VirtualDesktopAccessor.dll(a file inside the library), and that .dll connects to Windows
The library will need the latest VirtualDesktopAccessor.dll, one that is up to date with Windows 11, wich can be found at the repo of the autor of VirtualDesktopAccessor.dll: https://github.com/Ciantic/VirtualDesktopAccessor
Download, reemplace and make sure that the line 5 of Main.ahk(that file is inside the library) has the right path to the VirtualDesktopAccessor.dll so it can "see" the .dll

Functions:

Note: a lot of functions takes the parameter hwnd, you can use the Built in Function GetActiveHwnd() to get the active hwnd
To the newbies: hwnd = ahk_id = it's the id of the window, every window has one

Navigate between desktops:

Functions Description
GoToDesktop(desktop_number) Goes to the desired desktop
GoToNextDesktop() Goes to the next desktop
GoToPrevDesktop() Goes to the previous desktop

Return information:

Functions Description
GetCurrentDesktop() Returns in wich desktop you are, for example if you are in desktop 8 it will return 8
GetAmountOfDesktops() Returns the total number of virtual desktops
InWichDesktopThisWindowIs(hwnd) Returns in which desktop a given hwnd is
IsWindowOnCurrentDesktop(hwnd) Returns if the given hwnd is in the current desktop
IsWindowOnDesktopNumber(desktop_number, hwnd) Return if a hwnd is in a specified desktop
GetAltTabList() Alt+Tab shows an array/list of open windows, this funtion returns that array, his order is from the foremost window to the one in the back, and is a array of hwnd's
IsFullScreenMode(ExesToIgnore) Returns True if you are in full screen mode
Returns False if you are in window mode
ExesToIgnore parameter: You can leave it empty or you can pass an array to it of .exe´s, and it will ignore those, so even if they are in full screen it will return False
For example. ExesToIgnore := ["atom.exe","GitHubDesktop.exe","chrome.exe"]
Use the funtion CopyActiveExe() in the Built in Functions to get the exe easier

For multimonitor support read the function in the source code

Move windows between desktops:

Functions Description
MoveCurrentWindowToDesktop(desktop_number) Moves current window to the desired desktop
MoveCurrentWindowToDesktopAndGo(desktop_number) Same as above but also goes to that desktop
MoveWindowToDesktop(desktop_number, hwndToMove) Meant to move a background window from the actual desktop to another

You can get a list of all background windows with GetAltTabList()
MoveWindowToDesktopAndGo(desktop_number, hwndToMove) Same as above but moves to that desktop and it will focus that window

Note: Functions here have repetitive names, but that's because I already combined them for you and dealed with side effects of it(for example flickering)
So don't combine funtions, use the already combined ones from the table IF possible
For example instead of this:

q::
MoveCurrentWindowToDesktop(2)
GoToDesktop(2)
return

Do this:

q::
MoveCurrentWindowToDesktopAndGo(2)
return

Open specified program on desired desktop every time:

Functions Description
AlwaysOpenOnDesktopNumber(desktop_number, exe) You can use this to have your favourite programs in the desktops you want.
Every time you open the a specified program(does not matter how) it will open in the desired desktop.
Requires 2 parameters:
desktop_number:In wich desktop the program will open
exe: a string with the .exe(NOT case sensitive).
For example. AlwaysOpenOnDesktopNumber(3, "Notepad.exe")

In this part you can use the Built in Function CopyActiveExe() to make it easier.

Note: There's File Explorer support, just do:
AlwaysOpenOnDesktopNumber(2, "explorer.exe")

If all windows start to open in that desktop, that means that the parameters are wrong
AlwaysOpenOnDesktopNumberAndGo(desktop_number, exe) Same as above, but also goes to that desktop

Open-Close Desktop:

Functions Description
NewDesktop() Opens a new desktop
CloseDesktop() Closes current desktop

Pin-UnPin Windows:

When you pin a Window or an App, it means that it will stay in all desktops, Windows remembers pins even if the script closes, so remember to unpin if you want to

Functions Description
PinWindow(hwnd) Pins the specified window(making it stay in all desktops)
UnPinWindow(hwnd) UnPins the specified window
IsPinnedWindow(hwnd) Returns 1 if pinned, 0 if not pinned, -1 if not valid
PinApp(hwnd) Pins the specified app(making it stay in all desktops)
UnPinApp(hwnd) UnPins the specified app
IsPinnedApp(hwnd) Returns 1 if pinned, 0 if not pinned, -1 if not valid

Set a background for each desktop:

Functions Description
SetBackgroundOnDesktop(desktop_number, path) Sets the background of a particular desktop
Parameter path: You can put in it one of 2 things:
1. The path to an image
2. The path to a folder with only images on it, and it will take a random one from it, for example SetBackgroundOnDesktop(1,"C:\Personalizing Windows\Wallpapers\For desktop 1\"), don´t forget to put an "" at the end

Note: you can give to it a folder path and have only one image in it, that way when you decide to change the wallpaper you have to interact with the folder and not with the code
SetDefaultBackground(path) For example if you didn't set up the background with SetBackgroundOnDesktop(desktop_number, path) in desktop 4, the background will be the default one that you set here, the parameter path works exactly the same as the function above

Note: The wallpaper does not changes instantly(takes 200 ms?), windows was not made with this feature in mind so this is my best try

Misc:

Functions Description
AltTabOnSwitch() Call this function and when you go to another desktop and everything is minimized it will automaticaly alt+tab(it does not send the keystrokes Alt+Tab because I tryed and looks bad and has bugs, the script imitates alt tab, does not use it)
CallFunctionOnDesktopSwitch() When you call it, it will call a funcion named OnDesktopSwitch() each time the desktop changes, YOU need to create that funcion OnDesktopSwitch() and add to it what you want to happen every time the desktop changes
DesktopManager() Opens desktop manager, call it again to close it
HoldAltTab() Same as Ctrl+Alt+Tab
FocusLastWindow() Like Alt+Tab, but does not press Alt+Tab, it's an ahk imitation
ShowHideDesktop() Show/hide desktop, Sends Win+D

Usefull Built in Functions:

Meant to make it easier

Hwnd

Functions Description
GetActiveHwnd() Returns the hwnd of the active window
CopyActiveHwnd() Copies into the clipboard the hwnd of the active window
IsHwndActive(hwnd) Returns True if is active and False if not, you have to give it a hwnd as a parameter

Exe

Functions Description
GetActiveExe() Returns the exe of the active window
CopyActiveExe() Copies into the clipboard the exe of the active window
IsExeActive(exe) Returns True if is active and False if not, you have to give it an exe as a parameter

Class

Functions Description
GetActiveClass() Returns the class of the active window
CopyActiveClass() Copies into the clipboard the class of the active window
IsClassActive(class) Returns True if is active and False if not, you have to give it a class as a parameter

Title

Functions Description
GetActiveTitle() Returns the title of the active window
CopyActiveTitle() Copies into the clipboard the title of the active window
IsTitleActive(title) Returns True if is active and False if not, you have to give it a windowTitle as a parameter

Working AHK Example:

I put a bunch of hotkeys together so you can test it for yourself, with escape you exit the script

#Include lib\AHK-Virtual-Desktop-Library\Main.ahk

GoToDesktop(2) ; tip: if you call this at the beginning of your script and if you start it with windows, you will start windows always on the desktop you want

; You can use this to have your favourite programs in the desktops you want:
; try opening paint with this script running, it will open in desktop 3:
AlwaysOpenOnDesktopNumber(3,"mspaint.exe")
; try opening notepad with this script running, it will open in desktop 1 and also go to it:
AlwaysOpenOnDesktopNumberAndGo(1,"Notepad.exe")

q::GoToPrevDesktop()
w::GoToNextDesktop()
e::DesktopManager() ; press again to close

1::GoToDesktop(1)
2::GoToDesktop(2)
3::GoToDesktop(3)

z::
currentDesktop := GetCurrentDesktop()
MsgBox, You are on desktop number %currentDesktop%
return

x::MoveCurrentWindowToDesktop(3)
; x::MoveCurrentWindowToDesktopAndGo(3)

a::CallFunctionOnDesktopSwitch(true) ; If true calls a funcion named OnDesktopSwitch(), is not obligatory to use

OnDesktopSwitch(){
	MsgBox, I run every time the desktop changes, I stop with the key "s"
}

s::CallFunctionOnDesktopSwitch(false) ; stops calling OnDesktopSwitch()

; to get the hwnd and exe easier:
r::CopyActiveHwnd() ; thats it, just paste it wherever you want
y::CopyActiveExe()

;Pin current window(remember to unpin)
f::
activeHwnd := GetActiveHwnd() ; you can use the built in function GetActiveHwnd() to get the active hwnd
PinWindow(activeHwnd)
return

;UpPin current window
g::
activeHwnd := GetActiveHwnd() ; you can use the built in function GetActiveHwnd() to get the active hwnd
UnPinWindow(activeHwnd)
return

Escape::ExitApp

Usefull ideas to use this library:

  • Go to the next/prev desktop when the mouse touches the left/right side of the screen(if you want this to not work inside games use the function IsFullScreenMode())
  • Move a window to the next/prev desktop when dragged to the left/right side of the screen, and to snap them to the sides use Microsoft PowerToys(in Youtube there's demos of PowerToys)
  • When you go to another desktop and everything is minimized automaticaly focus the last minimized window with this function AltTabOnSwitch(True)Function in this table
  • Have your favourite programs open always in the desktops you want(no matter how you open them) with the Function in this table
  • Pressing a key and moving the mouse to one corner will DesktopManager()Function in this table
  • XButton2(also called 5th mouse button or button foward in the mouse) to FocusLastWindow()(Function in this table) without sending the keystroke alt+tab

If you have any usefull way you use this library and is not in this list, please open an isue and tell me so i add it to this list, that way i hope between everyone we get a good list
I also put only original ideas, pressing 1,2,3 to go to desktop 1,2,3 its not going to be here PLEASE: if you do the code of any of this ideas, show me your repo so I can link it here or so we/I can use it, thanks!

Credits:

I want to thank Ciantic(Jari Pennanen) because he did the .dll that connects to Windows, thats black magic for me, so thanks
Ciantic: https://github.com/Ciantic/VirtualDesktopAccessor

Thanks to lschwahn because he did a complex program and I took ideas from his code
lschwahn: https://github.com/lschwahn/win-10-virtual-desktop-enhancer

As a newbie I couldn't find something easy to use, something ready to go, something with documentation, so here it is, I also added more than 20 of my own functions

Credits to Fanatic Guru for the [Class] WinHook

Thanks SKAN for the function that copies to the clipboard

Also thanks to tom-bowles for a "bug fix" here, it was really usefull

Thanks to Icarus for half of the IsFullScreenMode() function here

GetAltTabList() took from here

Thanks to itzjakm for his idea of being able to pick a random image from a folder to set it as a wallpaper

And thanks to the ahk community

GTD:

-I have to create a function called AlwaysStayWindowOnDesktop(desktop, exe), because the windows move by themselves sometimes from one dektop to another, all thanks to a low level bug on windows

-read the code and fix documented irrelevant bugs