HEAVILY VIBE-CODED : This is effectively the only part of this project written by a human. I hope no one reading this would blame me for not wanting to port undocumented COM code to c++ considering their unsupported nature. You can find the autohotkey library used as "motivation" (the claude prompt) here.
A C++ port of the AutoHotkey VD.ahk Windows Virtual Desktop library. It
drives the same undocumented IVirtualDesktopManagerInternal / IVirtualDesktop
/ IVirtualDesktopPinnedApps COM interfaces, using the same runtime
build-detection + manual vtable-index technique (these interfaces have no
public header and their method order changes across Windows builds, so a
static C++ interface declaration can't work here — each call goes through
vtable[index], matching what the original script does with DllCall).
VirtualDesktop.h/VirtualDesktop.cpp— the library.example.cpp,CMakeLists.txt— a minimal demo/build.
Windows only, needs a recent Windows SDK (for shobjidl.h's IObjectArray
and servprov.h's IServiceProvider).
cmake -B build -A x64
cmake --build build --config Release
Or add VirtualDesktop.h/.cpp to any MSVC/MinGW project and link
ole32, user32, shlwapi, version.
#include "VirtualDesktop.h"
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
vd::VirtualDesktopManager vdm;
if (vdm.IsValid()) {
int n = vdm.GetCount();
vdm.GoToDesktopNumber(2);
vdm.MoveWindowToDesktopNumber(L"Notepad", 1);
}| VD.ahk | C++ |
|---|---|
VD.getCurrentDesktopNum() |
GetCurrentDesktopNumber() |
VD.getDesktopNumOfWindow(wintitle) |
GetDesktopNumberOfWindow(title) / (HWND) |
VD.getCount() |
GetCount() |
VD.getRelativeDesktopNum(anchor, n) |
GetRelativeDesktopNumber(anchor, n) |
VD.goToDesktopNum(n) |
GoToDesktopNumber(n, activate=true) |
VD.goToDesktopOfWindow(wintitle) |
GoToDesktopOfWindow(title) |
VD.gotoRelativeDesktopNum(n) |
GoToRelativeDesktopNumber(n) |
VD.MoveWindowToDesktopNum(wintitle, n) |
MoveWindowToDesktopNumber(title, n) |
VD.MoveWindowToCurrentDesktop(wintitle) |
MoveWindowToCurrentDesktop(title) |
VD.MoveWindowToRelativeDesktopNum(wintitle, n) |
MoveWindowToRelativeDesktopNumber(title, n) |
VD.createDesktop() / createUntil() |
CreateDesktop() / CreateUntil() |
VD.removeDesktop(n) |
RemoveDesktop(n) |
VD.IsWindowPinned / TogglePinWindow / PinWindow / UnPinWindow |
same names, *Window(title) |
VD.IsAppPinned / TogglePinApp / PinApp / UnPinApp (by exe path) |
IsAppPinned/PinApp/UnpinApp/TogglePinApp(exePath) |
| same, but by window title (as used in VD.ahk's examples) | *ByWindow(title) variants |
getNameFromDesktopNum / setNameToDesktopNum are also ported
(GetNameFromDesktopNumber / SetNameToDesktopNumber), even though they're
only in VD.ahk's comments, not its "public API" header block.
- No event/notification support.
RegisterDesktopNotificationsand theVirtualDesktopCreated/CurrentVirtualDesktopChanged/ etc. callbacks are not ported (they require implementing a full COMIVirtualDesktopNotificationsink with per-build vtables — out of scope here). Only the request/response API is included. - No wallpaper get/set (
getWallpaperFromDesktopNum/setWallpaperToDesktopNum) — not part of VD.ahk's documented public API. - Simplified switch animation. VD.ahk works around older Windows
versions lacking a native animated switch by briefly moving an invisible
GUI window to the target desktop via the public
IVirtualDesktopManagerinterface as a trick to trigger the OS's built-in switch animation. This port skips that trick: it uses the nativeSwitchDesktopWithAnimationmethod when the OS provides one (Windows 11 23H2+), and a plain (non-animated) switch otherwise. Desktop-arrival detection and window-activation-on-arrival are preserved. - Window matching mirrors AHK's
SetTitleMatchMode 2+DetectHiddenWindows Onsemantics (case-insensitive substring match over all top-level windows, including hidden ones).
Same 7 build ranges as VD.ahk: 17763.1+, 20348.2227+, 22000.51+,
22483.1000+/22621.1778+, 22621.2215+/22483(rev), 22631.3085+, and
26100.863+ (Windows 11 24H2+). Detected via twinui.pcshell.dll's file
version, exactly like the original script.