How to call a Win32 API with UUID [IVirtualDesktopManager]

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
oliverlipkau
Posts: 9
Joined: 16 Jun 2015, 06:40
Contact:

How to call a Win32 API with UUID [IVirtualDesktopManager]

17 Aug 2018, 08:33

Hey.

I am looking into how to manage windows on multiple virtual desktops.
I found this API: https://docs.microsoft.com/en-us/window ... wdesktopid

But I am not that experienced with `DllCall()`.
How would I use this API in an AHK script?

Thank you
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: How to call a Win32 API with UUID [IVirtualDesktopManager] [IVirtualDesktopManagerInternal]

17 Aug 2018, 09:57

Code: Select all

; IVirtualDesktopManager interface
; https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager
IVirtualDesktopManager          := ComObjCreate("{AA509086-5CA9-4C25-8F95-589D3C07B48A}", "{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}")
IsWindowOnCurrentVirtualDesktop := NumGet(NumGet(IVirtualDesktopManager+0)+3*A_PtrSize)
GetWindowDesktopId              := NumGet(NumGet(IVirtualDesktopManager+0)+4*A_PtrSize)
MoveWindowToDesktop             := NumGet(NumGet(IVirtualDesktopManager+0)+5*A_PtrSize)

/*
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}")
GetCount                       := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+3*A_PtrSize)
MoveViewDesktop                := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+4*A_PtrSize)
CanViewMoveDesktops            := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+5*A_PtrSize)
GetCurrentDesktop              := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+6*A_PtrSize)
GetDesktops                    := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+7*A_PtrSize)
GetAdjacentDesktop             := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+8*A_PtrSize)
SwitchDesktop                  := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+9*A_PtrSize)
CreateDesktopW                 := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+10*A_PtrSize)
RemoveDesktop                  := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+11*A_PtrSize)
FindDesktop                    := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+12*A_PtrSize)
*/

; IVirtualDesktopManager::GetWindowDesktopId method
; https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nf-shobjidl_core-ivirtualdesktopmanager-getwindowdesktopid
TopLevelWindow := WinExist("A")
VarSetCapacity(GUID, 16)
R := DllCall(GetWindowDesktopId, "UPtr", IVirtualDesktopManager, "Ptr", TopLevelWindow, "UPtr", &GUID, "UInt")
if ( !R )   ; OK
{
    VarSetCapacity(strGUID, (38 + 1) * 2)
    DllCall("Ole32.dll\StringFromGUID2", "UPtr", &GUID, "UPtr", &strGUID, "Int", 38 + 1)
    MsgBox % "Identifier for the virtual desktop hosting the topLevelWindow`n" . StrGet(&strGUID, "UTF-16")
}
ExitApp
oliverlipkau
Posts: 9
Joined: 16 Jun 2015, 06:40
Contact:

Re: How to call a Win32 API with UUID [IVirtualDesktopManager]

18 Aug 2018, 06:14

@Flipeador

could you show me how to use the parts you have commented out, such as "GetDesktops"?
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: How to call a Win32 API with UUID [IVirtualDesktopManager]

18 Aug 2018, 08:09

The IVirtualDesktopManagerInternal interface is not officially documented by Microsoft, it could stop working in any Windows update!.

Code: Select all

; IVirtualDesktopManager interface
; https://docs.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-ivirtualdesktopmanager
IVirtualDesktopManager          := ComObjCreate("{AA509086-5CA9-4C25-8F95-589D3C07B48A}", "{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}")
IsWindowOnCurrentVirtualDesktop := NumGet(NumGet(IVirtualDesktopManager+0)+3*A_PtrSize)
GetWindowDesktopId              := NumGet(NumGet(IVirtualDesktopManager+0)+4*A_PtrSize)
MoveWindowToDesktop             := NumGet(NumGet(IVirtualDesktopManager+0)+5*A_PtrSize)

; internal interface IVirtualDesktopManagerInternal14328
; https://sourceforge.net/p/virtual-desktop-grid-switcher/src/ci/d85ff70ced929d161bd45d10a47ebb0c0f2a1f68/tree/VirtualDesktop-master/source/VirtualDesktop/Interop/IVirtualDesktopManagerInternal.cs#l71
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}")
GetCount                       := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+3*A_PtrSize)
MoveViewDesktop                := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+4*A_PtrSize)
CanViewMoveDesktops            := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+5*A_PtrSize)
GetCurrentDesktop              := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+6*A_PtrSize)
GetDesktops                    := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+7*A_PtrSize)
GetAdjacentDesktop             := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+8*A_PtrSize)
SwitchDesktop                  := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+9*A_PtrSize)
CreateDesktopW                 := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+10*A_PtrSize)
RemoveDesktop                  := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+11*A_PtrSize)
FindDesktop                    := NumGet(NumGet(IVirtualDesktopManagerInternal+0)+12*A_PtrSize)

; IVirtualDesktopManagerInternal::GetDesktops method
IObjectArray := 0
DllCall(GetDesktops, "UPtr", IVirtualDesktopManagerInternal, "UPtrP", IObjectArray, "UInt")

; IObjectArray::GetCount method
; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getcount
Count := 0
DllCall(NumGet(NumGet(IObjectArray+0)+3*A_PtrSize), "UPtr", IObjectArray, "UIntP", Count, "UInt")

VarSetCapacity(strGUID, (38 + 1) * 2)
VarSetCapacity(GUID, 16)

IVirtualDesktop := 0
Loop % (Count)
{
    ; https://github.com/nullpo-head/Windows-10-Virtual-Desktop-Switching-Shortcut/blob/master/VirtualDesktopSwitcher/VirtualDesktopSwitcher/VirtualDesktops.h
    DllCall("Ole32.dll\CLSIDFromString", "Str", "{FF72FFDD-BE7E-43FC-9C03-AD81681E88E4}", "UPtr", &GUID)

    ; IObjectArray::GetAt method
    ; https://docs.microsoft.com/en-us/windows/desktop/api/objectarray/nf-objectarray-iobjectarray-getat
    DllCall(NumGet(NumGet(IObjectArray+0)+4*A_PtrSize), "UPtr", IObjectArray, "UInt", A_Index-1, "UPtr", &GUID, "UPtrP", IVirtualDesktop, "UInt")

    ; IVirtualDesktop::GetID method
    DllCall(NumGet(NumGet(IVirtualDesktop+0)+4*A_PtrSize), "UPtr", IVirtualDesktop, "UPtr", &GUID, "UInt")
    DllCall("Ole32.dll\StringFromGUID2", "UPtr", &GUID, "UPtr", &strGUID, "Int", 38 + 1)
    MsgBox % StrGet(&strGUID, "UTF-16")
}
As there is nothing documented, it is not easy to guess how it works, what are you trying to do?. I guess that number at the end of IVirtualDesktopManagerInternal has something to do with the Windows version (IVirtualDesktopManagerInternal14328).
oliverlipkau
Posts: 9
Joined: 16 Jun 2015, 06:40
Contact:

Re: How to call a Win32 API with UUID [IVirtualDesktopManager]

18 Aug 2018, 10:14

I am trying to write a script where I can record a state of what window/program goes on what VD.
And when I (re)boot, it will reconstruct that setup - instead of me having to move windows to other VDs.

I found this script which reads the UUIDs of the VDs from the registry.
https://github.com/pmb6tz/windows-deskt ... hk#L24-L49
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: How to call a Win32 API with UUID [IVirtualDesktopManager]

18 Aug 2018, 10:27

Yes, reading from the registry and using the Send command is the most "simple" way to do it. The correct (and serious) way to do it would be with DllCall, the only problem, as I mentioned, is that it could stop working with future Windows updates (nothing that we can not solve).

I'll see what I can do.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: How to call a Win32 API with UUID [IVirtualDesktopManager]

18 Aug 2018, 12:27

I have tried to use MoveWindowToDesktop but it does not work with the windows of other processes, it only works with the windows of your script. Maybe it can work by hooking or inject a DLL, but things get too complicated (this would take work). When you try to call the method, it returns 0x80070005 (E_ACCESSDENIED).

Links of interest:
https://stackoverflow.com/questions/318 ... l-desktops
https://github.com/Grabacr07/SylphyHorn
https://github.com/Eun/MoveToDesktop
https://github.com/tmyt/VDMHelper
https://autohotkey.com/boards/viewtopic.php?t=5571

Honestly I can not think of any simple way to move a window to another virtual desktop. Maybe someone who has experience injecting code into another process can help you. If I find any way I will let you know.
char101
Posts: 11
Joined: 10 Mar 2017, 04:15

Re: How to call a Win32 API with UUID [IVirtualDesktopManager]

23 Feb 2019, 22:42

I had written a script to move windows between virtual desktops using the function MoveWindowToDesktopNumberProc from https://github.com/Ciantic/VirtualDesktopAccessor/

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: imstupidpleshelp, jaka1, OrangeCat and 156 guests